<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><atom:link href="https://mccue.dev" rel="self" type="application/rss+xml"/><title>mccue.dev</title><link>https://mccue.dev</link><description></description><generator>clj-rss</generator><item><title>I want to want the Facebook Pervert Glasses</title><link>https://mccue.dev/pages/7-2-26-meta-glasses</link><description></description><pubDate>Thu, 02 Jul 0026 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>I want to want the Facebook Pervert Glasses</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">I want to want the Facebook Pervert Glasses</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
I was in the marching band in High School. If you know me, that should track.

<p>Part of being in a marching band is memorizing where you need to go on the field and when. We would have a week-long bootcamp before school started where we would drill that and the songs into our heads.</p>
<p>At the time, Google Glass was just coming out. I couldn't help but dream that we could all just put on a pair of those and get real time waypoints like in an FPS. Sure, we'd all look like dorks, but whatever. You play enough Halo, and you'll start to wish you had a HUD too.</p>
<p>Google Glass never took off. I never even got to try it. But recently Facebook launched a similar product, their Pervert Glasses Display.</p>
<p>I had to drive an hour to a BestBuy in New Hampshire to demo them and, if I ever wore them in public, I would be cruisin' for a bruisin'. Still, two things would tempt me.</p>
<ol type="1">
<li>Real-life waypoints. I want a HUD. I want to look off in the sky and see a beacon telling me where I need to go.</li>
<li>A real-life dash-cam. I want to be able to go "clip that" and capture the last 60 seconds of whatever I just saw. I see some shit.</li>
</ol>
<p>But alas, the product sucks.</p>
<p>You cannot make your own apps for the thing, so you are limited to whatever Facebook has made. This includes Instagram, WhatsApp, Facebook, ... all chat apps. Really putting hats on hats.</p>
<p>There is a Maps app, but it just shows a normal map. You could just hold your phone up to your face and get the same experience.</p>
<p>There were some...games? Even the person demoing it said they basically just use theirs as a mic for Discord.</p>
<p>To top it all off, the thing gives me a headache. It is really hard to look at anything on the display part without closing one eye. Add that to all the normal horse excrement like needing to log in, connect with your phone, or the battery not even lasting a full day and yeah. Huge bummer.</p>
<p>The control doohickey that senses your finger movements was legitimately fun though. I would want that as an input device for a lot of things, not that it will be an option.</p>
<p>Maybe SnapChat's Pervert Glasses will be better. I'll have to try a pair before that company dies.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>50 out of 413 Companies that use my libraries</title><link>https://mccue.dev/pages/6-27-26-who-uses</link><description></description><pubDate>Sat, 27 Jun 0026 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>50 out of 413 Companies that use my libraries</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">50 out of 413 Companies that use my libraries</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
Maven Central gives a stats page to publishers of libraries telling them roughly how many downloads their libraries
get.

<p><img src="./6-26-26-central.png"></img></p>
<p>But if you want to know more specific info, say "which of my libraries gets the most downloads," they point you to a separate service called "Scarf."</p>
<p><img src="./6-26-26-scarf-cta.png"></img></p>
<p>And wow, that is neat. A lot of people use my repackaged guava (which whatever), but actually I get quite a few downloads on my JSON library. Nowhere near Jackson, but I choose to be happy about it. Really wish I could see the rest though.</p>
<p><img src="./6-26-26-dls.png"></img></p>
<p>And it makes sense that most of my users are in the US, but I am taken aback by how much of the globe I've touched.</p>
<p>A bit of a bummer that I only get to see the last 3 months, I wonder if I hit everywhere at least once.</p>
<p><img src="./6-26-26-globe.png"></img></p>
<p>But hey what the fuck is this?</p>
<p><img src="./6-26-26-companies.png"></img></p>
<p>So okay clearly behind the scenes they have some way to guess at which companies are the ones initiating a download for a library. Probably no more complicated than having some known IP addresses of them. That isn't what shocks me.</p>
<p>What shocks me is both that they gate this information and the price they demand for access.</p>
<p>So as whatever user tier I am I get "50 free unlock credits". Meaning of the large corporations that use the libraries I publish I can see exactly 50.</p>
<p><img src="./6-26-26-company-unlocks.png"></img></p>
<p>To get 250 unlocks, which isn't even the whole list for me, I would have to pay them <strong>$1350 a month</strong>.</p>
<p><img src="./6-26-26-1350.png"></img></p>
<p>Well, not really. That is just what they show as the default. I can tune the "runs" number down to <code>1</code> and the "company unlocks" to exactly <code>413</code> and then it is only <strong>$1076.60 a month</strong>.</p>
<p><img src="./6-26-26-unlocks-1.png"></img></p>
<p>And I could go into all the other pricing options, but I think you get the picture. That's more than a car payment and only a little less than a Github Copilot subscription.</p>
<p>Clearly they are <em>able</em> to gatekeep it. Sonatype sold them IPs of downloads and they have a dataset mapping IPs to companies. Neither of those are public so they get to put a price on it.</p>
<p>But the only reason people would pay a price is that the information has value. If an author knows exactly who is consuming their open source libraries that gives them leverage. They can go to these companies and say "Hey, I am in your supply chain."</p>
<p>If you have been following me the last few months you'll know I have been working on a repository scheme of my own. Making it such that information like "Company A depends on David Smith of Lansing Michigan" is not gatekept has now moved way up my priorities list.</p>
<p>Because fuck this, fuck Scarf.</p>
<table>
<thead>
<tr class="header">
<th>company_name</th>
<th>company_size</th>
<th>company_country</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>UiPath</td>
<td>1,000 - 4,999</td>
<td>Brazil</td>
</tr>
<tr class="even">
<td>SAP</td>
<td>10,000</td>
<td>Hungary</td>
</tr>
<tr class="odd">
<td>IBM</td>
<td>100K+</td>
<td>United States</td>
</tr>
<tr class="even">
<td>Cloudinary</td>
<td>251-1K</td>
<td>Israel</td>
</tr>
<tr class="odd">
<td>Segment</td>
<td>1,000 - 4,999</td>
<td>India</td>
</tr>
<tr class="even">
<td>Citrix</td>
<td>5K-10K</td>
<td>United States</td>
</tr>
<tr class="odd">
<td>Apple</td>
<td>10,000</td>
<td>United States</td>
</tr>
<tr class="even">
<td>Microsoft</td>
<td>10,000</td>
<td>Switzerland</td>
</tr>
<tr class="odd">
<td>Copart</td>
<td>5K-10K</td>
<td>United States</td>
</tr>
<tr class="even">
<td>Critical TechWorks</td>
<td>1K-5K</td>
<td>Portugal</td>
</tr>
<tr class="odd">
<td>Motive</td>
<td>1,000 - 4,999</td>
<td>United States</td>
</tr>
<tr class="even">
<td>Google</td>
<td>100K+</td>
<td>United States</td>
</tr>
<tr class="odd">
<td>ICF</td>
<td>5K-10K</td>
<td>United States</td>
</tr>
<tr class="even">
<td>Cisco</td>
<td>10,000</td>
<td>United Kingdom</td>
</tr>
<tr class="odd">
<td>Alation</td>
<td>500 - 999</td>
<td>United States</td>
</tr>
<tr class="even">
<td>Comcast</td>
<td>100K+</td>
<td>United States</td>
</tr>
<tr class="odd">
<td>Gazprombank</td>
<td>10K-50K</td>
<td>Russia</td>
</tr>
<tr class="even">
<td>Twitter</td>
<td>5K-10K</td>
<td>United States</td>
</tr>
<tr class="odd">
<td>NCR Voyix</td>
<td>10K-50K</td>
<td>United States</td>
</tr>
<tr class="even">
<td>JPMorgan Chase</td>
<td>100K+</td>
<td>United States</td>
</tr>
<tr class="odd">
<td>Rockwell Automation</td>
<td>10,000</td>
<td>United States</td>
</tr>
<tr class="even">
<td>Duncan Aviation</td>
<td>1K-5K</td>
<td>United States</td>
</tr>
<tr class="odd">
<td>Productboard</td>
<td>250 - 499</td>
<td>United States</td>
</tr>
<tr class="even">
<td>Adobe</td>
<td>10,000</td>
<td>France</td>
</tr>
<tr class="odd">
<td>Boeing</td>
<td>10,000</td>
<td>Australia</td>
</tr>
<tr class="even">
<td>Neo4j</td>
<td>500 - 999</td>
<td>United States</td>
</tr>
<tr class="odd">
<td>RTX Corporation</td>
<td>10,000</td>
<td>Singapore</td>
</tr>
<tr class="even">
<td>Mastercard</td>
<td>10K-50K</td>
<td>United States</td>
</tr>
<tr class="odd">
<td>Baker Hughes</td>
<td>50K-100K</td>
<td>United States</td>
</tr>
<tr class="even">
<td>Halliburton</td>
<td>10K-50K</td>
<td>United States</td>
</tr>
<tr class="odd">
<td>Parker Hannifin</td>
<td>10,000</td>
<td>United States</td>
</tr>
<tr class="even">
<td>Disney</td>
<td>10,000</td>
<td>United States</td>
</tr>
<tr class="odd">
<td>Cvent</td>
<td>5,000 - 9,999</td>
<td>Singapore</td>
</tr>
<tr class="even">
<td>JD.com</td>
<td>100K+</td>
<td>China</td>
</tr>
<tr class="odd">
<td>Edelman</td>
<td>5K-10K</td>
<td>United States</td>
</tr>
<tr class="even">
<td>FEMA &amp; Keller Williams</td>
<td>100K+</td>
<td>United States</td>
</tr>
<tr class="odd">
<td>Nokia</td>
<td>10,000</td>
<td>Finland</td>
</tr>
<tr class="even">
<td>HCA Healthcare</td>
<td>10,000</td>
<td>United States</td>
</tr>
<tr class="odd">
<td>Bosch</td>
<td>10,000</td>
<td>France</td>
</tr>
<tr class="even">
<td>Tech Mahindra</td>
<td>10,000</td>
<td>India</td>
</tr>
<tr class="odd">
<td>Kum &amp; Go</td>
<td>10,000</td>
<td>United States</td>
</tr>
<tr class="even">
<td>PwC</td>
<td>100K+</td>
<td>United Kingdom</td>
</tr>
<tr class="odd">
<td>Ericsson</td>
<td>10,000</td>
<td>United States</td>
</tr>
<tr class="even">
<td>Itau Unibanco</td>
<td>10,000</td>
<td>Brazil</td>
</tr>
<tr class="odd">
<td>Calendly</td>
<td>251-1K</td>
<td>United States</td>
</tr>
<tr class="even">
<td>International Bank Of Azerbaijan</td>
<td>1K-5K</td>
<td>Azerbaijan</td>
</tr>
<tr class="odd">
<td>Nielsen</td>
<td>10K-50K</td>
<td>United States</td>
</tr>
<tr class="even">
<td>Snyk</td>
<td>1,000 - 4,999</td>
<td>United States</td>
</tr>
<tr class="odd">
<td>Imagine Apps</td>
<td>51-250</td>
<td>Colombia</td>
</tr>
</tbody>
</table>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>People Hate AI Art</title><link>https://mccue.dev/pages/5-8-26-ai-art</link><description></description><pubDate>Fri, 08 May 0026 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>People Hate AI Art</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">People Hate AI Art</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
There's a vivid mental image I have in my head of a T-Rex giving a thumbs up.

<p>So I had ChatGPT generate that for me.</p>
<p><img src="/pages/5-8-26-dinosaur-ai.png"></img></p>
<p>If your initial reaction to reading that and seeing that is some variation of "ughhh" or rolling your eyes or "fuck this guy" congrats. You are normal.</p>
<p>If it wasn't I cannot stress to you enough that you are an outlier. Whenever you pick key art for a presentation or blog, your business, or whatever - if you use AI art you give a clear signal that you have low social literacy. You immediately associate yourself with a huge bundle of negative emotions because people, largely, <a href="https://www.youtube.com/watch?v=DGjj7wDYaiI">hate this shit</a>.</p>
<p>The game theory on this is astoundingly clear. The best case scenario is that your audience doesn't mind. The worst, and common-case, scenario is that they think less of you. Nobody sane looks at that and goes "wow, they must have spent such a long time prompting."</p>
<p>Here are some easy alternatives.</p>
<h2 id="alternative-1-lazy-photoshop">Alternative 1: Lazy photoshop</h2>
<p>Here I've taken a photo of a T-Rex from the Jurassic Park Wiki and used <a href="https://jspaint.app"><a href="https://jspaint.app">https://jspaint.app</a></a> to very poorly edit on a thumbs up emoji.</p>
<p><img src="/pages/5-8-26-dinosaur-mspaint.png"></img></p>
<p>I'm sure I could have found a public domain rendering of a dinosaur, but if we cared about intellectual property AI wouldn't be on the table regardless.</p>
<p>And again to stress the point - people will look upon this much more favorably.</p>
<h2 id="alternative-2-doodle">Alternative 2: Doodle</h2>
<p>This one speaks for itself. Pull out your colored pencils, your markers, your watercolors. Draw something, and take a photo with your phone.</p>
<p><img src="/pages/5-8-26-dinosaur-doodle.png"></img></p>
<p>Now I drew this one, but do you comprehend how much it improves people's perception of you if you can say "my 6-year-old niece drew this?" If you have access to a child make use of that.</p>
<h2 id="alternative-3-commission-art">Alternative 3: Commission Art</h2>
<p>I write about software, I post in software spaces. I must assume that some significant fraction of those reading this are software professionals.</p>
<p>Do you have any idea how negatively it reflects on you as a person if you have a six-figure job but won't shell out some cash to a starving artist?</p>
<p>I commissioned <a href="https://bsky.app/profile/dsoart.com"><a href="https://bsky.app/profile/dsoart.com">https://bsky.app/profile/dsoart.com</a></a> for this one, and I am more than pleased. You can too. Or any number of relatively affordable professionals.</p>
<p><img src="/pages/5-8-26-dinosaur-comm.png"></img></p>
<h2 id="alternative-4-be-a-grifter">Alternative 4: Be a grifter</h2>
<p>People with minor cases of major brain damage. Those who have drunk too long from the leaden hose of LinkedIn. The kind of person who was really into NFTs in 2022. These people make perfect marks.</p>
<p>Using AI images is an effective way to filter out people with critical thinking skills. If you are running a grift it can be a valuable piece of your toolkit. Much like your classic "Nigerian prince" scams, the kind of people who see that junk and still engage are your most cash of cows.</p>
<p>If that's what you want to do, if that's who you want to be - godspeed, loser.</p>
<p><img src="/pages/5-8-26-dinosaur-infowars.png"></img></p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>A Brisk Introduction to Linked Lists and Binary Search Trees</title><link>https://mccue.dev/pages/3-19-26-ll-and-bst</link><description></description><pubDate>Thu, 19 Mar 0026 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>A Brisk Introduction to Linked Lists and Binary Search Trees</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">A Brisk Introduction to Linked Lists and Binary Search Trees</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
## Linked Lists

<p>A linked list is either</p>
<ul>
<li>An empty list</li>
<li>A "not empty" list, which has a "head" and a "tail"</li>
</ul>
<p>In Java we can represent this situation using a "sealed interface."</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co">// A linked list is either empty or not empty.</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> <span class="bu">LinkedList</span><span class="op">&lt;</span>T<span class="op">&gt;</span> </span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    permits Empty<span class="op">,</span> <span class="bu">NotEmpty</span> <span class="op">{}</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>record Empty<span class="op">&lt;</span>T<span class="op">&gt;()</span> <span class="kw">implements</span> <span class="bu">LinkedList</span><span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">{}</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>record <span class="bu">NotEmpty</span><span class="op">&lt;</span>T<span class="op">&gt;(</span>T first<span class="op">,</span> <span class="bu">LinkedList</span><span class="op">&lt;</span>T<span class="op">&gt;</span> rest<span class="op">)</span> <span class="op">{}</span></span></code></pre></div>
<p>To define operations on a linked list we need to define their operation on the "empty" and "not empty" cases.</p>
<p>The size of an empty list is 0.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> <span class="fu">size</span><span class="op">(</span><span class="bu">LinkedList</span><span class="op">&lt;?&gt;</span> ll<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="cf">switch</span> <span class="op">(</span>ll<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">case</span> <span class="fu">Empty</span><span class="op">()</span> <span class="op">-&gt;</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And the size of a not empty list is 1 + the size of the rest of the list.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> <span class="fu">size</span><span class="op">(</span><span class="bu">LinkedList</span><span class="op">&lt;?&gt;</span> ll<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="cf">switch</span> <span class="op">(</span>ll<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">case</span> <span class="fu">Empty</span><span class="op">()</span> <span class="op">-&gt;</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>        <span class="cf">case</span> <span class="bu">NotEmpty</span><span class="op">(</span>_<span class="op">,</span> var rest<span class="op">)</span> <span class="op">-&gt;</span> <span class="dv">1</span> <span class="op">+</span> <span class="fu">size</span><span class="op">(</span>rest<span class="op">);</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>To "map" a function on each element in the list works very similarly.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>T<span class="op">,</span> R<span class="op">&gt;</span> <span class="bu">LinkedList</span><span class="op">&lt;</span>R<span class="op">&gt;</span> <span class="fu">map</span><span class="op">(</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>        <span class="bu">LinkedList</span><span class="op">&lt;</span>T<span class="op">&gt;</span> ll<span class="op">,</span> </span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>        Function<span class="op">&lt;?</span> <span class="kw">super</span> T<span class="op">,</span> <span class="op">?</span> <span class="kw">extends</span> R<span class="op">&gt;</span> f</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="cf">switch</span> <span class="op">(</span>ll<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">case</span> <span class="fu">Empty</span><span class="op">()</span> <span class="op">-&gt;</span> <span class="kw">new</span> <span class="fu">Empty</span><span class="op">();</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">case</span> <span class="bu">NotEmpty</span><span class="op">(</span>var first<span class="op">,</span> var rest<span class="op">)</span> <span class="op">-&gt;</span> <span class="kw">new</span> <span class="bu">NotEmpty</span><span class="op">(</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>                f<span class="op">.</span><span class="fu">apply</span><span class="op">(</span>first<span class="op">),</span> </span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>                <span class="fu">map</span><span class="op">(</span>rest<span class="op">,</span> f<span class="op">)</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>As does every operation you might want to define. The recursive structure of the list itself is your guide for implementing operations on it.</p>
<h2 id="binary-search-trees">Binary Search Trees</h2>
<p>A tree is either</p>
<ul>
<li>A leaf node, holding no data</li>
<li>A branch node, holding a value as well as a subtree to its left and right</li>
</ul>
<p>In Java we can represent this situation using a "sealed interface."</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="co">// A tree is either a leaf or a branch.</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> BST<span class="op">&lt;</span>T<span class="op">&gt;</span> </span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    permits Leaf<span class="op">,</span> Branch <span class="op">{}</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>record Leaf<span class="op">&lt;</span>T<span class="op">&gt;()</span> <span class="kw">implements</span> BST<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">{}</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>record Branch<span class="op">&lt;</span>T<span class="op">&gt;(</span>BST<span class="op">&lt;</span>T<span class="op">&gt;</span> left<span class="op">,</span> T value<span class="op">,</span> BST<span class="op">&lt;</span>T<span class="op">&gt;</span> right<span class="op">)</span> <span class="op">{}</span></span></code></pre></div>
<p>To insert a value into a BST we need to be careful to always properly order elements. If a branch has <code>5</code> and we try to insert <code>2</code> in the tree, the <code>2</code> should go to the "left" because it is less than <code>5</code>.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>T<span class="op">&gt;</span> BST<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="fu">insert</span><span class="op">(</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>        BST<span class="op">&lt;</span>T<span class="op">&gt;</span> bst<span class="op">,</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>        T value<span class="op">,</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Comparator</span><span class="op">&lt;?</span> <span class="kw">super</span> T<span class="op">&gt;</span> comparator</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="cf">switch</span> <span class="op">(</span>bst<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">case</span> <span class="fu">Leaf</span><span class="op">()</span> <span class="op">-&gt;</span> <span class="kw">new</span> <span class="fu">Branch</span><span class="op">(</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>                <span class="kw">new</span> <span class="fu">Leaf</span><span class="op">(),</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>                value<span class="op">,</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>                <span class="kw">new</span> <span class="fu">Leaf</span><span class="op">()</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>        <span class="cf">case</span> <span class="fu">Branch</span><span class="op">(</span>var left<span class="op">,</span> var v<span class="op">,</span> var right<span class="op">)</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>            <span class="dt">int</span> comparison <span class="op">=</span> comparator<span class="op">.</span><span class="fu">compare</span><span class="op">(</span>value<span class="op">,</span> v<span class="op">);</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>comparison <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a>                yield bst<span class="op">;</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a>            <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>comparison <span class="op">&gt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a>                yield <span class="kw">new</span> <span class="fu">Branch</span><span class="op">(</span></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a>                        left<span class="op">,</span></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a>                        v<span class="op">,</span></span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a>                        <span class="fu">insert</span><span class="op">(</span>right<span class="op">,</span> value<span class="op">,</span> comparator<span class="op">)</span></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a>                <span class="op">);</span></span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true" tabindex="-1"></a>            <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true" tabindex="-1"></a>                yield <span class="kw">new</span> <span class="fu">Branch</span><span class="op">(</span></span>
<span id="cb6-26"><a href="#cb6-26" aria-hidden="true" tabindex="-1"></a>                        <span class="fu">insert</span><span class="op">(</span>left<span class="op">,</span> value<span class="op">,</span> comparator<span class="op">),</span></span>
<span id="cb6-27"><a href="#cb6-27" aria-hidden="true" tabindex="-1"></a>                        v<span class="op">,</span></span>
<span id="cb6-28"><a href="#cb6-28" aria-hidden="true" tabindex="-1"></a>                        right</span>
<span id="cb6-29"><a href="#cb6-29" aria-hidden="true" tabindex="-1"></a>                <span class="op">);</span></span>
<span id="cb6-30"><a href="#cb6-30" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb6-31"><a href="#cb6-31" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb6-32"><a href="#cb6-32" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb6-33"><a href="#cb6-33" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This is the invariant that allows us to quickly search for values in such a structure. At every branch we can ignore at most half of the tree.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="dt">boolean</span> <span class="fu">contains</span><span class="op">(</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>        BST<span class="op">&lt;</span>T<span class="op">&gt;</span> bst<span class="op">,</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>        T value<span class="op">,</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Comparator</span><span class="op">&lt;?</span> <span class="kw">super</span> T<span class="op">&gt;</span> comparator</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="cf">switch</span> <span class="op">(</span>bst<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">case</span> <span class="fu">Leaf</span><span class="op">()</span> <span class="op">-&gt;</span> <span class="kw">false</span><span class="op">;</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>        <span class="cf">case</span> <span class="fu">Branch</span><span class="op">(</span>var left<span class="op">,</span> var v<span class="op">,</span> var right<span class="op">)</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>            <span class="dt">int</span> comparison <span class="op">=</span> comparator<span class="op">.</span><span class="fu">compare</span><span class="op">(</span>value<span class="op">,</span> v<span class="op">);</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>comparison <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>                yield <span class="kw">true</span><span class="op">;</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a>            <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>comparison <span class="op">&gt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a>                yield <span class="fu">contains</span><span class="op">(</span></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a>                        left<span class="op">,</span></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a>                        value<span class="op">,</span></span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true" tabindex="-1"></a>                        comparator</span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true" tabindex="-1"></a>                <span class="op">);</span></span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true" tabindex="-1"></a>            <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true" tabindex="-1"></a>                yield <span class="fu">contains</span><span class="op">(</span></span>
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true" tabindex="-1"></a>                        right<span class="op">,</span></span>
<span id="cb7-23"><a href="#cb7-23" aria-hidden="true" tabindex="-1"></a>                        value<span class="op">,</span></span>
<span id="cb7-24"><a href="#cb7-24" aria-hidden="true" tabindex="-1"></a>                        comparator</span>
<span id="cb7-25"><a href="#cb7-25" aria-hidden="true" tabindex="-1"></a>                <span class="op">);</span></span>
<span id="cb7-26"><a href="#cb7-26" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb7-27"><a href="#cb7-27" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb7-28"><a href="#cb7-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb7-29"><a href="#cb7-29" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<p>Now compare this explanation and whatever one you - the reader - were given in school. What are your thoughts?</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Python Only Has One Real Competitor</title><link>https://mccue.dev/pages/2-6-26-python-competitor</link><description></description><pubDate>Fri, 06 Feb 0026 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Python Only Has One Real Competitor</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Python Only Has One Real Competitor</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
Clickbait subtitle: "and it's not even close"

<hr />
<p><code>Python</code> is the undisputed monarch in exactly one domain: Data Science.</p>
<p>The story, as I understand it, goes something like this:</p>
<p><code>Python</code> has very straight-forward interop with native code. Because interop is straightforward, libraries like <code>numpy</code> and <code>pandas</code> got made. Around these an entire Data Science ecosystem bloomed.</p>
<p>This in turn gave rise to interactive notebooks with <code>iPython</code> (now "Jupyter"), plotting with <code>Matplotlib</code>, and machine learning with <code>PyTorch</code> and company.</p>
<p>There are other languages and platforms - like <code>R</code>, <code>MATLAB</code>, etc. - which compete for users with <code>Python</code>. If you have a field biologist out there wading through the muck to measure turtles, they will probably make their charts and papers with whatever they learned in school.</p>
<p>But the one glaring weakness of these competitors is that they are not general purpose languages. <code>Python</code> is. This means that <code>Python</code> is also widely used for other kinds of programs - such as HTTP servers.</p>
<p>So for the people who are training machine learning models to do things like classify spam it is easiest to then serve those models using the same language and libraries that were used to produce them. This can be done without much risk because you can assume <code>Python</code> will have things like, say, a <code>Kafka</code> library should you need it. You can't really say the same for <code>MATLAB</code>.</p>
<p>And in the rare circumstance you want to do something that is easiest in one of those alternative ecosystems, <code>Python</code> will have a binding. You can call <code>R</code> with <a href="https://rpy2.github.io/"><code>rpy2</code></a>, <a href="https://www.mathworks.com/products/matlab/matlab-and-python.html"><code>MATLAB</code> with another library</a>, <code>Spark</code> with <a href="https://spark.apache.org/docs/latest/api/python/index.html"><code>PySpark</code></a>, and so on.</p>
<p>For something to legitimately be a competitor to <code>Python</code> I think it needs to do two things.</p>
<ol type="1">
<li>Be at least as good at everything as <code>Python</code>.</li>
<li>Be better than <code>Python</code> in a way that matters.</li>
</ol>
<p>The only language which clears this bar is called <code>Clojure</code>.</p>
<p><img src="/pages/2-6-26-clojure-logo.png"
alt="Clojure Language Logo" ></img></p>
<hr />
<p>That's a bold claim, I know. Hear me out.</p>
<p><code>Clojure</code> has a rich ecosystem of Data Science libraries, including feature complete <code>numpy</code> and <code>pandas</code> equivalents in <a href="https://github.com/cnuernber/dtype-next"><code>dtype-next</code></a> and <a href="https://github.com/techascent/tech.ml.dataset"><code>tech.ml.dataset</code></a>. <a href="https://github.com/scicloj/metamorph.ml"><code>metamorph.ml</code></a> for Machine Learning pipelines, <a href="https://github.com/scicloj/tableplot"><code>Tableplot</code></a> for plotting, and <a href="https://github.com/scicloj/clay"><code>Clay</code></a> for interactive notebooks.</p>
<p>For what isn't covered it can call <code>Python</code> directly via <a href="https://github.com/clj-python/libpython-clj"><code>libpython-clj</code></a>, <code>R</code> via <a href="https://github.com/scicloj/clojisr">ClojisR</a>, and so on.</p>
<p><code>Clojure</code> is also a general purpose language. Making HTTP servers or whatever else in <code>Clojure</code> is very practical.</p>
<p>What starts to give <code>Clojure</code> the edge is also the answer to the age-old question: "Why is <code>Python</code> so slow?"</p>
<p><code>Python</code> is slow because it cannot be made fast. The dark side of <code>Python</code>'s easy interop with native code is that many of the implementation details of <code>CPython</code> were made visible to, and relied upon by, authors of native bindings.</p>
<p>Because all these details were relied upon, the authors of the <code>CPython</code> runtime can't really change those details and not break the entire Data Science ecosystem. This heavily constrains the optimizations that the <code>CPython</code> runtime can do.</p>
<p>This means that people need to constantly avoid writing CPU intensive code in <code>Python</code>. It is orders of magnitude faster to use something which delegates to the native world than something written in pure <code>Python</code>. This affects the experience of things like <code>numpy</code> and <code>pandas</code>. There is often a "fast way" to do something and several "slow ways." The slow ways are always when too much actual <code>Python</code> code gets involved in the work.</p>
<p><code>Clojure</code> does not have this problem. <code>Clojure</code> is a language that runs on the Java Virtual Machine. The JVM can optimize code like crazy on account of all the souls sacrificed to it. So you can write real logic in <code>Clojure</code> no issue.</p>
<p>There's a reason <code>Python</code>'s list is implemented in <code>C</code> code but <code>Java</code> can have multiple competing implementations, all written in <code>Java</code>. <code>Java</code> code can count on some aggressive runtime optimizations when it matters.</p>
<p>This also means that if you use <code>Clojure</code> for something like an HTTP Server to serve a model, you can generally expect much better performance at scale than the equivalent in <code>Python</code>. You could even write that part in pure <code>Java</code> to make use of that trained pool of developers. Anecdotally, startups often switch from whatever language they started with to something that runs on the JVM once they get big enough to care about performance.</p>
<p><code>Clojure</code>'s library ecosystem includes many high quality libraries written in <code>Java</code>. Many of these are better performing than their <code>Python</code> analogues. Many also do things for which <code>Python</code> has no equivalent. <code>Clojure</code> then gets access to all <code>Python</code> libraries via <a href="https://github.com/clj-python/libpython-clj"><code>libpython-clj</code></a>.</p>
<p><code>Clojure</code>'s interop story is also quite strong at the language level. Calling a <code>Python</code> function is almost as little friction linguistically as calling a <code>Clojure</code> function. Calling native code with <a href="https://github.com/IGJoshua/coffi">coffi</a> is also pretty darn simple.</p>
<p>The language is also very small even compared to <code>Python</code>. Obviously the education system infrastructure is not in place, but in principle there is less to learn about the language itself before one can productively learn how to do Data Science.</p>
<p>An extremely important part of productive Data Science work is interacting with a dataset. This is why interactive notebooks are such a big part of this world. It's also a benefit of using dynamic languages like <code>Python</code> and <code>Clojure</code>. Being able to run quick experiments and poke at data is more important than static type information.</p>
<p><code>Clojure</code> is part of a family of languages with a unique method of interactive development. This method is considered by its fans to be superior to the cell-based notebooks that <code>Jupyter</code> provides.</p>
<p>All in all, it's a competitive package. Whether it ever gets big enough to take a big bite of <code>Python</code> comes down to kismet, but I think it's the only thing that might stand a chance to.</p>
<hr />
<p>If this got you interested in learning <code>Clojure</code> check out <a href="https://clojure.camp/">Clojure Camp</a> for resources and <a href="https://scicloj.github.io/noj/">noj</a> for a cohesive introduction to the Data Science ecosystem.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>public static void main(String[] args) is dead</title><link>https://mccue.dev/pages/9-16-25-psvm</link><description></description><pubDate>Tue, 16 Sep 0025 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>public static void main(String[] args) is dead</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">public static void main(String[] args) is dead</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
As of September 16th, year of our lord 2025, this is no longer the first Java
program you need to write.

<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Scanner</span> scanner <span class="op">=</span> <span class="kw">new</span> <span class="bu">Scanner</span><span class="op">(</span><span class="bu">System</span><span class="op">.</span><span class="fu">in</span><span class="op">);</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">print</span><span class="op">(</span><span class="st">&quot;What is your name? &quot;</span><span class="op">);</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>        <span class="bu">String</span> name <span class="op">=</span> scanner<span class="op">.</span><span class="fu">nextLine</span><span class="op">();</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Hello, &quot;</span> <span class="op">+</span> name<span class="op">);</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This is.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    var name <span class="op">=</span> IO<span class="op">.</span><span class="fu">readln</span><span class="op">(</span><span class="st">&quot;What is your name? &quot;</span><span class="op">);</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    IO<span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Hello, &quot;</span> <span class="op">+</span> name<span class="op">);</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Good Fucking Riddance.</p>
<p>I'll be nuanced later, we've all earned some catharsis now.</p>
<p>Holy fucking shit did this suck<sup><a href="#1">1</a></sup>. There is a comments section below. Give your eulogy for that piece of shit sorcerous incantation there or wherever else.</p>
<p><code>new Scanner(System.in)</code> and <code>System.out.println</code> too. Don't let your sense of dignity hold you back.</p>
<p>Just record yourself giving a guttural scream and post it. Sing a song, do a dance, cast aspersions.</p>
<p>Honestly just let it all out.</p>
<p id="1" style="font-size: 14px">1: When I was a Freshman in High School I asked a Junior what it meant. He had no clue.
<br><br>That Junior later went on to drop out of college and <a href="https://www.youtube.com/@ryguyrocky">become a Minecraft Youtuber</a>.
I vividly remember him making videos where <a href="https://www.youtube.com/watch?v=3vLpuQpiGuA&list=PLF67-ejpmYg8zK2-xOBcmxnTrW1NAu3tw&index=2">he and his girlfriend pretend to be toddlers in a Minecraft day-care.</a> What a life.</p>

<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Approximating Named Arguments in Java</title><link>https://mccue.dev/pages/8-13-25-approximating-named-arguments</link><description></description><pubDate>Wed, 13 Aug 0025 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Approximating Named Arguments in Java</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Approximating Named Arguments in Java</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
Named arguments are a language feature where you can provide arguments
to a function call by name instead of positionally. This is usually paired
with some mechanism to have default values that a caller does not need to specify

<p>Take <a href="https://scikit-learn.org/stable/modules/generated/sklearn.cluster.k_means.html">the definition of <code>k_means</code> from scikit-learn</a> for example.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> k_means(</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    X,</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    n_clusters,</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">*</span>,</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    sample_weight<span class="op">=</span><span class="va">None</span>,</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    init<span class="op">=</span><span class="st">&quot;k-means++&quot;</span>,</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    n_init<span class="op">=</span><span class="st">&quot;auto&quot;</span>,</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    max_iter<span class="op">=</span><span class="dv">300</span>,</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    verbose<span class="op">=</span><span class="va">False</span>,</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>    tol<span class="op">=</span><span class="fl">1e-4</span>,</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>    random_state<span class="op">=</span><span class="va">None</span>,</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>    copy_x<span class="op">=</span><span class="va">True</span>,</span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>    algorithm<span class="op">=</span><span class="st">&quot;lloyd&quot;</span>,</span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>    return_n_iter<span class="op">=</span><span class="va">False</span>,</span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>):</span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    <span class="co"># ...</span></span></code></pre></div>
<p>It takes two arguments positionally and then has a very large number of optional arguments which have default values.</p>
<p>If a caller wants to only change the <code>max_iter</code> parameter they do not need to specify the others</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>k_means(X, n_clusters, max_iter<span class="op">=</span><span class="dv">10000</span>)</span></code></pre></div>
<p>Java does not (yet) have this or an equivalent as a language feature. Not only can you not specify parameters by name, you cannot get default values for said parameters easily</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co">// This is unideal for multiple reasons</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="fu">k_means</span><span class="op">(</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    X<span class="op">,</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    n_clusters<span class="op">,</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">null</span><span class="op">,</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;k-means++&quot;</span><span class="op">,</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;auto&quot;</span><span class="op">,</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>    <span class="dv">300</span><span class="op">,</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">false</span><span class="op">,</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>    <span class="fl">1e-4</span><span class="op">,</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">null</span><span class="op">,</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">true</span><span class="op">,</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;lloyd&quot;</span><span class="op">,</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">false</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span></code></pre></div>
<p>There are many strategies for coping with this. The most notable is using the builder pattern to make an "input object".</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>var input <span class="op">=</span> KMeansInput<span class="op">.</span><span class="fu">builder</span><span class="op">(</span>X<span class="op">,</span> n_clusters<span class="op">).</span><span class="fu">maxIter</span><span class="op">(</span><span class="dv">10000</span><span class="op">).</span><span class="fu">build</span><span class="op">();</span> </span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>var o <span class="op">=</span> <span class="fu">k_means</span><span class="op">(</span>input<span class="op">);</span></span></code></pre></div>
<p>This requires you to make both a class that holds all the input values in addition to an intermediate mutable class which holds all the same values.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> KMeansInput <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="bu">Object</span> X<span class="op">;</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="dt">int</span> nClusters<span class="op">;</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="bu">Double</span> sampleWeight<span class="op">;</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ... Need to have all the data here</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">KMeansInput</span><span class="op">(</span>Builder builder<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>        <span class="co">// copy from and potentially validate what is in the builder;</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> Builder <span class="fu">builder</span><span class="op">(</span><span class="bu">Object</span> x<span class="op">,</span> <span class="dt">int</span> nClusters<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Builder</span><span class="op">(</span>x<span class="op">,</span> nClusters<span class="op">);</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">final</span> <span class="kw">class</span> Builder <span class="op">{</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">final</span> <span class="bu">Object</span> X<span class="op">;</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">final</span> <span class="dt">int</span> nClusters<span class="op">;</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="bu">Double</span> sampleWeight <span class="op">=</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ... AND all the data here</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="fu">Builder</span><span class="op">(</span><span class="bu">Object</span> x<span class="op">,</span> <span class="dt">int</span> nClusters<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">X</span> <span class="op">=</span> x<span class="op">;</span></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">nClusters</span> <span class="op">=</span> nClusters<span class="op">;</span></span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb5-26"><a href="#cb5-26" aria-hidden="true" tabindex="-1"></a>        <span class="co">// Then mutating methods</span></span>
<span id="cb5-27"><a href="#cb5-27" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Builder <span class="fu">sampleWeight</span><span class="op">(</span><span class="dt">double</span> sampleWeight<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-28"><a href="#cb5-28" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">sampleWeight</span> <span class="op">=</span> sampleWeight<span class="op">;</span></span>
<span id="cb5-29"><a href="#cb5-29" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb5-30"><a href="#cb5-30" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb5-31"><a href="#cb5-31" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb5-32"><a href="#cb5-32" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb5-33"><a href="#cb5-33" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb5-34"><a href="#cb5-34" aria-hidden="true" tabindex="-1"></a>        <span class="co">// and a build()</span></span>
<span id="cb5-35"><a href="#cb5-35" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> KMeansInput <span class="fu">build</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb5-36"><a href="#cb5-36" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">new</span> <span class="fu">KMeansInput</span><span class="op">(</span><span class="kw">this</span><span class="op">);</span></span>
<span id="cb5-37"><a href="#cb5-37" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb5-38"><a href="#cb5-38" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-39"><a href="#cb5-39" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And all of that is a non-trivial amount of boilerplate.</p>
<p>Of course you <strong>could</strong> just have a public class with all the fields exposed.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> KMeansInput <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">final</span> <span class="bu">Object</span> X<span class="op">;</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">final</span> <span class="dt">int</span> nClusters<span class="op">;</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">Double</span> sampleWeight <span class="op">=</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">int</span> maxIter <span class="op">=</span> <span class="dv">300</span><span class="op">;</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">KMeansInput</span><span class="op">(</span><span class="bu">Object</span> x<span class="op">,</span> <span class="dt">int</span> nClusters<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">X</span> <span class="op">=</span> x<span class="op">;</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">nClusters</span> <span class="op">=</span> nClusters<span class="op">;</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Since setting a field value puts the name of that field on the page, this also works as an approximation of named arguments.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>var input <span class="op">=</span> <span class="kw">new</span> <span class="fu">KMeansInput</span><span class="op">(</span>X<span class="op">,</span> n_clusters<span class="op">);</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>input<span class="op">.</span><span class="fu">maxIter</span> <span class="op">=</span> <span class="dv">10000</span><span class="op">;</span> </span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>var o <span class="op">=</span> <span class="fu">k_means</span><span class="op">(</span>input<span class="op">);</span></span></code></pre></div>
<p>But there are two major downsides here. One is that you have a mutable object now and those are hard to reason about. You don't really know if <code>k_means</code> will mutate its "input object" or not.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>var input <span class="op">=</span> <span class="kw">new</span> <span class="fu">KMeansInput</span><span class="op">(</span>X<span class="op">,</span> n_clusters<span class="op">);</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>input<span class="op">.</span><span class="fu">maxIter</span> <span class="op">=</span> <span class="dv">10000</span><span class="op">;</span> </span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="co">// All is well for the first call</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>var o1 <span class="op">=</span> <span class="fu">k_means</span><span class="op">(</span>input<span class="op">);</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a><span class="co">// But this second call is dodgey</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>var o2 <span class="op">=</span> <span class="fu">k_means</span><span class="op">(</span>input<span class="op">);</span></span></code></pre></div>
<p>The other is the classic "there is no way to evolve a call to a field in a binary compatible way" issue.</p>
<p>If you wanted to make sure <code>maxIter</code> is never negative but still want a mutable aggregate, here come the getters and setters.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>var input <span class="op">=</span> <span class="kw">new</span> <span class="fu">KMeansInput</span><span class="op">(</span>X<span class="op">,</span> n_clusters<span class="op">);</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>input<span class="op">.</span><span class="fu">setMaxIter</span><span class="op">(</span><span class="dv">10000</span><span class="op">);</span> </span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>var o <span class="op">=</span> <span class="fu">k_means</span><span class="op">(</span>input<span class="op">);</span></span></code></pre></div>
<p>But this reintroduces boilerplate.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> KMeansInput <span class="op">{</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="bu">Object</span> X<span class="op">;</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">Object</span> <span class="fu">getX</span><span class="op">()</span> <span class="op">{</span> <span class="cf">return</span> x<span class="op">;</span> <span class="op">}</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="dt">int</span> nClusters<span class="op">;</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">int</span> <span class="fu">getNClusters</span><span class="op">()</span> <span class="op">{</span> <span class="cf">return</span> nClusters<span class="op">;</span> <span class="op">}</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="bu">Double</span> sampleWeight <span class="op">=</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">Double</span> <span class="fu">getSampleWeight</span><span class="op">()</span> <span class="op">{</span> <span class="cf">return</span> sampleWeight<span class="op">;</span> <span class="op">}</span></span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setSampleWeight</span><span class="op">(</span><span class="bu">Double</span> sampleWeight<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sampleWeight</span> <span class="op">=</span> sampleWeight<span class="op">;</span></span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">int</span> maxIter <span class="op">=</span> <span class="dv">300</span><span class="op">;</span></span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">int</span> <span class="fu">getMaxIter</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> maxIter<span class="op">;</span></span>
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-24"><a href="#cb10-24" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb10-25"><a href="#cb10-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setMaxIter</span><span class="op">(</span><span class="dt">int</span> maxIter<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-26"><a href="#cb10-26" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">maxIter</span> <span class="op">=</span> maxIter<span class="op">;</span></span>
<span id="cb10-27"><a href="#cb10-27" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-28"><a href="#cb10-28" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb10-29"><a href="#cb10-29" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb10-30"><a href="#cb10-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-31"><a href="#cb10-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">KMeansInput</span><span class="op">(</span><span class="bu">Object</span> x<span class="op">,</span> <span class="dt">int</span> nClusters<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-32"><a href="#cb10-32" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">X</span> <span class="op">=</span> x<span class="op">;</span></span>
<span id="cb10-33"><a href="#cb10-33" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">nClusters</span> <span class="op">=</span> nClusters<span class="op">;</span></span>
<span id="cb10-34"><a href="#cb10-34" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-35"><a href="#cb10-35" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>So now not only do you have about a lot of boilerplate, just like the builder approach, but you are stuck with a mutable object in the end.</p>
<p>The next best candidate is records. They work well for getting an immutable aggregate with default values.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> record <span class="fu">KMeansInput</span><span class="op">(</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Object</span> X<span class="op">,</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> nClusters<span class="op">,</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Double</span> sampleWeight<span class="op">,</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>        <span class="bu">String</span> init<span class="op">,</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>        <span class="bu">String</span> nInit<span class="op">,</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> maxIter<span class="op">,</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>        <span class="dt">boolean</span> verbose<span class="op">,</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a>        <span class="dt">double</span> tol<span class="op">,</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Object</span> randomState<span class="op">,</span></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>        <span class="dt">boolean</span> copyX<span class="op">,</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>        <span class="bu">String</span> algorithm<span class="op">,</span></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a>        <span class="dt">boolean</span> returnNIter</span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">KMeansInput</span><span class="op">(</span><span class="bu">Object</span> X<span class="op">,</span> <span class="dt">int</span> nClusters<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">(</span></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true" tabindex="-1"></a>                X<span class="op">,</span> </span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true" tabindex="-1"></a>                nClusters<span class="op">,</span> </span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true" tabindex="-1"></a>                <span class="kw">null</span><span class="op">,</span> </span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;k-means++&quot;</span><span class="op">,</span> </span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;auto&quot;</span><span class="op">,</span> </span>
<span id="cb11-22"><a href="#cb11-22" aria-hidden="true" tabindex="-1"></a>                <span class="dv">300</span><span class="op">,</span> </span>
<span id="cb11-23"><a href="#cb11-23" aria-hidden="true" tabindex="-1"></a>                <span class="kw">false</span><span class="op">,</span> </span>
<span id="cb11-24"><a href="#cb11-24" aria-hidden="true" tabindex="-1"></a>                <span class="fl">1e-4</span><span class="op">,</span> </span>
<span id="cb11-25"><a href="#cb11-25" aria-hidden="true" tabindex="-1"></a>                <span class="kw">null</span><span class="op">,</span> </span>
<span id="cb11-26"><a href="#cb11-26" aria-hidden="true" tabindex="-1"></a>                <span class="kw">true</span><span class="op">,</span> </span>
<span id="cb11-27"><a href="#cb11-27" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;lloyd&quot;</span><span class="op">,</span> </span>
<span id="cb11-28"><a href="#cb11-28" aria-hidden="true" tabindex="-1"></a>                <span class="kw">false</span></span>
<span id="cb11-29"><a href="#cb11-29" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb11-30"><a href="#cb11-30" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb11-31"><a href="#cb11-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Downside is that the constructor(s) you make to delegate to the canonical constructor will be fiddly. There aren't any names in that <code>this(...)</code> invocation.</p>
<p>There is also the fact that records expose a pattern matching API that is not currently generally available to all classes. This means that, unlike the <code>Builder</code> -&gt; input object flow, adding new components to an input object record is always a sort of breaking change.</p>
<p>You will eventually be able to use withers to take a fully constructed record, update one part, and recreate the record.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>var input <span class="op">=</span> <span class="kw">new</span> <span class="fu">KMeansInput</span><span class="op">(</span>X<span class="op">,</span> n_clusters<span class="op">).</span><span class="fu">with</span> <span class="op">{</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>    maxIter <span class="op">=</span> <span class="dv">10000</span><span class="op">;</span>  </span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span></code></pre></div>
<p>But withers are also still not in the language. You can emulate them by making your own mutable aggregate and using it as a temporary for "reconstruction."</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">function</span><span class="op">.</span><span class="im">Consumer</span><span class="op">;</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> record <span class="fu">KMeansInput</span><span class="op">(</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Object</span> X<span class="op">,</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> nClusters<span class="op">,</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Double</span> sampleWeight<span class="op">,</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>        <span class="bu">String</span> init<span class="op">,</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>        <span class="bu">String</span> nInit<span class="op">,</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> maxIter<span class="op">,</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>        <span class="dt">boolean</span> verbose<span class="op">,</span></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>        <span class="dt">double</span> tol<span class="op">,</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Object</span> randomState<span class="op">,</span></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>        <span class="dt">boolean</span> copyX<span class="op">,</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a>        <span class="bu">String</span> algorithm<span class="op">,</span></span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a>        <span class="dt">boolean</span> returnNIter</span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">KMeansInput</span><span class="op">(</span><span class="bu">Object</span> X<span class="op">,</span> <span class="dt">int</span> nClusters<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">(</span></span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a>                X<span class="op">,</span></span>
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true" tabindex="-1"></a>                nClusters<span class="op">,</span></span>
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true" tabindex="-1"></a>                <span class="kw">null</span><span class="op">,</span></span>
<span id="cb13-22"><a href="#cb13-22" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;k-means++&quot;</span><span class="op">,</span></span>
<span id="cb13-23"><a href="#cb13-23" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;auto&quot;</span><span class="op">,</span></span>
<span id="cb13-24"><a href="#cb13-24" aria-hidden="true" tabindex="-1"></a>                <span class="dv">300</span><span class="op">,</span></span>
<span id="cb13-25"><a href="#cb13-25" aria-hidden="true" tabindex="-1"></a>                <span class="kw">false</span><span class="op">,</span></span>
<span id="cb13-26"><a href="#cb13-26" aria-hidden="true" tabindex="-1"></a>                <span class="fl">1e-4</span><span class="op">,</span></span>
<span id="cb13-27"><a href="#cb13-27" aria-hidden="true" tabindex="-1"></a>                <span class="kw">null</span><span class="op">,</span></span>
<span id="cb13-28"><a href="#cb13-28" aria-hidden="true" tabindex="-1"></a>                <span class="kw">true</span><span class="op">,</span></span>
<span id="cb13-29"><a href="#cb13-29" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;lloyd&quot;</span><span class="op">,</span></span>
<span id="cb13-30"><a href="#cb13-30" aria-hidden="true" tabindex="-1"></a>                <span class="kw">false</span></span>
<span id="cb13-31"><a href="#cb13-31" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb13-32"><a href="#cb13-32" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-33"><a href="#cb13-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-34"><a href="#cb13-34" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> KMeansInput <span class="fu">with</span><span class="op">(</span>Consumer<span class="op">&lt;</span>MutableKMeansInput<span class="op">&gt;</span> consumer<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-35"><a href="#cb13-35" aria-hidden="true" tabindex="-1"></a>        var mut <span class="op">=</span> <span class="kw">new</span> <span class="fu">MutableKMeansInput</span><span class="op">(</span><span class="kw">this</span><span class="op">);</span></span>
<span id="cb13-36"><a href="#cb13-36" aria-hidden="true" tabindex="-1"></a>        consumer<span class="op">.</span><span class="fu">accept</span><span class="op">(</span>mut<span class="op">);</span></span>
<span id="cb13-37"><a href="#cb13-37" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> mut<span class="op">.</span><span class="fu">freeze</span><span class="op">();</span></span>
<span id="cb13-38"><a href="#cb13-38" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-39"><a href="#cb13-39" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb14"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> MutableKMeansInput <span class="op">{</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">Object</span> X<span class="op">;</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">int</span> nClusters<span class="op">;</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">Double</span> sampleWeight<span class="op">;</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">String</span> init<span class="op">;</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">String</span> nInit<span class="op">;</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">int</span> maxIter<span class="op">;</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">boolean</span> verbose<span class="op">;</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">double</span> tol<span class="op">;</span></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">Object</span> randomState<span class="op">;</span></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">boolean</span> copyX<span class="op">;</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">String</span> algorithm<span class="op">;</span></span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">boolean</span> returnNIter<span class="op">;</span></span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true" tabindex="-1"></a>    <span class="fu">MutableKMeansInput</span><span class="op">(</span>KMeansInput input<span class="op">)</span> <span class="op">{</span></span>
<span id="cb14-16"><a href="#cb14-16" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">X</span> <span class="op">=</span> input<span class="op">.</span><span class="fu">X</span><span class="op">;</span></span>
<span id="cb14-17"><a href="#cb14-17" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">nClusters</span> <span class="op">=</span> input<span class="op">.</span><span class="fu">nClusters</span><span class="op">;</span></span>
<span id="cb14-18"><a href="#cb14-18" aria-hidden="true" tabindex="-1"></a>        <span class="co">// and so on</span></span>
<span id="cb14-19"><a href="#cb14-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-20"><a href="#cb14-20" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb14-21"><a href="#cb14-21" aria-hidden="true" tabindex="-1"></a>    KMeansInput <span class="fu">freeze</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb14-22"><a href="#cb14-22" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">KMeansInput</span><span class="op">(</span>X<span class="op">,</span> nClusters<span class="op">,</span> sampleWeight<span class="op">,</span> <span class="kw">...</span><span class="op">);</span></span>
<span id="cb14-23"><a href="#cb14-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-24"><a href="#cb14-24" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb14-25"><a href="#cb14-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Using this scheme would look something like this.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>var input <span class="op">=</span> <span class="kw">new</span> <span class="fu">KMeansInput</span><span class="op">(</span>X<span class="op">,</span> nClusters<span class="op">).</span><span class="fu">with</span><span class="op">(</span>it <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>    it<span class="op">.</span><span class="fu">maxIter</span> <span class="op">=</span> <span class="dv">10000</span><span class="op">;</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="op">});</span></span></code></pre></div>
<p>You might notice that its somewhat like "builder, but backwards." A builder starts out with a mutable aggregate and later builds a (hopefully) immutable one. A record with this style of wither emulation starts off with an immutable aggregate and uses a temporary mutable aggregate which gets turned into the immutable verson later</p>
<p>Unfortunately this didn't really solve our boilerplate problem. Records once withers are in the language come the closest though. As with all boilerplate a degree of code generation can help a little, so you can reach for <a href="https://github.com/Randgalt/record-builder">recordbuilder</a> or similar.</p>
<p>The last way I can think of is a Java classic. Instead of having a method that takes in arguments, turn the whole process into an object.</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> KMeans <span class="op">{</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="bu">Object</span> X<span class="op">;</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="dt">int</span> nClusters<span class="op">;</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="bu">Double</span> sampleWeight<span class="op">;</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">KMeans</span><span class="op">(</span><span class="bu">Object</span> X<span class="op">,</span> <span class="dt">int</span> nClusters<span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>        <span class="co">// initialize all the defaults</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>    <span class="co">// then setters for all the knobs</span></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setSampleWeight</span><span class="op">(</span><span class="bu">Double</span> sampleWeight<span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sampleWeight</span> <span class="op">=</span> sampleWeight<span class="op">;</span></span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a>    <span class="co">// and finally the ability to run the algorithm</span></span>
<span id="cb16-20"><a href="#cb16-20" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> KMeansOutput <span class="fu">run</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb16-21"><a href="#cb16-21" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb16-22"><a href="#cb16-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-23"><a href="#cb16-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The overall object lifecycle of "make it, tweak it, run it" comes up a lot, but often especially when reading code from Java's early days. I don't have a coherent explanation as to why, but I think at some point this style of code fell out of favor.</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>var kMeans <span class="op">=</span> <span class="kw">new</span> <span class="fu">KMeans</span><span class="op">(</span>X<span class="op">,</span> nClusters<span class="op">);</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>kMeans<span class="op">.</span><span class="fu">setMaxIter</span><span class="op">(</span><span class="dv">10000</span><span class="op">);</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>var o <span class="op">=</span> kMeans<span class="op">.</span><span class="fu">run</span><span class="op">();</span></span></code></pre></div>
<p>So of all these options suck in their own ways.</p>
<p>Records with withers has the most potential in my eyes, but its important to remember that this whole process only solves for the situation where most of the parameters are optional and have defaults.</p>
<p>While I'd say rare-ish, its not impossible to end up wanting to make something where all 20 or so parameters should be defined and have no defaults. Named arguments as a general feature could handle that, but it's going to be quite awhile before that is top of anyone's priority list.</p>
<hr />
<p>Edit: As has been pointed out, you can also pass a callback that operates on a mutable object without necessarily exposing the object to be directly constructed.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="fu">kMeans</span><span class="op">(</span>X<span class="op">,</span> nClusters<span class="op">,</span> opts <span class="op">-&gt;</span> opts<span class="op">.</span><span class="fu">maxIter</span> <span class="op">=</span> <span class="dv">1000</span><span class="op">);</span></span></code></pre></div>
<p>Same general sorts of tradeoffs between direct fields vs. methods that set exist there.</p>
<p>I don't know why I forget about that one all the time.</p>
<p>Also with the setters you can still do the builder thing where you make then chainable.</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">new</span> <span class="fu">KMeansInput</span><span class="op">(</span>X<span class="op">,</span> nClusters<span class="op">)</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">setMaxIter</span><span class="op">(</span><span class="dv">1000</span><span class="op">)</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">setTol</span><span class="op">(</span><span class="fl">1e-8</span><span class="op">);</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Inheritance vs. Composition</title><link>https://mccue.dev/pages/7-27-25-inheritance-vs-composition</link><description></description><pubDate>Sun, 27 Jul 0025 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Inheritance vs. Composition</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Inheritance vs. Composition</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
This list is the result of a question posed by [Mika Moilanen](https://github.com/mikmoila). It's not comprehensive, but I think it's
illustrative of a way to break down these choices that's a tad more healthy than "always choose X" or "never do Y."
Specifically because you can take these properties and evaluate them against a given set of conditions.

<p>"List all the differences between using an abstract class and using a delegate object when sharing common functionality."</p>
<h2 id="both-let-you-reuse-a-method-definition">Both let you reuse a method definition</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Adder <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">+</span> y<span class="op">;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Composition <span class="op">{</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> Adder a <span class="op">=</span> <span class="kw">new</span> <span class="fu">Adder</span><span class="op">();</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> a<span class="op">.</span><span class="fu">add</span><span class="op">(</span>x<span class="op">,</span> y<span class="op">);</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">abstract</span> <span class="kw">class</span> Adder <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">+</span> y<span class="op">;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Inheritance <span class="kw">extends</span> Adder <span class="op">{</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Implicitly inherits add</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="composition-requires-you-re-list-every-method-you-want-to-borrow">Composition requires you re-list every method you want to borrow</h2>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> MathDoer <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">+</span> y<span class="op">;</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">sub</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">-</span> y<span class="op">;</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">mul</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">*</span> y<span class="op">;</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">div</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">/</span> y<span class="op">;</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Composition <span class="op">{</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> MathDoer m <span class="op">=</span> <span class="kw">new</span> <span class="fu">MathDoer</span><span class="op">();</span></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> m<span class="op">.</span><span class="fu">add</span><span class="op">(</span>x<span class="op">,</span> y<span class="op">);</span></span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">sub</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> m<span class="op">.</span><span class="fu">sub</span><span class="op">(</span>x<span class="op">,</span> y<span class="op">);</span></span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">mul</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> m<span class="op">.</span><span class="fu">mul</span><span class="op">(</span>x<span class="op">,</span> y<span class="op">);</span></span>
<span id="cb3-32"><a href="#cb3-32" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-33"><a href="#cb3-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-34"><a href="#cb3-34" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">div</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-35"><a href="#cb3-35" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> m<span class="op">.</span><span class="fu">div</span><span class="op">(</span>x<span class="op">,</span> y<span class="op">);</span></span>
<span id="cb3-36"><a href="#cb3-36" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-37"><a href="#cb3-37" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">abstract</span> <span class="kw">class</span> MathDoer <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">+</span> y<span class="op">;</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">sub</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">-</span> y<span class="op">;</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">mul</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">*</span> y<span class="op">;</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">div</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">/</span> y<span class="op">;</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Inheritance <span class="kw">extends</span> Adder <span class="op">{</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Implicitly inherits add, sub, mul, and div</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="inheritance-can-lead-to-observing-otherwise-hidden-method-relationships">Inheritance can lead to observing otherwise hidden method relationships</h2>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">abstract</span> <span class="kw">class</span> MathDoer <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">+</span> y<span class="op">;</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">sub</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fu">add</span><span class="op">(</span>x<span class="op">,</span> <span class="op">-</span><span class="dv">1</span> <span class="op">*</span> y<span class="op">);</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Inheritance <span class="kw">extends</span> Adder <span class="op">{</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Will print for both add and sub</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>    <span class="co">// but brittle if sub is ever redefined</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a>    <span class="co">// to be &quot;return x - y;&quot;</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a>        IO<span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Add called. x=&quot;</span> <span class="op">+</span> x <span class="op">+</span> <span class="st">&quot;, y=&quot;</span> <span class="op">+</span> y<span class="op">);</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">super</span><span class="op">.</span><span class="fu">add</span><span class="op">(</span>x<span class="op">,</span> y<span class="op">);</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> MathDoer <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">+</span> y<span class="op">;</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">sub</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fu">add</span><span class="op">(</span>x<span class="op">,</span> <span class="op">-</span><span class="dv">1</span> <span class="op">*</span> y<span class="op">);</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Composition <span class="op">{</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> MathDoer m <span class="op">=</span> <span class="kw">new</span> <span class="fu">MathDoer</span><span class="op">();</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Resilient to whatever internal relationships</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a>    <span class="co">// add and sub have within MathDoer</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a>        IO<span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Add called. x=&quot;</span> <span class="op">+</span> x <span class="op">+</span> <span class="st">&quot;, y=&quot;</span> <span class="op">+</span> y<span class="op">);</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> m<span class="op">.</span><span class="fu">add</span><span class="op">(</span>x<span class="op">,</span> y<span class="op">);</span></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">sub</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a>        IO<span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Sub called. x=&quot;</span> <span class="op">+</span> x <span class="op">+</span> <span class="st">&quot;, y=&quot;</span> <span class="op">+</span> y<span class="op">);</span></span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> m<span class="op">.</span><span class="fu">sub</span><span class="op">(</span>x<span class="op">,</span> y<span class="op">);</span></span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="inheritance-implicitly-gives-polymorphic-dispatch-for-all-exposed-methods">Inheritance implicitly gives polymorphic dispatch for all exposed methods</h2>
<div class="sourceCode" id="cb7"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">abstract</span> <span class="kw">class</span> MathDoer <span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">+</span> y<span class="op">;</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">sub</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">-</span> y<span class="op">;</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Inheritance <span class="kw">extends</span> MathDoer <span class="op">{</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a>        IO<span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Add called. x=&quot;</span> <span class="op">+</span> x <span class="op">+</span> <span class="st">&quot;, y=&quot;</span> <span class="op">+</span> y<span class="op">);</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">super</span><span class="op">.</span><span class="fu">add</span><span class="op">(</span>x<span class="op">,</span> y<span class="op">);</span></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true" tabindex="-1"></a>    MathDoer m <span class="op">=</span> <span class="kw">new</span> <span class="fu">Inheritance</span><span class="op">();</span></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true" tabindex="-1"></a>    IO<span class="op">.</span><span class="fu">println</span><span class="op">(</span>m<span class="op">.</span><span class="fu">add</span><span class="op">(</span><span class="dv">1</span><span class="op">,</span> <span class="dv">2</span><span class="op">));</span></span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb8"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="co">// To get dynamic dispatch you need an intermediate interface</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">interface</span> IMathDoer <span class="op">{</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">);</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">sub</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">);</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a><span class="co">// This in turn means methods must be public.</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a><span class="co">//</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a><span class="co">// If you want &quot;package-private&quot; dynamic dispatch you</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a><span class="co">// are out of luck.</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> MathDoer <span class="kw">implements</span> IMathDoer <span class="op">{</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">+</span> y<span class="op">;</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">int</span> <span class="fu">sub</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fu">add</span><span class="op">(</span>x<span class="op">,</span> <span class="op">-</span><span class="dv">1</span> <span class="op">*</span> y<span class="op">);</span></span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Composition <span class="kw">implements</span> IMathDoer <span class="op">{</span></span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> MathDoer m <span class="op">=</span> <span class="kw">new</span> <span class="fu">MathDoer</span><span class="op">();</span></span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> m<span class="op">.</span><span class="fu">add</span><span class="op">(</span>x<span class="op">,</span> y<span class="op">);</span></span>
<span id="cb8-26"><a href="#cb8-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-27"><a href="#cb8-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-28"><a href="#cb8-28" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">int</span> <span class="fu">sub</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-29"><a href="#cb8-29" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> m<span class="op">.</span><span class="fu">sub</span><span class="op">(</span>x<span class="op">,</span> y<span class="op">);</span></span>
<span id="cb8-30"><a href="#cb8-30" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-31"><a href="#cb8-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb8-32"><a href="#cb8-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-33"><a href="#cb8-33" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb8-34"><a href="#cb8-34" aria-hidden="true" tabindex="-1"></a>    IMathDoer m <span class="op">=</span> <span class="kw">new</span> <span class="fu">Composition</span><span class="op">();</span></span>
<span id="cb8-35"><a href="#cb8-35" aria-hidden="true" tabindex="-1"></a>    IO<span class="op">.</span><span class="fu">println</span><span class="op">(</span>m<span class="op">.</span><span class="fu">add</span><span class="op">(</span><span class="dv">1</span><span class="op">,</span> <span class="dv">2</span><span class="op">));</span></span>
<span id="cb8-36"><a href="#cb8-36" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="you-can-compose-behavior-from-multiple-objects-inheritance-is-linear">You can compose behavior from multiple objects. Inheritance is linear</h2>
<div class="sourceCode" id="cb9"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">abstract</span> <span class="kw">class</span> Adder <span class="op">{</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">+</span> y<span class="op">;</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a><span class="kw">abstract</span> <span class="kw">class</span> Subber <span class="op">{</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">sub</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">-</span> y<span class="op">;</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Inheritance <span class="kw">extends</span> Adder <span class="op">{</span> <span class="co">// Cannot also extend Subber</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb10"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Adder <span class="op">{</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">+</span> y<span class="op">;</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Subber <span class="op">{</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">sub</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">-</span> y<span class="op">;</span></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Composition <span class="op">{</span></span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> Adder a <span class="op">=</span> <span class="kw">new</span> <span class="fu">Adder</span><span class="op">();</span></span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> Subber s <span class="op">=</span> <span class="kw">new</span> <span class="fu">Subber</span><span class="op">();</span></span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Resilient to whatever internal relationships</span></span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a>    <span class="co">// add and sub have within MathDoer</span></span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> a<span class="op">.</span><span class="fu">add</span><span class="op">(</span>x<span class="op">,</span> y<span class="op">);</span></span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">sub</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-24"><a href="#cb10-24" aria-hidden="true" tabindex="-1"></a>        s<span class="op">.</span><span class="fu">sub</span><span class="op">(</span>x<span class="op">,</span> y<span class="op">);</span></span>
<span id="cb10-25"><a href="#cb10-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-26"><a href="#cb10-26" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="inheritance-lets-you-define-protected-members-which-are-public-only-to-classes-in-the-same-package-and-extenders">Inheritance lets you define <code>protected</code> members which are public only to classes in the same package and extenders</h2>
<div class="sourceCode" id="cb11"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span><span class="im"> a</span><span class="op">;</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a><span class="kw">abstract</span> <span class="kw">class</span> MathDoer <span class="op">{</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">protected</span> <span class="kw">abstract</span> <span class="dt">int</span> <span class="fu">addInternal</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">);</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">final</span> <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fu">addInternal</span><span class="op">(</span>x<span class="op">,</span> y<span class="op">);</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">final</span> <span class="dt">int</span> <span class="fu">sub</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fu">addInternal</span><span class="op">(</span>x<span class="op">,</span> <span class="fu">mul</span><span class="op">(</span>y<span class="op">,</span> <span class="op">-</span><span class="dv">1</span><span class="op">));</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb12"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span><span class="im"> b</span><span class="op">;</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a><span class="co">// If extending the class, can see addInternal </span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a><span class="co">// despite being in a different package</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Inheritance <span class="kw">extends</span> MathDoer <span class="op">{</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">protected</span> <span class="dt">int</span> <span class="fu">addInternal</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">+</span> y<span class="op">;</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb13"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span><span class="im"> a</span><span class="op">;</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="co">// No way to define a method or field that will</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="co">// be visible across package boundaries only to things</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a><span class="co">// that are &quot;composing&quot;.</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a><span class="dt">final</span> <span class="kw">class</span> MathDoer <span class="op">{</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">+</span> y<span class="op">;</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">sub</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fu">add</span><span class="op">(</span>x<span class="op">,</span> <span class="op">-</span><span class="dv">1</span> <span class="op">*</span> y<span class="op">);</span></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="inheritance-requires-you-directly-expose-constructors">Inheritance requires you directly expose constructors</h2>
<div class="sourceCode" id="cb14"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">abstract</span> <span class="kw">class</span> MathDoer <span class="op">{</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Subclasses need to call a super-class constructor</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>    <span class="fu">MathDoer</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">+</span> y<span class="op">;</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">sub</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fu">add</span><span class="op">(</span>x<span class="op">,</span> <span class="op">-</span><span class="dv">1</span> <span class="op">*</span> y<span class="op">);</span></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Inheritance <span class="kw">extends</span> Adder <span class="op">{</span></span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true" tabindex="-1"></a>    <span class="fu">Inhertiance</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb14-16"><a href="#cb14-16" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">();</span></span>
<span id="cb14-17"><a href="#cb14-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-18"><a href="#cb14-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb15"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> MathDoer <span class="op">{</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">MathDoer</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> MathDoer <span class="fu">getIt</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">MathDoer</span><span class="op">();</span></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">+</span> y<span class="op">;</span></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">sub</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fu">add</span><span class="op">(</span>x<span class="op">,</span> <span class="op">-</span><span class="dv">1</span> <span class="op">*</span> y<span class="op">);</span></span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb15-15"><a href="#cb15-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb15-16"><a href="#cb15-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-17"><a href="#cb15-17" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Composition <span class="op">{</span></span>
<span id="cb15-18"><a href="#cb15-18" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Meanwhile composition can allow you to keep constructors hidden</span></span>
<span id="cb15-19"><a href="#cb15-19" aria-hidden="true" tabindex="-1"></a>    <span class="co">// and only expose static factories or builders.</span></span>
<span id="cb15-20"><a href="#cb15-20" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> MathDoer m <span class="op">=</span> MathDoer<span class="op">.</span><span class="fu">getIt</span><span class="op">();</span></span>
<span id="cb15-21"><a href="#cb15-21" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb15-22"><a href="#cb15-22" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-23"><a href="#cb15-23" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> m<span class="op">.</span><span class="fu">add</span><span class="op">(</span>x<span class="op">,</span> y<span class="op">);</span></span>
<span id="cb15-24"><a href="#cb15-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb15-25"><a href="#cb15-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-26"><a href="#cb15-26" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">sub</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-27"><a href="#cb15-27" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> m<span class="op">.</span><span class="fu">sub</span><span class="op">(</span>x<span class="op">,</span> y<span class="op">);</span></span>
<span id="cb15-28"><a href="#cb15-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb15-29"><a href="#cb15-29" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="inheritance-leaves-you-exposed-to-new-methods-with-incompatible-signatures">Inheritance leaves you exposed to new methods with incompatible signatures</h2>
<div class="sourceCode" id="cb16"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">abstract</span> <span class="kw">class</span> MathDoer <span class="op">{</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">+</span> y<span class="op">;</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">sub</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fu">add</span><span class="op">(</span>x<span class="op">,</span> <span class="op">-</span><span class="dv">1</span> <span class="op">*</span> y<span class="op">);</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>    <span class="co">// int mul(int x, int y) {</span></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>    <span class="co">//     return x * y;</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>    <span class="co">// }</span></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Inheritance <span class="kw">extends</span> Adder <span class="op">{</span></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a>    <span class="dt">double</span> <span class="fu">mul</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a>        <span class="co">// This is fine initially, but poses a problem </span></span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a>        <span class="co">// if an incompatible method is added to the superclass later</span></span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">((</span><span class="dt">double</span><span class="op">)</span> x <span class="op">*</span> y<span class="op">);</span></span>
<span id="cb16-20"><a href="#cb16-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-21"><a href="#cb16-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb17"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> MathDoer <span class="op">{</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">+</span> y<span class="op">;</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">sub</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fu">add</span><span class="op">(</span>x<span class="op">,</span> <span class="op">-</span><span class="dv">1</span> <span class="op">*</span> y<span class="op">);</span></span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">mul</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">*</span> y<span class="op">;</span></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Composition <span class="op">{</span></span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> MathDoer m <span class="op">=</span> <span class="kw">new</span> <span class="fu">MathDoer</span><span class="op">();</span></span>
<span id="cb17-17"><a href="#cb17-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-18"><a href="#cb17-18" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Resilient to whatever internal relationships</span></span>
<span id="cb17-19"><a href="#cb17-19" aria-hidden="true" tabindex="-1"></a>    <span class="co">// add and sub have within MathDoer</span></span>
<span id="cb17-20"><a href="#cb17-20" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb17-21"><a href="#cb17-21" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> m<span class="op">.</span><span class="fu">add</span><span class="op">(</span>x<span class="op">,</span> y<span class="op">);</span></span>
<span id="cb17-22"><a href="#cb17-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb17-23"><a href="#cb17-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-24"><a href="#cb17-24" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">sub</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb17-25"><a href="#cb17-25" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> m<span class="op">.</span><span class="fu">sub</span><span class="op">(</span>x<span class="op">,</span> y<span class="op">);</span></span>
<span id="cb17-26"><a href="#cb17-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb17-27"><a href="#cb17-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-28"><a href="#cb17-28" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Any methods not taken via composition</span></span>
<span id="cb17-29"><a href="#cb17-29" aria-hidden="true" tabindex="-1"></a>    <span class="co">// do not pose a problem.</span></span>
<span id="cb17-30"><a href="#cb17-30" aria-hidden="true" tabindex="-1"></a>    <span class="co">//</span></span>
<span id="cb17-31"><a href="#cb17-31" aria-hidden="true" tabindex="-1"></a>    <span class="co">// A caveat is that this is an issue</span></span>
<span id="cb17-32"><a href="#cb17-32" aria-hidden="true" tabindex="-1"></a>    <span class="co">// with interfaces as well, so its more a property</span></span>
<span id="cb17-33"><a href="#cb17-33" aria-hidden="true" tabindex="-1"></a>    <span class="co">// of polymorphic dispatch</span></span>
<span id="cb17-34"><a href="#cb17-34" aria-hidden="true" tabindex="-1"></a>    <span class="dt">double</span> <span class="fu">mul</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb17-35"><a href="#cb17-35" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">((</span><span class="dt">double</span><span class="op">)</span> x <span class="op">*</span> y<span class="op">);</span></span>
<span id="cb17-36"><a href="#cb17-36" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb17-37"><a href="#cb17-37" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<p>Once I am able to cohere my thoughts without foaming at the mouth and twitching, expect a rant on "mechanics-ism."</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>The Economics of AI (Ed Zitron is Wrong)</title><link>https://mccue.dev/pages/7-22-25-ed-zitron-is-wrong</link><description></description><pubDate>Tue, 22 Jul 0025 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>The Economics of AI (Ed Zitron is Wrong)</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">The Economics of AI (Ed Zitron is Wrong)</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
Ed Zitron, or as my friends call him while doing the SpongeBob thing "EdWaRd," [Seems
to think that AI is in some manner a bubble](https://www.wheresyoured.at/the-haters-gui/).

<p>This is patently ridiculous. To understand why you need to understand a little basic kindergarten level economics.</p>
<h2 id="the-lemonade-stand">The Lemonade Stand</h2>
<p>Imagine a lemonade stand run by three plucky 12-year-olds. Call them Ed, Edd, and Eddy.</p>
<p>Each day of operation for this lemonade stand will both cost money to run and bring in money from sales. These costs are expenses and the money brought in is revenue.</p>
<p>Subtract expenses from revenue, and you get the total profit (or loss) for that day of operations.</p>
<p>Say they sell $10 worth of lemonade and the cost of sugar, lemon, and water totals up to $6. For that day they will have made $4 in profit.</p>
<h2 id="startup-costs">Startup Costs</h2>
<p>Businesses have all sorts of expenses.</p>
<p>We can simplify these broadly into one-time expenses (like the lumber to make the booth) and recurring expenses (like the materials to make the lemonade.)</p>
<p>One-time expenses needed for the business to begin operations are called "startup costs."</p>
<p>Since the business is not yet running - at least not at full capacity - the funds to cover these startup costs needs to come from somewhere else. For a lemonade stand this is likely a parent of one of the children. This, depending on the preferred child-rearing strategy, can make that parent an "investor."</p>
<p>So if it costs $20 to get all the supplies for the first day of operations, how long until the lemonade stand can repay their startup costs?</p>
<h2 id="unit-economics">Unit Economics</h2>
<p>It is generally understood that the more customers a business has the more money it makes.</p>
<p>To know exactly how much money to expect you need to understand the "unit economics" of the business. This is just the amount made per unit of product sold.</p>
<p>So if you sell 1 cup of lemonade for $1.00, and it took $0.50 to make, you will profit $0.50 per cup of lemonade sold.</p>
<p>This means that once you sell 40 cups of lemonade you will have made back the initial $20 investment.</p>
<h2 id="economies-of-scale">Economies of Scale</h2>
<p>Unfortunately sugar and lemons are not sold in clean "amount needed for a cup of lemonade" increments.</p>
<p>If you buy a small bag of sugar it might cost $5 but contain enough sugar for 20 cups of lemonade. If, however, you buy a large bag of sugar it might cost $100 but contain enough sugar for 1000 cups of lemonade.</p>
<p>This is what people mean by "economies of scale." If you can expect to sell more than 1000 cups of lemonade you can make your per-unit cost go down by buying the larger bag of sugar. If you aren't yet selling that much lemonade you might need to make do with the smaller bag.</p>
<h2 id="subsidies">Subsidies</h2>
<p>It is always possible for a business to run at a loss. There are two broad reasons for this.</p>
<p>First is that it might not yet be profitable. It takes time for customers to discover and use your lemonade stand. For a period of time you might be stuck buying small bags of sugar. If you actually priced your product so that you make a profit-per-unit you might never get enough customers to "activate economies of scale."</p>
<p>Second is that it might never be profitable.</p>
<p>In both situations a business needs to be subsidized. This means that cash needs to be continuously injected to keep operations afloat.</p>
<p>Investors generally do this because they believe that, with enough time in the proverbial oven, the business can become profitable. One way that can happen is that the aforementioned "economies of scale" can drive down per-unit costs.</p>
<p>The other is "market capture." If you pour enough money into a lemonade stand that it can open branches on literally every street corner you can prevent new lemonade stands from opening. Being the only option in town for lemonade means you can jack up the price to become profitable. This has some limits - you can't make lemonade $2000 and expect anyone to be able or willing to afford that - but monopolies and oligopolies are almost the ideal state for a business.</p>
<p>If a business will never become profitable investors still might subsidize it. Lemonade stands are often used to teach children life lessons, not to become profitable. For this reason a parental investor might contribute money that they never expect to make back. The thing they are purchasing is not future returns but instead the existence of the lemonade stand itself.</p>
<p>With a particularly affluent parent a modest lemonade stand can be kept in operation almost indefinitely, even if they sell the lemonade for free.</p>
<h2 id="anthropic">Anthropic</h2>
<p>Anthropic, a major AI company, <a href="https://www.wheresyoured.at/anthropic-is-bleeding-out/">loses money on every active user</a>. This is because they charge people a monthly rate, and it costs multiple times that monthly rate to provide them the product they paid for.</p>
<p>The numbers aren't fully known, but it seems safe to say that for everyone who pays for and uses their platform they probably lose at least ~3x what that person paid them. The more someone uses their AI the faster they lose money.</p>
<p>There aren't any economies of scale left for them to activate. They are already plenty big and the GPUs they bought are expensive. But the more expensive part is actually running them. The costs of doing that aren't going to go down any time soon and actually increase the more usage they see.</p>
<p>They also can't make up the difference by capturing the market. Their users are costing them multiple thousands of dollars and only paying them at most a few hundred. Not enough people will drop a mortgage payment on AI to make up the difference.</p>
<p>Anthropic is just one AI company, but the broad math seems to be the same for all of them.</p>
<h2 id="why-this-still-works">Why this still works</h2>
<p>But here's the part that critics don't understand.</p>
<p>People aren't investing in AI companies to make a profit. It's clear these companies will never be profitable and, because the market famously is never irrational, investors must be taking this into account.</p>
<p>Instead, these companies are kept healthy and thriving by "parental investors." Just like how a lemonade stand keeps a kid occupied on the weekend and out of trouble, generative AI companies keep a large number of business and tech brothers off the streets. You'd much rather have then doing ZYNs and Addies in a safe office setting where they can chill with their homies and learn valuable life skills.</p>
<p>These investors have, from my perspective, almost infinite money. It only makes sense that they will be able to keep investing that infinite money forever, regardless of how much money the AI companies lose.</p>
<p>The future is bright and this economy - our economy - is invincible.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Issues you will face binding to C from Java.</title><link>https://mccue.dev/pages/7-21-25-c-binding-struggles</link><description></description><pubDate>Mon, 21 Jul 0025 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Issues you will face binding to C from Java.</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Issues you will face binding to C from Java.</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
Specifically using the Foreign Function and Memory API.

<p>I've written about some of these issues before, but now I have a project I can use as an example.</p>
<p>Stick around to the end for an open challenge to the audience.</p>
<h2 id="context">Context</h2>
<p>Yu-Gi-Oh is a children's card game from Japan. Each player has "life points" and the goal of the game is to use your monsters, spells, and traps to reduce your opponent's life points to zero.</p>
<p>This game is how I first learned to read.</p>
<p>My Father likes playing a Yu-Gi-Oh game from the early 2000s called "Power of Chaos: Yugi the Destiny," named after the character in the anime who solves a puzzle and gets possessed by the spirit of an ancient Egyptian Pharaoh.</p>
<p>Since he figured out it supports multiplayer and can let me play against him, he has also started playing "Power of Chaos: Joey the Passion." This is also from the early 2000s and is named after the character in the anime who is a Japanese high school student that for some reason speaks with a Brooklyn accent.</p>
<p>Every now and then a character will die because they lost this children's card game. This got censored as them being "sent to the shadow realm," a place of eternal torture where their soul will never know peace. Much more kid friendly.</p>
<p>In my opinion the "Power of Chaos" series of games have by far the best visual, audio, and interaction design of any Yu-Gi-Oh game. This includes unofficial fan projects.</p>
<p>So something I threw on my large list of back-burner projects is to make my own Yu-Gi-Oh game that closely emulates the design of those early games.</p>
<p>Unfortunately the actual card game is crazy complicated. Every card is basically its own tiny program and there are decades of special case rulings to implement. It is well beyond the scope of what I am capable of as an individual.</p>
<p>Fortunately there is both <a href="https://github.com/Fluorohydride/ygopro-scripts">a crowdsourced repository of lua scripts</a> for all the cards and <a href="https://github.com/edo9300/ygopro-core">a community maintained engine for simulating the rules of the game</a>. This engine has <a href="https://github.com/edo9300/ygopro-core/tree/158aebe758be3c46249c75d602e3f16d63d2ef31?tab=readme-ov-file#c-api-for-clients">a relatively minimal C API</a> and is, I think, a perfect example of the kind of thing that should have bindings written for it. The depth of expertise that went into it is unrepeatable.</p>
<h2 id="problem-1-c-libraries-arent-always-pure-c">Problem 1: C libraries aren't always pure C</h2>
<p>Despite having a C API some of the headers of this particular library <a href="https://github.com/edo9300/ygopro-core/issues/168">made use of C++ features</a>. This is often ignorable in the C/C++ world since the major C compilers also support C++. It is not ignorable when you use <code>jextract</code> to generate bindings. <code>jextract</code> only supports C.</p>
<p>You could interpret this as a one-off, but my suspicion is that it's a problem that will naturally recur for libraries written in C++ that expose a C API. Especially if they are never tested in this context.</p>
<p>The solutions are to either make issues/open PRs or to enhance <code>jextract</code> to be able to support a limited subset of C++. Despite the words "limited subset" the latter is likely a nightmare pit of a task, so you should be ready to do the first.</p>
<h2 id="problem-2-you-need-different-java-code-per-platform">Problem 2: You need different Java code per-platform</h2>
<p><code>jextract</code> takes as input a C header file and spits out a folder of Java classes. These classes include information about available functions as well as the memory layouts of defined structs. Unfortunately <a href="https://faultlore.com/blah/c-isnt-a-language/">C is a protocol</a> where memory layouts can change based on both the target operating system and the underlying CPU architecture.</p>
<p>This means you need different Java code for macos-aarch64 than you do for windows-x86. Pop-quiz: <a href="https://xkcd.com/1168/">how do you do this in Maven? In Gradle?</a></p>
<p>You also need access to the target platform to generate this code. <code>jextract</code> doesn't have the <a href="https://zig.guide/build-system/cross-compilation/"><code>zig cc</code> magic that lets it compile for any platform from any platform</a>. So you are left with having to use services <a href="https://github.com/pot/boba/blob/main/.github/workflows/jextract.yml">like Github Actions</a>.</p>
<p>In the absolute best case scenario you can just swap out a source set when compiling. <code>OCG_CardData</code> might have a platform specific layout, but the generated methods and struct members will be the same.</p>
<p>If you want to have one library support all platforms you'll need to <a href="https://github.com/pot/boba/blob/main/core/src/main/java/dev/weisz/boba/terminal/Terminal.java#L10">contrive a system for selecting methods to call at runtime</a>. This can lead to some <a href="https://github.com/pot/boba/blob/main/core/src/main/java/dev/weisz/boba/terminal/MacTerminal_arm64.java">pointless duplication</a>.</p>
<h2 id="problem-3-c-libraries-are-often-special-snowflakes">Problem 3: C libraries are often special snowflakes</h2>
<p>Question: what is the Maven Central for C?</p>
<p>Answer: ha. hahaha. ha. ha. ha. ha.</p>
<p>While there are things like <a href="https://conan.io/">Conan</a> and <a href="https://github.com/microsoft/vcpkg">vcpkg</a> out in the world it's far from a given that any particular library you'd want is on them.</p>
<p>Its likely you'll end up either adding a GitHub repo as a submodule or writing a script to <a href="https://github.com/bowbahdoe/ygo/blob/main/Justfile#L5">download the repo</a> or some random <code>.zip</code>/<code>.tar.gz</code> file.</p>
<p>From there every C library has its own build instructions and flags you may or may not need to pass.</p>
<p>Pop-quiz: how do you do this in Maven? In Gradle?</p>
<h2 id="problem-4-you-need-to-figure-out-packaging">Problem 4: You need to figure out packaging</h2>
<p>From here we'll assume that the C library you are binding is going into a library. Either to be shared with the wider world or to be one module in a larger project tree.</p>
<p>Firstly, you probably need to make one artifact per target platform. In Maven repositories the way people share such artifacts is with a classifier scheme. Each artifact should be published with a <code>-macos-aarch64</code> or similar classifier and modules depending on these libraries need to select the right one.</p>
<p>Then for the actual <code>.dll</code>/<code>.so</code>/<code>.dylib</code> that is the compiled artifact for the C library you have a few options.</p>
<ol type="1">
<li>Expect the user to just have it on their machine already or install it separately.</li>
<li>Expect the user to provide it manually with <code>-Dsystem.library.path</code>.</li>
<li>Package that file into a jar and extract it dynamically at runtime.</li>
<li>Package your code as a <code>.jmod</code> and expect that to be usable.</li>
</ol>
<p>Option 1 sucks for obvious reasons.</p>
<p>Option 2 is just option 1 but without it needing to be a global system-level thing. Tools like Maven are, best I can tell, built around the concept that a "Set of Dependencies" should become a <code>--class-path</code>. You can't really have C shared libraries as automatically resolved dependencies.</p>
<p>Option 3 is what most libraries do today. <a href="https://github.com/LWJGL/lwjgl3-wiki/wiki/1.2.-Install">LWJGL has "natives" jars</a> which contain the actual shared libraries. It then uses <a href="https://github.com/LWJGL/lwjgl3/blob/master/modules/lwjgl/core/src/main/java/org/lwjgl/system/SharedLibraryLoader.java">a shim to extract the shared libraries to the filesystem</a>. This is annoying firstly because its finicky code. Extracting a file atomically to the filesystem <a href="https://github.com/LWJGL/lwjgl3/blob/master/modules/lwjgl/core/src/main/java/org/lwjgl/system/SharedLibraryLoader.java#L239">is a whole thing</a>. It also requires that you are deploying code in a context where you have a writable filesystem. This is not always the case.</p>
<p>But most importantly it annoys me because it is so clearly a forced move. If you could actually just put the shared library on the <code>-Dsystem.library.path</code> automatically in the same way other dependencies are automatically put on the <code>--class-path</code> I don't think people would be doing it. Well, that and if people weren't universally using uberjars as their deployment mechanism.</p>
<p>Option 4 I think has potential. <a href="https://github.com/bowbahdoe/ygo/blob/main/Justfile#L58">It's what I've done for the Yu-Gi-Oh bindings</a>. For those unaware, <code>.jmod</code> files have delineated locations for classes, legal metadata, configuration files, and shared libraries. This is how the JDK bundles the shared libraries needed for making things like Swing work.</p>
<p>One problem is that <code>.jmod</code>s aren't usable at runtime. You need to link them together with <code>jlink</code> to produce a JDK then use that JDK. You can technically extract the contents of a <code>.jmod</code> and put the extracted <code>classes</code> folder on the <code>--module-path</code> and <code>libs</code> on the <code>-Dsystem.library.path</code>.</p>
<p>Pop-quiz: how do you do that in Maven? In Gradle?</p>
<h2 id="problem-5-nobody-uses-the---module-path">Problem 5: Nobody uses the <code>--module-path</code></h2>
<p>In discussions about the <code>--module-path</code> the focus tends to be on one of three aspects.</p>
<ol type="1">
<li>I heard a friend of a cousin say it broke a library nearly a decade ago in Java 9.</li>
<li>It was needed to turn off deep reflection for JDK internals.</li>
<li>Wow, tooling does not support this well at all.</li>
</ol>
<p>The 3rd aspect is most relevant here because you can't really expect anyone using your library to have put it on the <code>--module-path</code>. This is unfortunate because modules are the only mechanism to group up and hide whole packages from external consumers.</p>
<p><code>jextract</code> will generate a large number of public classes which contain calls to fundamentally unsafe APIs. Not only that, unless you go through and manually allowlist functions and symbols with <code>--include-function</code> et al. it will contain a lot of stray functions you may or may not be using in your actual binding code.</p>
<p>What you would ideally want is to just not export those autogenerated classes and only export the code you wrote that wraps them up. This would be needed for someone writing <code>--enable-native-access=your.specific.module</code> to mean "I have audited or otherwise trust the producer of this module to have interacted with the native world in a way that won't crash the JVM."</p>
<p>This is in contrast to <code>--enable-native-access=ALL-UNNAMED</code> and "yeah whatever, just let me use native stuff. Who cares where it comes from."</p>
<p>Even if you don't particularly care about that story, autogenerated bindings don't make for the world's best public API.</p>
<h2 id="challenges">Challenges</h2>
<p>So with that prelude, here is the challenge for the audience.</p>
<ol type="1">
<li><p>Using your build tool of choice (Maven, Gradle, bld, Mill, etc.) replace the <a href="https://github.com/bowbahdoe/ygo/blob/main/Justfile">Justfile</a> I have to build the project. I mean replace, not do a different or worse job. Produce as a final artifact a <code>.jmod</code>, procure the C library, run <code>jextract</code>, include the proper legal metadata, etc.</p></li>
<li><p>Put it in a local maven repository and use it from a Maven project. Good luck.</p></li>
<li><p>Bonus points, actually work on the unfinished binding code. Would be appreciated, but it's also my burden to bear and not super relevant to the rest of this post.</p></li>
</ol>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Clojure as a First Language</title><link>https://mccue.dev/pages/7-14-25-clojure-as-a-first-language</link><description></description><pubDate>Tue, 15 Jul 0025 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Clojure as a First Language</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Clojure as a First Language</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
This might come as somewhat of a shock to my regular audience, but I don't only write Java.

<p>The reason I focus so much on specifically Java education is because it is often the first language people are taught. This matters for a lot of reasons, not all of which I have the page space to get in to, but crucially being taught first has a direct impact on a language's popularity.</p>
<p>I'm writing this because I think Clojure now has a real shot at becoming a first language.</p>
<h2 id="why">Why</h2>
<p>Of all the less-than-massively-popular-languages out there, Clojure is probably hurt the least by not having widespread adoption. This is in large part because it gets to piggyback on existing libraries and ecosystems.</p>
<p>Clojure is a hosted language. Clojure on the JVM can use any Java library, Clojure in the browser can use any JavaScript library, and so on. It is always good when Clojure-native libraries get written, but they've never been an absolute necessity.</p>
<p>So why pursue popularity?</p>
<h3 id="1-paper-clipping">1. Paper Clipping.</h3>
<p>A lawyer has a duty to be a zealous advocate for their client. There's a non-trivial tribal monkey aspect to wanting <strong>your</strong> programming language to be popular and, at a certain point, pursuing that end <a href="https://en.wikipedia.org/wiki/Is%E2%80%93ought_problem">has no fundamental justification</a>.</p>
<p>But we make our own meaning in life so screw it.</p>
<h3 id="2-its-better">2. It's Better.</h3>
<p>The value proposition of Clojure is different to most other languages. I'm not going to s*** Paul Graham's d*** or wax poetic about macros, but it's hard to deny that Clojure codebases tend to be quite different to those written in Python, JavaScript, Java, R, etc.</p>
<p>There are reasons to think that Clojure could be a better fit for producing certain genres of software. Popularity would therefore lead to "better" software being produced, which is reasonable to want.</p>
<p>I'm being vague on purpose here. The difference between closed and open aggregates alone could be its own essay.</p>
<h3 id="3-money">3. Money.</h3>
<p>The more people who use Clojure the more Clojure jobs there are. The more Clojure jobs there are the more secure Clojure experts can be, etc.</p>
<p>TypedClojure is a one-man-show. TypeScript is funded by Microsoft paychecks. Popularity opens the door to all sorts of support.</p>
<h2 id="how">How</h2>
<p>So to become popular you need to be someone's first language. To be someone's first language you need to be what they learned in school. This means convincing teachers and curriculum makers.</p>
<p>For CS education I think this is a lost cause. There are very well-made CS 101 courses that use lisps and <a href="https://felleisen.org/matthias/Thoughts/py.html">face cosmically stupid pushback for doing so</a>. It is hard to imagine winning that fight.</p>
<p>But people going for Computer Science degrees aren't the only people who program. When my brother got his Masters in Marine Biology he was taught R. Analyzing data, making charts, etc. <a href="https://waterwelljournal.com/a-historical-perspective-of-well-installation/">is needed for a wide variety of fields</a>.</p>
<p>I think Clojure could steal significant market share here.</p>
<p><a href="https://scicloj.github.io/noj/">Noj</a> is a collection of a bunch of data science libraries for Clojure. With what is in there you can:</p>
<ul>
<li>Load data into data frames</li>
<li>Make visualizations</li>
<li>Train ML models (including deep learning)</li>
<li>Do anything Python can do (<a href="https://scicloj.github.io/noj/noj_book.underlying_libraries.html#:~:text=Python%20bindings%20and%20interoperability">by directly calling Python libraries</a>)</li>
<li>Do anything R can do (<a href="https://scicloj.github.io/noj/noj_book.underlying_libraries.html#:~:text=R%20language%20interoperability%20and%20bindings">by directly calling R libraries</a>)</li>
<li>Do anything Wolfram can do (<a href="https://scicloj.github.io/wolframite/">by directly calling Worlfram</a>)</li>
<li>... and more</li>
</ul>
<p>This has the makings of an extremely compelling pitch.</p>
<p>The biggest missing piece, as I see it, is resources tailored to people learning Clojure as a first language.</p>
<p>Historically the vast majority of Clojure programmers have been transplants from other languages. We have books like <a href="https://www.braveclojure.com/">Clojure for the Brave and True</a> that serve this crowd, but few-to-none for people who are starting truly from scratch.</p>
<p>This has also affected the way people talk about Clojure. Keep in mind that you don't need to convince people of functional programming, homoiconicity, or anything else when it's the first thing they learn. The pitches you'd use to pull in a Ruby programmer should be kept in their lane.</p>
<p>So that's the gap. The data science people are presumably going to keep chugging away at the things they do. If you are interested in making Clojure a "First Language" give a shot at making something that fills that gap.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>A Modest Critique of Optional Handling</title><link>https://mccue.dev/pages/4-5-25-optional-critique</link><description></description><pubDate>Sat, 05 Apr 0025 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>A Modest Critique of Optional Handling</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">A Modest Critique of Optional Handling</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
`java.util.Optional` is a class that breaks peoples brains a bit.

<p>It offers a way to represent a potentially missing piece of information. If your method might not produce a result you can use an empty <code>Optional</code> to represent that.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>Optional<span class="op">&lt;</span>LocalDate<span class="op">&gt;</span> <span class="fu">birthday</span><span class="op">(</span><span class="bu">String</span> name<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="cf">switch</span> <span class="op">(</span>name<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">case</span> <span class="st">&quot;Mr. Rodgers&quot;</span> <span class="op">-&gt;</span> </span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>                Optional<span class="op">.</span><span class="fu">of</span><span class="op">(</span>LocalDate<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="dv">1928</span><span class="op">,</span> Month<span class="op">.</span><span class="fu">MARCH</span><span class="op">,</span> <span class="dv">20</span><span class="op">));</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">case</span> <span class="st">&quot;Mr. T&quot;</span> <span class="op">-&gt;</span> </span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>                Optional<span class="op">.</span><span class="fu">of</span><span class="op">(</span>LocalDate<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="dv">1952</span><span class="op">,</span> Month<span class="op">.</span><span class="fu">MAY</span><span class="op">,</span> <span class="dv">21</span><span class="op">));</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">default</span> <span class="op">-&gt;</span> </span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>                Optional<span class="op">.</span><span class="fu">empty</span><span class="op">();</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span>var name <span class="op">:</span> <span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;Mr. T&quot;</span><span class="op">,</span> <span class="st">&quot;H.R. Puffinstuff&quot;</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>        IO<span class="op">.</span><span class="fu">println</span><span class="op">(</span>name <span class="op">+</span> <span class="st">&quot;: &quot;</span> <span class="op">+</span> <span class="fu">birthday</span><span class="op">(</span>name<span class="op">));</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This has a few pros over the other standard option of returning <code>null</code>.</p>
<p>For one, Java's type system (currently) does not track <code>null</code> values as part of a type. This means that a programmer needs to infer nullability from written documentation and context clues.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>LocalDate <span class="fu">birthday</span><span class="op">(</span><span class="bu">String</span> name<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="cf">switch</span> <span class="op">(</span>name<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">case</span> <span class="st">&quot;Mr. Rodgers&quot;</span> <span class="op">-&gt;</span> </span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>                LocalDate<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="dv">1928</span><span class="op">,</span> Month<span class="op">.</span><span class="fu">MARCH</span><span class="op">,</span> <span class="dv">20</span><span class="op">);</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">case</span> <span class="st">&quot;Mr. T&quot;</span> <span class="op">-&gt;</span> </span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>                LocalDate<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="dv">1952</span><span class="op">,</span> Month<span class="op">.</span><span class="fu">MAY</span><span class="op">,</span> <span class="dv">21</span><span class="op">);</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">default</span> <span class="op">-&gt;</span> </span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>                <span class="kw">null</span><span class="op">;</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span>var name <span class="op">:</span> <span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;Mr. T&quot;</span><span class="op">,</span> <span class="st">&quot;H.R. Puffinstuff&quot;</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>        <span class="co">// .getMonth() is not always valid to call</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>        IO<span class="op">.</span><span class="fu">println</span><span class="op">(</span>name <span class="op">+</span> <span class="st">&quot;: &quot;</span> <span class="op">+</span> <span class="fu">birthday</span><span class="op">(</span>name<span class="op">).</span><span class="fu">getMonth</span><span class="op">());</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This is mitigated somewhat when an API makes use of nullability annotations. Today that requires you to use special null-aware tooling but null-aware types are <a href="https://openjdk.org/jeps/8303099">slated to come to Java proper at some point.</a></p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co">// LocalDate? in the future (probably)</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="at">@Nullable</span> LocalDate <span class="fu">birthday</span><span class="op">(</span><span class="bu">String</span> name<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="cf">switch</span> <span class="op">(</span>name<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>        <span class="cf">case</span> <span class="st">&quot;Mr. Rodgers&quot;</span> <span class="op">-&gt;</span> </span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>                LocalDate<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="dv">1928</span><span class="op">,</span> Month<span class="op">.</span><span class="fu">MARCH</span><span class="op">,</span> <span class="dv">20</span><span class="op">);</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">case</span> <span class="st">&quot;Mr. T&quot;</span> <span class="op">-&gt;</span> </span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>                LocalDate<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="dv">1952</span><span class="op">,</span> Month<span class="op">.</span><span class="fu">MAY</span><span class="op">,</span> <span class="dv">21</span><span class="op">);</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">default</span> <span class="op">-&gt;</span> </span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>                <span class="kw">null</span><span class="op">;</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span>var name <span class="op">:</span> <span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;Mr. T&quot;</span><span class="op">,</span> <span class="st">&quot;H.R. Puffinstuff&quot;</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>        <span class="co">// Tooling should catch this mistake</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>        IO<span class="op">.</span><span class="fu">println</span><span class="op">(</span>name <span class="op">+</span> <span class="st">&quot;: &quot;</span> <span class="op">+</span> <span class="fu">birthday</span><span class="op">(</span>name<span class="op">).</span><span class="fu">getMonth</span><span class="op">());</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>But null values in Java always require explicit checks to handle.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>v <span class="op">==</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="co">// or</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>v <span class="op">==</span> <span class="kw">null</span> <span class="op">?</span> <span class="kw">...</span> <span class="op">:</span> <span class="kw">...</span><span class="op">;</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a><span class="co">// or Objects.requireNonNullElse(v, ...)</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a><span class="co">// but that&#39;s just a method</span></span></code></pre></div>
<p>This makes them ill-suited to the task <code>Optional</code> was originally introduced for - being part of the customary chain of method calls that form stream operations. This is most important when an <code>Optional</code> appears in the middle of a stack of such operations, but even when the <code>Optional</code> handling is at the end it's at least aesthetic.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>Stream<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="dv">1</span><span class="op">,</span> <span class="dv">2</span><span class="op">,</span> <span class="dv">3</span><span class="op">)</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">filter</span><span class="op">(</span>x <span class="op">-&gt;</span> x <span class="op">&lt;</span> <span class="dv">2</span><span class="op">)</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">findFirst</span><span class="op">()</span> <span class="co">// Here is where we get an optional</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">orElse</span><span class="op">(</span><span class="dv">0</span><span class="op">);</span> <span class="co">// And we can preserve the method chain stack </span></span></code></pre></div>
<p>People are far more likely to remember to write the above when Java forces them to. That's the point of it.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="bu">Integer</span> first <span class="op">=</span> Stream<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="dv">1</span><span class="op">,</span> <span class="dv">2</span><span class="op">,</span> <span class="dv">3</span><span class="op">)</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">filter</span><span class="op">(</span>x <span class="op">-&gt;</span> x <span class="op">&lt;</span> <span class="dv">2</span><span class="op">)</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">findFirst</span><span class="op">();</span> </span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="co">// Not forced to handle null usually and it&#39;s aesthetically</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="co">// inconvenient. This leads to mistakes in the context of chained methods.</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>first <span class="op">==</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>    first <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>But because it "solves null" (it doesn't) it sees a lot of use. A very common pattern has been for folks to take a <code>null</code> returning method and refactor it to use optional instead.</p>
<p>When this works its generally fine, what isn't fine is how callsites are often adapted.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>User user <span class="op">=</span> <span class="fu">findUserById</span><span class="op">(</span>id<span class="op">);</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>user <span class="op">!=</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Logic</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The code above is often turned into something like the following.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>Optional<span class="op">&lt;</span>User<span class="op">&gt;</span> userOpt <span class="op">=</span> <span class="fu">findUserById</span><span class="op">(</span>id<span class="op">);</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>userOpt<span class="op">.</span><span class="fu">isPresent</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>    User user <span class="op">=</span> userOpt<span class="op">.</span><span class="fu">get</span><span class="op">();</span> <span class="co">// or .orElseThrow() if civilized</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Logic</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Callsites refactored like this are strictly worse. Often an extra intermediate variable needs to be created, that intermediate has a stupid name, and static analysis tools will either not know what is happening or have special carve out exceptions so they know "when <code>.isPresent()</code>, <code>.get()</code> is okay."</p>
<p>Those carve out exceptions may or may not also apply to other ecosystem Optional types.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="co">// It&#39;s hard to argue that java.util.Optional really deserves</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="co">// special treatment over vavr&#39;s Option, but because code like</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="co">// this exists it&#39;s going to get it.</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="bu">Option</span><span class="op">&lt;</span>User<span class="op">&gt;</span> userOpt <span class="op">=</span> <span class="fu">findUserById</span><span class="op">(</span>id<span class="op">);</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>userOpt<span class="op">.</span><span class="fu">isDefined</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>    User user <span class="op">=</span> userOpt<span class="op">.</span><span class="fu">get</span><span class="op">();</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Logic</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And the general sort of advice to deal with this is to use <code>.map</code> and <code>.ifPresent</code> - the methods that let you work with the value in an <code>Optional</code> without "unboxing" it.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="fu">findUserById</span><span class="op">(</span>id<span class="op">).</span><span class="fu">ifPresent</span><span class="op">(</span>user <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Logic</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="op">});</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="co">// or keep chaining and deal with it later</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a><span class="fu">findUserById</span><span class="op">(</span>id<span class="op">).</span><span class="fu">map</span><span class="op">(</span>User<span class="op">::</span>email<span class="op">);</span></span></code></pre></div>
<p>When this works, it can be better. It just stops working when the code you want to run that involves the value might throw a checked exception - <code>.ifPresent</code> and friends cannot cope with that.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="fu">findUserById</span><span class="op">(</span>id<span class="op">).</span><span class="fu">ifPresent</span><span class="op">(</span>user <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Logic</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span><span class="kw">...</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>        <span class="co">// Difficult to know what to do.</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>        <span class="co">// Do we wrap the exception?</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>        <span class="fu">callRemoteAPI</span><span class="op">();</span>  </span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Logic</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a><span class="op">});</span></span></code></pre></div>
<p>It also stops working when you have multiple <code>Optional</code>s, at least from a readability perspective.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="fu">findUserById</span><span class="op">(</span>idA<span class="op">).</span><span class="fu">ifPresent</span><span class="op">(</span>userA <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>    <span class="fu">findUserById</span><span class="op">(</span>idB<span class="op">).</span><span class="fu">ifPresent</span><span class="op">(</span>userB <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>        <span class="fu">findUserById</span><span class="op">(</span>idC<span class="op">).</span><span class="fu">ifPresent</span><span class="op">(</span>userC <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>            <span class="co">// Logic</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">});</span> </span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">});</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a><span class="op">});</span></span></code></pre></div>
<p>And also when you want to mutate some local variables relevant to the rest of the function.</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> existingUsers <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="fu">findUserById</span><span class="op">(</span>id<span class="op">).</span><span class="fu">ifPresent</span><span class="op">(</span>user <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Logic</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>    existingUsers<span class="op">++;</span> <span class="co">// Lambda rules - does not work</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Logic</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a><span class="op">});</span></span></code></pre></div>
<p>And just in general, beyond the small and clean usages, I think using these methods makes code net worse.</p>
<p>What I suggest, and I think people don't consider specifically because they are viewing <code>Optional</code> as a replacement for <code>null</code>, is to use <code>.orElse(null)</code> and write the rest of the code in the method like normal.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>User user <span class="op">=</span> <span class="fu">findUserById</span><span class="op">(</span>id<span class="op">).</span><span class="fu">orElse</span><span class="op">(</span><span class="kw">null</span><span class="op">);</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>user <span class="op">!=</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Logic</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Static analysis tools can eat "local variable known to sometimes be <code>null</code>" for breakfast and there are no problems handling checked exceptions, multiple optionals, or mutating local state. It's a much more seamless refactor.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> existingUsers <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>User userA <span class="op">=</span> <span class="fu">findUserById</span><span class="op">(</span>idA<span class="op">).</span><span class="fu">orElse</span><span class="op">(</span><span class="kw">null</span><span class="op">);</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>User userB <span class="op">=</span> <span class="fu">findUserById</span><span class="op">(</span>idB<span class="op">).</span><span class="fu">orElse</span><span class="op">(</span><span class="kw">null</span><span class="op">);</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>User userC <span class="op">=</span> <span class="fu">findUserById</span><span class="op">(</span>idC<span class="op">).</span><span class="fu">orElse</span><span class="op">(</span><span class="kw">null</span><span class="op">);</span></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>userA <span class="op">!=</span> <span class="kw">null</span> <span class="op">&amp;&amp;</span> userB <span class="op">!=</span> <span class="kw">null</span> <span class="op">&amp;&amp;</span> userC <span class="op">!=</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Logic</span></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>    existingUsers<span class="op">++;</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span><span class="kw">...</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a>        <span class="fu">callRemoteAPI</span><span class="op">();</span>  </span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Logic</span></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The fact that it might be <code>null</code> also becomes explicit in the source code at every usage site, which is a strict improvement over the equivalent code with <code>null</code> returning methods.</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> existingUsers <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="co">// Back to inferring from context or documentation</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>User userA <span class="op">=</span> <span class="fu">findUserById</span><span class="op">(</span>idA<span class="op">);</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>User userB <span class="op">=</span> <span class="fu">findUserById</span><span class="op">(</span>idB<span class="op">);</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>User userC <span class="op">=</span> <span class="fu">findUserById</span><span class="op">(</span>idC<span class="op">);</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>userA <span class="op">!=</span> <span class="kw">null</span> <span class="op">&amp;&amp;</span> userB <span class="op">!=</span> <span class="kw">null</span> <span class="op">&amp;&amp;</span> userC <span class="op">!=</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Logic</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>    existingUsers<span class="op">++;</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span><span class="kw">...</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>        <span class="fu">callRemoteAPI</span><span class="op">();</span>  </span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Logic</span></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>There are more bike sheds to have on <code>Optional</code>, don't get me wrong, I just want to strongly encourage you to reconsider blanket advice to "avoid <code>.isPresent/.get</code>, use <code>.map/.ifPresent</code>" and highlight that <code>.orElse</code> is useful for more than valid default values.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Go's HTTP Server Patterns in Java 25</title><link>https://mccue.dev/pages/4-5-25-go-http-server</link><description></description><pubDate>Sat, 05 Apr 0025 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Go's HTTP Server Patterns in Java 25</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Go's HTTP Server Patterns in Java 25</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
I'm not a professional Go programmer so feel free to correct me on anything.

<p>The rest of this post is going to follow the example program from <a href="https://go.dev/doc/articles/wiki/">this piece of Go Documentation</a>. I'm even going to straight rip a lot of the prose.</p>
<p>My intent is to highlight how you can do spiritually similar things in Java.</p>
<p>The code in this guide, <a href="https://mail.openjdk.org/pipermail/amber-dev/2025-January/009198.html">god willing</a>, will work unaltered in Java 25.</p>
<h2 id="prerequisites">Prerequisites</h2>
<ul>
<li><a href="https://adoptium.net/temurin/releases/?version=24">Java</a>.</li>
<li>Some Libraries. The repo at the end will have them all in a folder. Java dependency management is a whole adventure, for now just follow along the ride.</li>
</ul>
<h2 id="getting-started">Getting Started</h2>
<p>Make a new directory for this tutorial and cd into it:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> mkdir javawiki</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> cd javawiki</span></code></pre></div>
<p>Create a file named <code>Wiki.java</code>, open it in your favorite editor, and add the following lines:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="data-structures">Data Structures</h2>
<p>A wiki consists of a series of interconnected pages, each of which has a title and a body (the page content). Here, we define Page as a record with two components representing the title and body.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Page</span><span class="op">(</span><span class="bu">String</span> title<span class="op">,</span> <span class="dt">byte</span><span class="op">[]</span> body<span class="op">)</span> <span class="op">{}</span></span></code></pre></div>
<p>The <code>Page</code> record describes how page data will be stored in memory. But what about persistent storage? We can address that by creating a save method on Page:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Page</span><span class="op">(</span><span class="bu">String</span> title<span class="op">,</span> <span class="dt">byte</span><span class="op">[]</span> body<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">save</span><span class="op">()</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>        var filename <span class="op">=</span> title <span class="op">+</span> <span class="st">&quot;.txt&quot;</span><span class="op">;</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>        Files<span class="op">.</span><span class="fu">write</span><span class="op">(</span>Path<span class="op">.</span><span class="fu">of</span><span class="op">(</span>filename<span class="op">),</span> body<span class="op">);</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The <code>save</code> method throws an <code>IOException</code> to let the application handle it should anything go wrong while writing the file. If all goes well, <code>Page.save()</code> will return without throwing.</p>
<p>In addition to saving pages, we will want to load pages, too:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Page</span><span class="op">(</span><span class="bu">String</span> title<span class="op">,</span> <span class="dt">byte</span><span class="op">[]</span> body<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">save</span><span class="op">()</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>        var filename <span class="op">=</span> title <span class="op">+</span> <span class="st">&quot;.txt&quot;</span><span class="op">;</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>        Files<span class="op">.</span><span class="fu">write</span><span class="op">(</span>Path<span class="op">.</span><span class="fu">of</span><span class="op">(</span>filename<span class="op">),</span> body<span class="op">);</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> Page <span class="fu">load</span><span class="op">(</span><span class="bu">String</span> title<span class="op">)</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>        var filename <span class="op">=</span> title <span class="op">+</span> <span class="st">&quot;.txt&quot;</span><span class="op">;</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>        var body <span class="op">=</span> Files<span class="op">.</span><span class="fu">readAllBytes</span><span class="op">(</span>Path<span class="op">.</span><span class="fu">of</span><span class="op">(</span>filename<span class="op">));</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Page</span><span class="op">(</span>title<span class="op">,</span> body<span class="op">);</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The method <code>load</code> constructs the file name from the title parameter, reads the file's contents into a new variable body, and returns a reference to a <code>Page</code> object.</p>
<p>At this point we have a simple data structure and the ability to save to and load from a file. Let's update the main method to test what we've written:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    var p1 <span class="op">=</span> <span class="kw">new</span> <span class="fu">Page</span><span class="op">(</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;TestPage&quot;</span><span class="op">,</span> </span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;This is a sample Page.&quot;</span><span class="op">.</span><span class="fu">getBytes</span><span class="op">(</span>StandardCharsets<span class="op">.</span><span class="fu">UTF_8</span><span class="op">)</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>    p1<span class="op">.</span><span class="fu">save</span><span class="op">();</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>    var p2 <span class="op">=</span> Page<span class="op">.</span><span class="fu">load</span><span class="op">(</span><span class="st">&quot;TestPage&quot;</span><span class="op">);</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>    IO<span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="kw">new</span> <span class="bu">String</span><span class="op">(</span>p2<span class="op">.</span><span class="fu">body</span><span class="op">,</span> StandardCharsets<span class="op">.</span><span class="fu">UTF_8</span><span class="op">));</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>After executing this code, a file named <code>TestPage.txt</code> would be created, containing the contents of p1. The file would then be read into p2, and its <code>body</code> component printed to the screen.</p>
<p>You can run the program like this:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> java Wiki.java</span></code></pre></div>
<p><a href="https://github.com/bowbahdoe/wiki-example/blob/main/part1/Wiki.java">Click here to view the code we've written so far.</a></p>
<h2 id="introducing-the-jdkhttpserver-module-an-interlude">Introducing the jdk.httpserver module (an interlude)</h2>
<p>Here's a full working example of a simple web server:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">module jdk</span><span class="op">.</span><span class="im">httpserver</span><span class="op">;</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">handler</span><span class="op">(</span>HttpExchange exchange<span class="op">)</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>    exchange<span class="op">.</span><span class="fu">sendResponseHeaders</span><span class="op">(</span><span class="dv">200</span><span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">try</span> <span class="op">(</span>var os <span class="op">=</span> exchange<span class="op">.</span><span class="fu">getResponseBody</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>        os<span class="op">.</span><span class="fu">write</span><span class="op">(</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;Hi there, I love %s!&quot;</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>                        <span class="op">.</span><span class="fu">formatted</span><span class="op">(</span>exchange<span class="op">.</span><span class="fu">getRequestURI</span><span class="op">().</span><span class="fu">getPath</span><span class="op">().</span><span class="fu">substring</span><span class="op">(</span><span class="dv">1</span><span class="op">))</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>                        <span class="op">.</span><span class="fu">getBytes</span><span class="op">(</span>StandardCharsets<span class="op">.</span><span class="fu">UTF_8</span><span class="op">)</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a>    var server <span class="op">=</span> HttpServer<span class="op">.</span><span class="fu">create</span><span class="op">(</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="bu">InetSocketAddress</span><span class="op">(</span><span class="dv">8080</span><span class="op">),</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a>            <span class="dv">0</span></span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true" tabindex="-1"></a>    server<span class="op">.</span><span class="fu">createContext</span><span class="op">(</span><span class="st">&quot;/&quot;</span><span class="op">,</span> <span class="kw">this</span><span class="op">::</span>handler<span class="op">);</span></span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true" tabindex="-1"></a>    server<span class="op">.</span><span class="fu">start</span><span class="op">();</span></span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The <code>main</code> method begins with a call to <code>HttpServer.create</code>, which creates an http server that will listen on port 8080. (Don't worry about its second parameter, <code>0</code>, for now.)</p>
<p>Then <code>server.createContext</code> tells the server to handle all requests to the web root ("/") with handler.</p>
<p>It then calls `server.start(). This method will block until the program is terminated.</p>
<p>If you run this program and access the URL:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="ex">http://localhost:8080/monkeys</span></span></code></pre></div>
<p>the program would present a page containing:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ex">Hi</span> there, I love monkeys!</span></code></pre></div>
<h2 id="introducing-the-devmccuejdkhttpserver-module-an-interlude-within-an-interlude">Introducing the dev.mccue.jdk.httpserver module (an interlude within an interlude)</h2>
<p>The <code>jdk.httpserver</code> module does not see as widespread use as Go's equivalent. As such, I think there are some ways to improve the API that should be rolled into the standard library at some point.</p>
<p>I put the most important of these - a <code>Body</code> abstraction - <a href="https://central.sonatype.com/artifact/dev.mccue/jdk-httpserver">into a library</a>. I'm going to ignore how to procure libraries in Java for the moment, but suspend your disbelief in the meantime.</p>
<p>With this library the server example above becomes the following:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">module jdk</span><span class="op">.</span><span class="im">httpserver</span><span class="op">;</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">module dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">jdk</span><span class="op">.</span><span class="im">httpserver</span><span class="op">;</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">handler</span><span class="op">(</span>HttpExchange exchange<span class="op">)</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>    HttpExchanges<span class="op">.</span><span class="fu">sendResponse</span><span class="op">(</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>            exchange<span class="op">,</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>            <span class="dv">200</span><span class="op">,</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>            Body<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;Hi there, I love %s!&quot;</span><span class="op">.</span><span class="fu">formatted</span><span class="op">(</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a>                    exchange<span class="op">.</span><span class="fu">getRequestURI</span><span class="op">().</span><span class="fu">getPath</span><span class="op">().</span><span class="fu">substring</span><span class="op">(</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>            <span class="op">))</span></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a>    var server <span class="op">=</span> HttpServer<span class="op">.</span><span class="fu">create</span><span class="op">(</span></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="bu">InetSocketAddress</span><span class="op">(</span><span class="dv">8080</span><span class="op">),</span></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true" tabindex="-1"></a>            <span class="dv">0</span></span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true" tabindex="-1"></a>    server<span class="op">.</span><span class="fu">createContext</span><span class="op">(</span><span class="st">&quot;/&quot;</span><span class="op">,</span> <span class="kw">this</span><span class="op">::</span>handler<span class="op">);</span></span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true" tabindex="-1"></a>    server<span class="op">.</span><span class="fu">start</span><span class="op">();</span></span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="using-jdkhttpserver-to-serve-wiki-pages">Using jdk.httpserver to serve wiki pages</h2>
<p>Let's create a handler, viewHandler that will allow users to view a wiki page. It will handle URLs prefixed with "/view/".</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">viewHandler</span><span class="op">(</span>HttpExchange exchange<span class="op">)</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>    var title <span class="op">=</span> exchange<span class="op">.</span><span class="fu">getRequestURI</span><span class="op">()</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">getPath</span><span class="op">()</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">substring</span><span class="op">(</span><span class="st">&quot;/view/&quot;</span><span class="op">.</span><span class="fu">length</span><span class="op">());</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>    var p <span class="op">=</span> Page<span class="op">.</span><span class="fu">load</span><span class="op">(</span>title<span class="op">);</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>    HttpExchanges<span class="op">.</span><span class="fu">sendResponse</span><span class="op">(</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>            exchange<span class="op">,</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>            <span class="dv">200</span><span class="op">,</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>            Body<span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;&lt;h1&gt;%s&lt;/h1&gt;&lt;div&gt;%s&lt;/div&gt;&quot;</span></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>                            <span class="op">.</span><span class="fu">formatted</span><span class="op">(</span></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a>                                    p<span class="op">.</span><span class="fu">title</span><span class="op">,</span> </span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a>                                    <span class="kw">new</span> <span class="bu">String</span><span class="op">(</span>p<span class="op">.</span><span class="fu">body</span><span class="op">,</span> StandardCharsets<span class="op">.</span><span class="fu">UTF_8</span><span class="op">)</span></span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a>                            <span class="op">)</span></span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a>            <span class="op">)</span></span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>To use this handler, we rewrite our main function to initialize an <code>HttpServer</code> using the <code>viewHandler</code> to handle any requests under the path <code>/view/</code>.</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>    var server <span class="op">=</span> HttpServer<span class="op">.</span><span class="fu">create</span><span class="op">(</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="bu">InetSocketAddress</span><span class="op">(</span><span class="dv">8080</span><span class="op">),</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>            <span class="dv">0</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>    server<span class="op">.</span><span class="fu">createContext</span><span class="op">(</span><span class="st">&quot;/view/&quot;</span><span class="op">,</span> <span class="kw">this</span><span class="op">::</span>viewHandler<span class="op">);</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>    server<span class="op">.</span><span class="fu">start</span><span class="op">();</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><a href="https://github.com/bowbahdoe/wiki-example/blob/main/part2/Wiki.java">Click here to view the code we've written so far.</a></p>
<p>Let's create some page data (as test.txt), compile our code, and try serving a wiki page.</p>
<p>Open test.txt file in your editor, and save the string "Hello world" (without quotes) in it.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="ex">java</span> <span class="at">--module-path</span> lib <span class="at">--add-modules</span> ALL-MODULE-PATH Wiki.java</span></code></pre></div>
<p>With this web server running, a visit to <code>http://localhost:8080/view/test</code> should show a page titled "test" containing the words "Hello world".</p>
<h2 id="editing-pages">Editing Pages</h2>
<p>A wiki is not a wiki without the ability to edit pages. Let's create two new handlers: one named <code>editHandler</code> to display an 'edit page' form, and the other named <code>saveHandler</code> to save the data entered via the form.</p>
<p>First, we add them to <code>main()</code>:</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>    var server <span class="op">=</span> HttpServer<span class="op">.</span><span class="fu">create</span><span class="op">(</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="bu">InetSocketAddress</span><span class="op">(</span><span class="dv">8700</span><span class="op">),</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>            <span class="dv">0</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>    server<span class="op">.</span><span class="fu">createContext</span><span class="op">(</span><span class="st">&quot;/view/&quot;</span><span class="op">,</span> <span class="kw">this</span><span class="op">::</span>viewHandler<span class="op">);</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>    server<span class="op">.</span><span class="fu">createContext</span><span class="op">(</span><span class="st">&quot;/edit/&quot;</span><span class="op">,</span> <span class="kw">this</span><span class="op">::</span>editHandler<span class="op">);</span></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>    server<span class="op">.</span><span class="fu">createContext</span><span class="op">(</span><span class="st">&quot;/save/&quot;</span><span class="op">,</span> <span class="kw">this</span><span class="op">::</span>saveHandler<span class="op">);</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a>    server<span class="op">.</span><span class="fu">start</span><span class="op">();</span></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The method <code>editHandler</code> loads the page (or, if it doesn't exist, create an empty Page record), and displays an HTML form.</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">editHandler</span><span class="op">(</span>HttpExchange exchange<span class="op">)</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>    var title <span class="op">=</span> exchange<span class="op">.</span><span class="fu">getRequestURI</span><span class="op">()</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">getPath</span><span class="op">()</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">substring</span><span class="op">(</span><span class="st">&quot;/edit/&quot;</span><span class="op">.</span><span class="fu">length</span><span class="op">());</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>    Page p<span class="op">;</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>        p <span class="op">=</span> Page<span class="op">.</span><span class="fu">load</span><span class="op">(</span>title<span class="op">);</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span>NoSuchFileException e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>        p <span class="op">=</span> <span class="kw">new</span> <span class="fu">Page</span><span class="op">(</span>title<span class="op">,</span> <span class="kw">new</span> <span class="dt">byte</span><span class="op">[]{});</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>    HttpExchanges<span class="op">.</span><span class="fu">sendResponse</span><span class="op">(</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>            exchange<span class="op">,</span></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a>            <span class="dv">200</span><span class="op">,</span></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a>            Body<span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;&quot;&quot;</span></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a>                    <span class="op">&lt;</span>h1<span class="op">&gt;</span>Editing <span class="op">%</span>s<span class="op">&lt;/</span>h1<span class="op">&gt;</span></span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a>                    <span class="op">&lt;</span>form action<span class="op">=</span><span class="st">&quot;/save/%s&quot;</span> method<span class="op">=</span><span class="st">&quot;POST&quot;</span><span class="op">&gt;</span></span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a>                        <span class="op">&lt;</span>textarea name<span class="op">=</span><span class="st">&quot;body&quot;</span><span class="op">&gt;%</span>s<span class="op">&lt;/</span>textarea<span class="op">&gt;&lt;</span>br<span class="op">&gt;</span></span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a>                        <span class="op">&lt;</span>input type<span class="op">=</span><span class="st">&quot;submit&quot;</span> value<span class="op">=</span><span class="st">&quot;Save&quot;</span><span class="op">&gt;</span></span>
<span id="cb16-20"><a href="#cb16-20" aria-hidden="true" tabindex="-1"></a>                    <span class="op">&lt;/</span>form<span class="op">&gt;</span></span>
<span id="cb16-21"><a href="#cb16-21" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;&quot;&quot;.formatted(</span></span>
<span id="cb16-22"><a href="#cb16-22" aria-hidden="true" tabindex="-1"></a>                            p<span class="op">.</span><span class="fu">title</span><span class="op">,</span></span>
<span id="cb16-23"><a href="#cb16-23" aria-hidden="true" tabindex="-1"></a>                            p<span class="op">.</span><span class="fu">title</span><span class="op">,</span></span>
<span id="cb16-24"><a href="#cb16-24" aria-hidden="true" tabindex="-1"></a>                            <span class="kw">new</span> <span class="bu">String</span><span class="op">(</span>p<span class="op">.</span><span class="fu">body</span><span class="op">,</span> StandardCharsets<span class="op">.</span><span class="fu">UTF_8</span><span class="op">)</span></span>
<span id="cb16-25"><a href="#cb16-25" aria-hidden="true" tabindex="-1"></a>                    <span class="op">)</span></span>
<span id="cb16-26"><a href="#cb16-26" aria-hidden="true" tabindex="-1"></a>            <span class="op">)</span></span>
<span id="cb16-27"><a href="#cb16-27" aria-hidden="true" tabindex="-1"></a>    )<span class="op">;</span></span>
<span id="cb16-28"><a href="#cb16-28" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This function will work fine, but all that hard-coded HTML is ugly. Of course, there is a better way.</p>
<p>(I mean honestly the bigger issue is XSS vulnerabilities, but whatever. Following along.)</p>
<h1 id="the-comsamskivertjmustache-module">The com.samskivert.jmustache module</h1>
<p><a href="https://central.sonatype.com/artifact/com.samskivert/jmustache"><code>com.samskivert.jmustache</code></a> is a library available in the Java ecosystem. We can use it to keep the HTML in a separate file, allowing us to change the layout of our edit page without modifying the underlying Java code.</p>
<p>First, we must add <code>com.samskivert.jmustache</code> to the list of imports. Again, we are glancing over how you procure libraries for this tutorial.</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">module jdk</span><span class="op">.</span><span class="im">httpserver</span><span class="op">;</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">module dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">jdk</span><span class="op">.</span><span class="im">httpserver</span><span class="op">;</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">module com</span><span class="op">.</span><span class="im">samskivert</span><span class="op">.</span><span class="im">jmustache</span><span class="op">;</span></span></code></pre></div>
<p>Let's create a template file containing the HTML form. Open a new file named <code>edit.html</code>, and add the following lines:</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;h1&gt;</span>Editing {{title}}<span class="kw">&lt;/h1&gt;</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;form</span> <span class="er">action</span><span class="ot">=</span><span class="st">&quot;/save/{{title}}&quot;</span> <span class="er">method</span><span class="ot">=</span><span class="st">&quot;POST&quot;</span><span class="kw">&gt;</span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">&lt;div&gt;&lt;textarea</span> <span class="er">name</span><span class="ot">=</span><span class="st">&quot;body&quot;</span> <span class="er">rows</span><span class="ot">=</span><span class="st">&quot;20&quot;</span> <span class="er">cols</span><span class="ot">=</span><span class="st">&quot;80&quot;</span><span class="kw">&gt;</span>{{body}}<span class="kw">&lt;/textarea&gt;&lt;/div&gt;</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">&lt;div&gt;&lt;input</span> <span class="er">type</span><span class="ot">=</span><span class="st">&quot;submit&quot;</span> <span class="er">value</span><span class="ot">=</span><span class="st">&quot;Save&quot;</span><span class="kw">&gt;&lt;/div&gt;</span></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;/form&gt;</span></span></code></pre></div>
<p>Modify <code>editHandler</code> to use the template, instead of the hard-coded HTML:</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">editHandler</span><span class="op">(</span>HttpExchange exchange<span class="op">)</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>    var title <span class="op">=</span> exchange<span class="op">.</span><span class="fu">getRequestURI</span><span class="op">()</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">getPath</span><span class="op">()</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">substring</span><span class="op">(</span><span class="st">&quot;/edit/&quot;</span><span class="op">.</span><span class="fu">length</span><span class="op">());</span></span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a>    Page p<span class="op">;</span></span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a>        p <span class="op">=</span> Page<span class="op">.</span><span class="fu">load</span><span class="op">(</span>title<span class="op">);</span></span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span>NoSuchFileException e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a>        p <span class="op">=</span> <span class="kw">new</span> <span class="fu">Page</span><span class="op">(</span>title<span class="op">,</span> <span class="kw">new</span> <span class="dt">byte</span><span class="op">[]{});</span></span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb19-12"><a href="#cb19-12" aria-hidden="true" tabindex="-1"></a>    var template <span class="op">=</span> Mustache<span class="op">.</span><span class="fu">compiler</span><span class="op">()</span></span>
<span id="cb19-13"><a href="#cb19-13" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">compile</span><span class="op">(</span>Files<span class="op">.</span><span class="fu">readString</span><span class="op">(</span>Path<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;edit.html&quot;</span><span class="op">)));</span></span>
<span id="cb19-14"><a href="#cb19-14" aria-hidden="true" tabindex="-1"></a>    HttpExchanges<span class="op">.</span><span class="fu">sendResponse</span><span class="op">(</span></span>
<span id="cb19-15"><a href="#cb19-15" aria-hidden="true" tabindex="-1"></a>            exchange<span class="op">,</span></span>
<span id="cb19-16"><a href="#cb19-16" aria-hidden="true" tabindex="-1"></a>            <span class="dv">200</span><span class="op">,</span></span>
<span id="cb19-17"><a href="#cb19-17" aria-hidden="true" tabindex="-1"></a>            Body<span class="op">.</span><span class="fu">of</span><span class="op">(</span>template<span class="op">.</span><span class="fu">execute</span><span class="op">(</span><span class="bu">Map</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb19-18"><a href="#cb19-18" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;title&quot;</span><span class="op">,</span> p<span class="op">.</span><span class="fu">title</span><span class="op">,</span></span>
<span id="cb19-19"><a href="#cb19-19" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;body&quot;</span><span class="op">,</span> <span class="kw">new</span> <span class="bu">String</span><span class="op">(</span>p<span class="op">.</span><span class="fu">body</span><span class="op">,</span> StandardCharsets<span class="op">.</span><span class="fu">UTF_8</span><span class="op">)</span></span>
<span id="cb19-20"><a href="#cb19-20" aria-hidden="true" tabindex="-1"></a>            <span class="op">)))</span></span>
<span id="cb19-21"><a href="#cb19-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb19-22"><a href="#cb19-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Since we're working with templates now, let's create a template for our <code>viewHandler</code> called <code>view.html</code>:</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;h1&gt;</span>{{title}}<span class="kw">&lt;/h1&gt;</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;p&gt;</span>[<span class="kw">&lt;a</span> <span class="er">href</span><span class="ot">=</span><span class="st">&quot;/edit/{{title}}&quot;</span><span class="kw">&gt;</span>edit<span class="kw">&lt;/a&gt;</span>]<span class="kw">&lt;/p&gt;</span></span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;div&gt;</span>{{body}}<span class="kw">&lt;/div&gt;</span></span></code></pre></div>
<p>Modify <code>viewHandler</code> accordingly:</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">viewHandler</span><span class="op">(</span>HttpExchange exchange<span class="op">)</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>    var title <span class="op">=</span> exchange<span class="op">.</span><span class="fu">getRequestURI</span><span class="op">()</span></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">getPath</span><span class="op">()</span></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">substring</span><span class="op">(</span><span class="st">&quot;/view/&quot;</span><span class="op">.</span><span class="fu">length</span><span class="op">());</span></span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>    var p <span class="op">=</span> Page<span class="op">.</span><span class="fu">load</span><span class="op">(</span>title<span class="op">);</span></span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>    var template <span class="op">=</span> Mustache<span class="op">.</span><span class="fu">compiler</span><span class="op">()</span></span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">compile</span><span class="op">(</span>Files<span class="op">.</span><span class="fu">readString</span><span class="op">(</span>Path<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;view.html&quot;</span><span class="op">)));</span></span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a>    HttpExchanges<span class="op">.</span><span class="fu">sendResponse</span><span class="op">(</span></span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a>            exchange<span class="op">,</span></span>
<span id="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a>            <span class="dv">200</span><span class="op">,</span></span>
<span id="cb21-11"><a href="#cb21-11" aria-hidden="true" tabindex="-1"></a>            Body<span class="op">.</span><span class="fu">of</span><span class="op">(</span>template<span class="op">.</span><span class="fu">execute</span><span class="op">(</span><span class="bu">Map</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb21-12"><a href="#cb21-12" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;title&quot;</span><span class="op">,</span> p<span class="op">.</span><span class="fu">title</span><span class="op">,</span></span>
<span id="cb21-13"><a href="#cb21-13" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;body&quot;</span><span class="op">,</span> <span class="kw">new</span> <span class="bu">String</span><span class="op">(</span>p<span class="op">.</span><span class="fu">body</span><span class="op">,</span> StandardCharsets<span class="op">.</span><span class="fu">UTF_8</span><span class="op">)</span></span>
<span id="cb21-14"><a href="#cb21-14" aria-hidden="true" tabindex="-1"></a>            <span class="op">)))</span></span>
<span id="cb21-15"><a href="#cb21-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb21-16"><a href="#cb21-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Notice that we've used almost exactly the same templating code in both handlers. Let's remove this duplication by moving the templating code to its own function:</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">renderTemplate</span><span class="op">(</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>        HttpExchange exchange<span class="op">,</span></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>        <span class="bu">String</span> tmpl<span class="op">,</span></span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>        Page p</span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a>    var template <span class="op">=</span> Mustache<span class="op">.</span><span class="fu">compiler</span><span class="op">()</span></span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">compile</span><span class="op">(</span>Files<span class="op">.</span><span class="fu">readString</span><span class="op">(</span>Path<span class="op">.</span><span class="fu">of</span><span class="op">(</span>tmpl<span class="op">)));</span></span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a>    HttpExchanges<span class="op">.</span><span class="fu">sendResponse</span><span class="op">(</span></span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a>            exchange<span class="op">,</span></span>
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a>            <span class="dv">200</span><span class="op">,</span></span>
<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a>            Body<span class="op">.</span><span class="fu">of</span><span class="op">(</span>template<span class="op">.</span><span class="fu">execute</span><span class="op">(</span><span class="bu">Map</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;title&quot;</span><span class="op">,</span> p<span class="op">.</span><span class="fu">title</span><span class="op">,</span></span>
<span id="cb22-13"><a href="#cb22-13" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;body&quot;</span><span class="op">,</span> <span class="kw">new</span> <span class="bu">String</span><span class="op">(</span>p<span class="op">.</span><span class="fu">body</span><span class="op">,</span> StandardCharsets<span class="op">.</span><span class="fu">UTF_8</span><span class="op">)</span></span>
<span id="cb22-14"><a href="#cb22-14" aria-hidden="true" tabindex="-1"></a>            <span class="op">)))</span></span>
<span id="cb22-15"><a href="#cb22-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb22-16"><a href="#cb22-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And modify the handlers to use that function:</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">viewHandler</span><span class="op">(</span>HttpExchange exchange<span class="op">)</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>    var title <span class="op">=</span> exchange<span class="op">.</span><span class="fu">getRequestURI</span><span class="op">()</span></span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">getPath</span><span class="op">()</span></span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">substring</span><span class="op">(</span><span class="st">&quot;/view/&quot;</span><span class="op">.</span><span class="fu">length</span><span class="op">());</span></span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a>    var p <span class="op">=</span> Page<span class="op">.</span><span class="fu">load</span><span class="op">(</span>title<span class="op">);</span></span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a>    <span class="fu">renderTemplate</span><span class="op">(</span>exchange<span class="op">,</span> <span class="st">&quot;view&quot;</span><span class="op">,</span> p<span class="op">);</span></span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-9"><a href="#cb23-9" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">editHandler</span><span class="op">(</span>HttpExchange exchange<span class="op">)</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb23-10"><a href="#cb23-10" aria-hidden="true" tabindex="-1"></a>    var title <span class="op">=</span> exchange<span class="op">.</span><span class="fu">getRequestURI</span><span class="op">()</span></span>
<span id="cb23-11"><a href="#cb23-11" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">getPath</span><span class="op">()</span></span>
<span id="cb23-12"><a href="#cb23-12" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">substring</span><span class="op">(</span><span class="st">&quot;/edit/&quot;</span><span class="op">.</span><span class="fu">length</span><span class="op">());</span></span>
<span id="cb23-13"><a href="#cb23-13" aria-hidden="true" tabindex="-1"></a>    Page p<span class="op">;</span></span>
<span id="cb23-14"><a href="#cb23-14" aria-hidden="true" tabindex="-1"></a>    <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb23-15"><a href="#cb23-15" aria-hidden="true" tabindex="-1"></a>        p <span class="op">=</span> Page<span class="op">.</span><span class="fu">load</span><span class="op">(</span>title<span class="op">);</span></span>
<span id="cb23-16"><a href="#cb23-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span>NoSuchFileException e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb23-17"><a href="#cb23-17" aria-hidden="true" tabindex="-1"></a>        p <span class="op">=</span> <span class="kw">new</span> <span class="fu">Page</span><span class="op">(</span>title<span class="op">,</span> <span class="kw">new</span> <span class="dt">byte</span><span class="op">[]{});</span></span>
<span id="cb23-18"><a href="#cb23-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb23-19"><a href="#cb23-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-20"><a href="#cb23-20" aria-hidden="true" tabindex="-1"></a>    <span class="fu">renderTemplate</span><span class="op">(</span>exchange<span class="op">,</span> <span class="st">&quot;edit&quot;</span><span class="op">,</span> p<span class="op">);</span></span>
<span id="cb23-21"><a href="#cb23-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><a href="https://github.com/bowbahdoe/wiki-example/blob/main/part3/Wiki.java">Click here to view the code we've written so far.</a></p>
<h2 id="handling-non-existent-pages">Handling non-existent pages</h2>
<p>What if you visit <code>/view/APageThatDoesntExist</code> You'll get no response. This is because <code>Page.load</code> errors. Instead, if the requested Page doesn't exist, it should redirect the client to the edit Page so the content may be created:</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">viewHandler</span><span class="op">(</span>HttpExchange exchange<span class="op">)</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>    var title <span class="op">=</span> exchange<span class="op">.</span><span class="fu">getRequestURI</span><span class="op">()</span></span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">getPath</span><span class="op">()</span></span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">substring</span><span class="op">(</span><span class="st">&quot;/view/&quot;</span><span class="op">.</span><span class="fu">length</span><span class="op">());</span></span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a>    Page p<span class="op">;</span></span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a>        p <span class="op">=</span> Page<span class="op">.</span><span class="fu">load</span><span class="op">(</span>title<span class="op">);</span></span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span>NoSuchFileException _<span class="op">)</span> <span class="op">{</span></span>
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a>        exchange<span class="op">.</span><span class="fu">getResponseHeaders</span><span class="op">()</span></span>
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;Location&quot;</span><span class="op">,</span> <span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;/edit/&quot;</span> <span class="op">+</span> title<span class="op">));</span></span>
<span id="cb24-11"><a href="#cb24-11" aria-hidden="true" tabindex="-1"></a>        HttpExchanges<span class="op">.</span><span class="fu">sendResponse</span><span class="op">(</span>exchange<span class="op">,</span> <span class="dv">302</span><span class="op">,</span> Body<span class="op">.</span><span class="fu">empty</span><span class="op">());</span></span>
<span id="cb24-12"><a href="#cb24-12" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span><span class="op">;</span></span>
<span id="cb24-13"><a href="#cb24-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb24-14"><a href="#cb24-14" aria-hidden="true" tabindex="-1"></a>    <span class="fu">renderTemplate</span><span class="op">(</span>exchange<span class="op">,</span> <span class="st">&quot;view&quot;</span><span class="op">,</span> p<span class="op">);</span></span>
<span id="cb24-15"><a href="#cb24-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>To do this we send an HTTP status code of 302 and a include Location header in the response.</p>
<h2 id="saving-pages">Saving pages</h2>
<p>The function saveHandler will handle the submission of forms located on the edit pages. To parse the form body we are going to add another library - <a href="https://central.sonatype.com/artifact/dev.mccue/urlparameters">dev.mccue.urlparameters</a>.</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">module dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">urlparameters</span><span class="op">;</span></span></code></pre></div>
<div class="sourceCode" id="cb26"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">saveHandler</span><span class="op">(</span>HttpExchange exchange<span class="op">)</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>    var title <span class="op">=</span> exchange<span class="op">.</span><span class="fu">getRequestURI</span><span class="op">()</span></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">getPath</span><span class="op">()</span></span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">substring</span><span class="op">(</span><span class="st">&quot;/save/&quot;</span><span class="op">.</span><span class="fu">length</span><span class="op">());</span></span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a>    var body <span class="op">=</span> UrlParameters<span class="op">.</span><span class="fu">parse</span><span class="op">(</span></span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="bu">String</span><span class="op">(</span></span>
<span id="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a>                    exchange<span class="op">.</span><span class="fu">getRequestBody</span><span class="op">().</span><span class="fu">readAllBytes</span><span class="op">(),</span></span>
<span id="cb26-8"><a href="#cb26-8" aria-hidden="true" tabindex="-1"></a>                    StandardCharsets<span class="op">.</span><span class="fu">UTF_8</span></span>
<span id="cb26-9"><a href="#cb26-9" aria-hidden="true" tabindex="-1"></a>            <span class="op">)</span></span>
<span id="cb26-10"><a href="#cb26-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">).</span><span class="fu">firstValue</span><span class="op">(</span><span class="st">&quot;body&quot;</span><span class="op">).</span><span class="fu">orElseThrow</span><span class="op">();</span></span>
<span id="cb26-11"><a href="#cb26-11" aria-hidden="true" tabindex="-1"></a>    var p <span class="op">=</span> <span class="kw">new</span> <span class="fu">Page</span><span class="op">(</span>title<span class="op">,</span> body<span class="op">.</span><span class="fu">getBytes</span><span class="op">(</span>StandardCharsets<span class="op">.</span><span class="fu">UTF_8</span><span class="op">));</span></span>
<span id="cb26-12"><a href="#cb26-12" aria-hidden="true" tabindex="-1"></a>    p<span class="op">.</span><span class="fu">save</span><span class="op">();</span></span>
<span id="cb26-13"><a href="#cb26-13" aria-hidden="true" tabindex="-1"></a>    exchange<span class="op">.</span><span class="fu">getResponseHeaders</span><span class="op">()</span></span>
<span id="cb26-14"><a href="#cb26-14" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;Location&quot;</span><span class="op">,</span> <span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;/view/&quot;</span> <span class="op">+</span> title<span class="op">));</span></span>
<span id="cb26-15"><a href="#cb26-15" aria-hidden="true" tabindex="-1"></a>    HttpExchanges<span class="op">.</span><span class="fu">sendResponse</span><span class="op">(</span>exchange<span class="op">,</span> <span class="dv">302</span><span class="op">,</span> Body<span class="op">.</span><span class="fu">empty</span><span class="op">());</span></span>
<span id="cb26-16"><a href="#cb26-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><a href="https://github.com/bowbahdoe/wiki-example/blob/main/part4/Wiki.java">Click here to view the code we've written so far.</a></p>
<h2 id="etc">Etc.</h2>
<p>There is more in the Go tutorial, including caching templates, making sure there aren't path traversal vulnerabilities (which, very important!), and some other potpourri.</p>
<p>But the purpose of this is just to illustrate that Java is capable of the same sort of "simple" web development that Go is known for. I'm leaving that stuff (and introducing a proper <a href="https://github.com/gorilla/mux">mux</a>) as exercises for you the reader.</p>
<p>And just as a note: If you dig into the <code>jdk.httpserver</code> module you will see some "for development only" warnings around it. This is because the actual server implementation in the JDK is mostly there to serve the <code>jwebserver</code> tool. (<code>jwebserver</code> is more or less equivalent to Python's <code>http.server</code>) You can seamlessly swap to using a production quality server like <a href="https://github.com/jetty/jetty.project">Jetty</a> and <a href="https://github.com/robaho/httpserver">others</a> by adding the appropriate dependencies.</p>
<hr />
<p>Tell me all about your past traumas with Java in the comments below.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Groyper Big Balls Vibe Codes away Social Security</title><link>https://mccue.dev/pages/4-2-25-vibe-code</link><description></description><pubDate>Wed, 02 Apr 0025 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Groyper Big Balls Vibe Codes away Social Security</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Groyper Big Balls Vibe Codes away Social Security</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 

<p>"<a href="https://en.wikipedia.org/wiki/Groypers">Groyper</a>" is the term used to describe the followers of <a href="https://en.wikipedia.org/wiki/Nick_Fuentes">Nick Fuentes</a>.</p>
<p>Nick Fuentes is a "Hitlerist," meaning he agrees with <a href="https://arc.net/l/quote/tjvieaaj">specifically the policies of Adolf Hitler</a>. You might also know him as the <a href="https://www.newsweek.com/nick-fuentes-your-body-my-choice-address-leaked-doxxing-donald-trump-1984492">"Your Body, My Choice"</a> guy.</p>
<p>"<a href="https://www.newsweek.com/who-big-balls-teen-doge-engineer-edward-coristine-2027698">Big Balls</a>" is the name of one of the young fascists recruited by DOGE. He gained particular notoriety for being young, <a href="https://d.newsweek.com/en/full/2583634/edward-corristine-elon-musk.webp?w=790&amp;f=e547ac66d0342a36b0b5066fcedaeee0">very punchable,</a> and having a head turning nickname.</p>
<p>Another DOGE fascist is Gavin Kliger. Gavin Kliger <a href="https://www.reuters.com/world/us/staffer-with-elon-musks-doge-amplified-white-supremacists-online-2025-02-07/">is very much a Groyper.</a></p>
<p>They are all Groypers.</p>
<p>This is why when DOGE fascist Marko Elez posted "Just for the record, I was racist before it was cool" and "Normalize Indian hate" Elon Musk <a href="https://www.bbc.com/news/articles/c93q625y04wo">went out of his way to keep him on the team.</a></p>
<p>DOGE has <a href="https://www.wired.com/story/doge-rebuild-social-security-administration-cobol-benefits/">announced plans to rewrite the computer systems of the Social Security Administration</a>. The timeline they give for this endeavor is several months.</p>
<p>This will not work out for the people who are dependent on their Social Security checks. The way in which it won't work out is t.b.d., but there are a few possibilities that come to mind.</p>
<p>For one, they are supposedly replacing tens of millions of lines of COBOL. That is an amount of code far beyond anyone's capacity to fully understand, let alone recreate, in a few months.</p>
<p>So best case scenario they miss something. More likely scenario they don't care if they "miss" something. These are fascists. They are predisposed to make things worse on purpose out of <a href="https://en.wikipedia.org/wiki/Pia%C8%9Ba_Roman%C4%83_metro_station#:~:text=Ceau%C8%99escu%20was%20concerned%20that%20workers%20and%20students%20were%20starting%20to%20gain%20weight%20and%20needed%20more%20exercise%2C%20hence%20they%20should%20walk%20instead%20of%20taking%20the%20metro%20train">condescension</a>, intentional malice, or some other goblin emotion.</p>
<p>Then there is the overarching plot-line of dismantling the social safety net. The template for those sorts of actions tends to be to take over a public service, make it worse, then privatize it as a solution. This would fit that template.</p>
<p>The stated plan is to accomplish this <a href="https://www.wired.com/story/doge-rebuild-social-security-administration-cobol-benefits/">with AI</a>. The practice of using AI to produce large chunks of code has been christened by the venture capital tech space as "<a href="https://en.wikipedia.org/wiki/Vibe_coding">Vibe Coding</a>."</p>
<p><a href="https://www.youtube.com/watch?v=v7UcVPO4y3c">Training programs</a> have already sprung up seeking to capitalize on the term, reinforcing the convenient smuggling it gives to obvious negligence.</p>
<p>As was the pattern with Big Data and "Web 3" before it, the programming and tech world seems to have few antibodies to nonsensical claims of future potential. Even skepticism will end up wrapped in the framing of "Well this is obviously the future, but."</p>
<p>Social Security's systems are reportedly currently in COBOL, but the plan is for them to be rewritten into Java.</p>
<p>There would be, in a saner time, reasons for that. Java can run on what we would call "commodity hardware" and there is a statistically younger pool of trained people to pull on to write it. It wouldn't be the first system "modernized" in such a way and doing so could make longer term maintenance simpler in a few ways.</p>
<p>But while COBOL Mainframes have a casual reputation of being relics of the past, they are some of the only systems in the world where you can have leader + follower replication of the results of individual CPU instructions.</p>
<p>IBM, <a href="https://en.wikipedia.org/wiki/IBM_and_the_Holocaust">the "Made the Holocaust Possible" company</a>, has an online transaction system called CICS that I have been informed is "nuclear attack resistant." I rest easy believing that, if we ever have the privilege to suffer through a <a href="https://en.wikipedia.org/wiki/Threads_(1984_film)">Threads</a>, my bank account will have its correct balance.</p>
<p>Unless they found a well-thought-out plan tucked in the desk of a more competent person they fired, these considerations will not be approached with nuance.</p>
<p>I mean, presuming there is a plan at all. It could just be, intentionally or not, a distraction while they pull out more important copper wiring like <a href="https://www.npr.org/2025/02/27/nx-s1-5307239/fdic-jobs-bank-regulator-trump-doge-elon-musk">the FDIC</a>.</p>
<hr />
<p>If I'm found dead it wasn't a suicide. If I'm disappeared find and rescue me. Leave comments wherever.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Life Altering Postgresql Patterns</title><link>https://mccue.dev/pages/3-11-25-life-altering-postgresql-patterns</link><description></description><pubDate>Tue, 11 Mar 0025 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Life Altering Postgresql Patterns</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Life Altering Postgresql Patterns</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
Believe it or not, I don't think that title is clickbait. 

<p>There is a set of things that you can do when working with a Postgres database which I have found made my and my coworker's lives much more pleasant. Each one is by itself small, but in aggregate have a noticeable effect.</p>
<h2 id="use-uuid-primary-keys">Use UUID primary keys</h2>
<p>UUIDs have downsides</p>
<ul>
<li>Truly random UUIDs doesn't sort well (and this has implications for indexes)</li>
<li>They take up more space than sequential ids (space being your cheapest resource)</li>
</ul>
<p>But I've found those to be far outweighed by the upsides</p>
<ul>
<li>You don't need to coordinate with the database to produce one.</li>
<li>They are safe to share externally.</li>
</ul>
<div class="sourceCode" id="cb1"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">TABLE</span> person(</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">id</span> uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> gen_random_uuid() <span class="kw">primary</span> <span class="kw">key</span>,</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    name text <span class="kw">not</span> <span class="kw">null</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>)</span></code></pre></div>
<h2 id="give-everything-created_at-and-updated_at">Give everything created_at and updated_at</h2>
<p>It's not a full history, but knowing when a record was created or last changed is a useful breadcrumb when debugging. Its also something you can't retroactively get unless you were recording it.</p>
<p>So just always slap a <code>created_at</code> and <code>updated_at</code> on your tables. You can maintain <code>updated_at</code> automatically with a trigger.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">TABLE</span> person(</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">id</span> uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> gen_random_uuid() <span class="kw">primary</span> <span class="kw">key</span>,</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    created_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    updated_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    name text <span class="kw">not</span> <span class="kw">null</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>);</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">FUNCTION</span> set_current_timestamp_updated_at()</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>    RETURNS <span class="kw">TRIGGER</span> <span class="kw">AS</span> $$</span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="kw">DECLARE</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>_new <span class="dt">record</span>;</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a><span class="cf">BEGIN</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>  _new <span class="op">:=</span> <span class="kw">NEW</span>;</span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>  _new.<span class="ot">&quot;updated_at&quot;</span> <span class="op">=</span> now();</span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a><span class="kw">RETURN</span> _new;</span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a><span class="cf">END</span>;</span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>$$ LANGUAGE plpgsql;</span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">TRIGGER</span> set_person_updated_at</span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>    <span class="kw">BEFORE</span> <span class="kw">UPDATE</span> <span class="kw">ON</span> person</span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a>    <span class="cf">FOR</span> <span class="kw">EACH</span> <span class="kw">ROW</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">EXECUTE</span> <span class="kw">PROCEDURE</span> set_current_timestamp_updated_at();</span></code></pre></div>
<p>You need to create the trigger for each table, but you only need to create the function once.</p>
<h2 id="on-update-restrict-on-delete-restrict">on update <strong>restrict</strong> on delete <strong>restrict</strong></h2>
<p>When you make a foreign key constraint on a table, always mark it with <code>on update restrict on delete restrict</code>.</p>
<p>This makes it so that if you try and delete the referenced row you will get an error. Storage is cheap, recovering data is a nightmare. Better to error than do something like <code>cascade</code>.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">TABLE</span> person(</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">id</span> uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> gen_random_uuid() <span class="kw">primary</span> <span class="kw">key</span>,</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    created_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    updated_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    name text <span class="kw">not</span> <span class="kw">null</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>);</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">TABLE</span> pet(</span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">id</span> uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> gen_random_uuid() <span class="kw">primary</span> <span class="kw">key</span>,</span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>    created_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>    updated_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>    name text <span class="kw">not</span> <span class="kw">null</span>,</span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>    owner_id uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">references</span> person(<span class="kw">id</span>)</span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">update</span> <span class="kw">restrict</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">delete</span> <span class="kw">restrict</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>);</span></code></pre></div>
<h2 id="use-schemas">Use schemas</h2>
<p>By default, every table in Postgres will go into the "<code>public</code>" schema. This is <em>fine</em>, but you are missing out if you don't take advantage of your ability to make new schemas.</p>
<p>Schemas work as namespaces for tables and for any moderate to large app you are going to have a lot of tables. You can do joins and have relationships between tables in different schemas so there isn't much of a downside.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">SCHEMA</span> vet;</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">TABLE</span> vet.person(</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">id</span> uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> gen_random_uuid() <span class="kw">primary</span> <span class="kw">key</span>,</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>    created_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    updated_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>    name text <span class="kw">not</span> <span class="kw">null</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>);</span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">TABLE</span> vet.pet(</span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">id</span> uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> gen_random_uuid() <span class="kw">primary</span> <span class="kw">key</span>,</span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>    created_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>    updated_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>    name text <span class="kw">not</span> <span class="kw">null</span>,</span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>    owner_id uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">references</span> vet.person(<span class="kw">id</span>)</span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">update</span> <span class="kw">restrict</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">delete</span> <span class="kw">restrict</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>);</span></code></pre></div>
<h2 id="enum-tables">Enum Tables</h2>
<p>There are a lot of ways to make "enums" in sql. One is to use the actual "<a href="https://www.postgresql.org/docs/current/datatype-enum.html">enum types</a>," another is to use a <a href="https://www.postgresql.org/docs/current/ddl-constraints.html">check constraint</a>.</p>
<p>The pattern introduced to me <a href="https://hasura.io/">by Hasura</a> was enum tables.</p>
<p>Have a table with some <code>text</code> value as a primary key and make columns in other tables reference it with a foreign key.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">TABLE</span> vet.pet_kind(</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="fu">value</span> text <span class="kw">not</span> <span class="kw">null</span> <span class="kw">primary</span> <span class="kw">key</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>);</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="kw">INSERT</span> <span class="kw">INTO</span> vet.pet_kind(<span class="fu">value</span>)</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="kw">VALUES</span> (<span class="st">&#39;dog&#39;</span>), (<span class="st">&#39;cat&#39;</span>), (<span class="st">&#39;bird&#39;</span>);</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">TABLE</span> vet.pet(</span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">id</span> uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> gen_random_uuid() <span class="kw">primary</span> <span class="kw">key</span>,</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>    created_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>    updated_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>    owner_id uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">references</span> vet.person(<span class="kw">id</span>)</span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">update</span> <span class="kw">restrict</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">delete</span> <span class="kw">restrict</span>,</span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>    kind text <span class="kw">not</span> <span class="kw">null</span> <span class="kw">references</span> vet.pet_kind(<span class="fu">value</span>)</span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">update</span> <span class="kw">restrict</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">delete</span> <span class="kw">restrict</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a>);</span></code></pre></div>
<p>This way you can insert into a table to add more allowed values or attach metadata like a comment to explain what each value means.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">TABLE</span> vet.pet_kind(</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    <span class="fu">value</span> text <span class="kw">not</span> <span class="kw">null</span> <span class="kw">primary</span> <span class="kw">key</span>,</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">comment</span> text <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> <span class="st">&#39;&#39;</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>);</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="kw">INSERT</span> <span class="kw">INTO</span> vet.pet_kind(<span class="fu">value</span>, <span class="kw">comment</span>)</span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a><span class="kw">VALUES</span> </span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>    (<span class="st">&#39;dog&#39;</span>, <span class="st">&#39;A Canine&#39;</span>),</span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>    (<span class="st">&#39;cat&#39;</span>, <span class="st">&#39;A Feline&#39;</span>),</span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>    (<span class="st">&#39;bird&#39;</span>, <span class="st">&#39;A 50 Year Commitment&#39;</span>);</span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">TABLE</span> vet.pet(</span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">id</span> uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> gen_random_uuid() <span class="kw">primary</span> <span class="kw">key</span>,</span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a>    created_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a>    updated_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a>    owner_id uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">references</span> vet.person(<span class="kw">id</span>)</span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">update</span> <span class="kw">restrict</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">delete</span> <span class="kw">restrict</span>,</span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a>    kind text <span class="kw">not</span> <span class="kw">null</span> <span class="kw">references</span> vet.pet_kind(<span class="fu">value</span>)</span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">update</span> <span class="kw">restrict</span></span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">delete</span> <span class="kw">restrict</span></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a>);</span></code></pre></div>
<h2 id="name-your-tables-singularly">Name your tables singularly</h2>
<p>This isn't even Postgres specific, just please name your tables using the singular form of a noun.</p>
<p><code>SELECT * FROM pets</code> might seem nicer than <code>SELECT * FROM pet</code> but the moment you start doing anything more interesting with your queries you will notice that your queries are actually working in terms of individual rows.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">FROM</span> pet</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- It&#39;s a cruel coincidence that in english an &quot;s&quot;</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- suffix can sometimes work both as a plural</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="co">-- and a possessive, but notice how the where clause</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a><span class="co">-- is asserting a condition about a single row.</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a><span class="kw">WHERE</span> pet.name <span class="op">=</span> <span class="st">&#39;sally&#39;</span> </span></code></pre></div>
<p>The deeper you dig the more annoying edge cases you'll run into with plural table names. Just name your tables the same as what an individual row in that table represents.</p>
<h2 id="mechanically-name-join-tables">Mechanically name join tables</h2>
<p>Sometimes there are sensible names to give "join tables" - tables which form the basis for "many to many" relationships between data - but often there isn't. In those cases don't hesitate to just concatenate the names of the tables you are joining between.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">TABLE</span> vet.person(</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">id</span> uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> gen_random_uuid() <span class="kw">primary</span> <span class="kw">key</span>,</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>    created_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>    updated_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now()</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>);</span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">TABLE</span> vet.pet(</span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">id</span> uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> gen_random_uuid() <span class="kw">primary</span> <span class="kw">key</span>,</span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>    created_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>    updated_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now()</span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>);</span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a><span class="co">-- pet_owner would work in this context, but</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a><span class="co">-- I just want to demonstrate the table_a_table_b naming scheme</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">TABLE</span> vet.person_pet(</span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">id</span> uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> gen_random_uuid() <span class="kw">primary</span> <span class="kw">key</span>,</span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a>    created_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true" tabindex="-1"></a>    updated_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true" tabindex="-1"></a>    person_id uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">references</span> vet.person(<span class="kw">id</span>)</span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">update</span> <span class="kw">restrict</span></span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">delete</span> <span class="kw">restrict</span>,</span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true" tabindex="-1"></a>    pet_id uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">references</span> vet.pet(<span class="kw">id</span>)</span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">update</span> <span class="kw">restrict</span></span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">delete</span> <span class="kw">restrict</span></span>
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true" tabindex="-1"></a>);</span>
<span id="cb8-26"><a href="#cb8-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-27"><a href="#cb8-27" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">UNIQUE</span> <span class="kw">INDEX</span> <span class="kw">ON</span> vet.person_pet(person_id, pet_id);</span></code></pre></div>
<h2 id="almost-always-soft-delete">Almost always soft delete</h2>
<p>I will reiterate that storage is cheap and recovering data is a nightmare.</p>
<p>If you have some domain specific need to delete (or otherwise mark as irrelevant) some data, use a nullable <code>timestamptz</code> column. If there is a timestamp filled in, that's when it was deleted. If there is no timestamp it isn't deleted yet.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">TABLE</span> vet.prescription(</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">id</span> uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> gen_random_uuid() <span class="kw">primary</span> <span class="kw">key</span>,</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>    created_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>    updated_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>    pet_id uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">references</span> vet.pet(<span class="kw">id</span>)</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>             <span class="kw">on</span> <span class="kw">update</span> <span class="kw">restrict</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>             <span class="kw">on</span> <span class="kw">delete</span> <span class="kw">restrict</span>,</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>    issued_at timestamptz <span class="kw">not</span> <span class="kw">null</span>,</span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>    <span class="co">-- Instead of deleting a prescription,</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>    <span class="co">-- explicitly mark when it was revoked</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>    revoked_at timestamptz</span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>);</span></code></pre></div>
<p>Even outside the context of a soft delete, timestamps are usually more useful than a boolean. If you want to know whether something happened, you generally also want to know when it happened.</p>
<h2 id="represent-statuses-as-a-log">Represent statuses as a log</h2>
<p>It is very tempting to represent the status of something as a single column. You submit some paperwork and it has a <code>status</code> of <code>submitted</code>. Someone starts to look at it then it transitions to <code>in_review</code>. From there maybe its <code>rejected</code> or <code>approved</code>.</p>
<p>There are two problems with this</p>
<ol type="1">
<li>You might actually care about when it was <code>approved</code>, or by whom.</li>
<li>You might receive this information out-of-order.</li>
</ol>
<p>Webhooks are a prime example of the 2nd situation. There's no way in the laws of physics to be sure you'll get events in exactly the right order.</p>
<p>To handle this you should have a table where each row represents the status of the thing at a given point in time. Instead of overloading <code>created_at</code> or <code>updated_at</code> for this, have an explicit <code>valid_at</code> which says when that information is valid for.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">TABLE</span> vet.adoption_approval_status(</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>    <span class="fu">value</span> text <span class="kw">not</span> <span class="kw">null</span> <span class="kw">primary</span> <span class="kw">key</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>);</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="kw">INSERT</span> <span class="kw">INTO</span> vet.adoption_approval_status(<span class="fu">value</span>)</span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a><span class="kw">VALUES</span> (<span class="st">&#39;submitted&#39;</span>), (<span class="st">&#39;in_review&#39;</span>), (<span class="st">&#39;rejected&#39;</span>), (<span class="st">&#39;approved&#39;</span>);</span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">TABLE</span> vet.adoption_approval(</span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">id</span> uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> gen_random_uuid() <span class="kw">primary</span> <span class="kw">key</span>,</span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>    created_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a>    updated_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a>    person_id uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">references</span> vet.person(<span class="kw">id</span>)</span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">update</span> <span class="kw">restrict</span></span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">delete</span> <span class="kw">restrict</span>,</span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a>    status text <span class="kw">not</span> <span class="kw">null</span> <span class="kw">references</span> vet.adoption_approval_status(<span class="fu">value</span>)</span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">update</span> <span class="kw">restrict</span></span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">delete</span> <span class="kw">restrict</span>,</span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a>    valid_at timestamptz <span class="kw">not</span> <span class="kw">null</span></span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true" tabindex="-1"></a>);</span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">INDEX</span> <span class="kw">ON</span> vet.adoption_approval(person_id, valid_at <span class="kw">DESC</span>);</span></code></pre></div>
<p>Just having an index on <code>valid_at</code> can work for a while, but eventually your queries will get too slow. There are a lot of ways to handle this, but the one we've found that works the best is to have an explicit <code>latest</code> column with a cheeky unique index and trigger to make sure that only the row with the newest <code>valid_at</code> is the <code>latest</code> one.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">TABLE</span> vet.adoption_approval(</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">id</span> uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> gen_random_uuid() <span class="kw">primary</span> <span class="kw">key</span>,</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>    created_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>    updated_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>    person_id uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">references</span> vet.person(<span class="kw">id</span>)</span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">update</span> <span class="kw">restrict</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">delete</span> <span class="kw">restrict</span>,</span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>    status text <span class="kw">not</span> <span class="kw">null</span> <span class="kw">references</span> vet.adoption_approval_status(<span class="fu">value</span>)</span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">update</span> <span class="kw">restrict</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">delete</span> <span class="kw">restrict</span>,</span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>    valid_at timestamptz <span class="kw">not</span> <span class="kw">null</span>,</span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>    latest <span class="dt">boolean</span> <span class="kw">default</span> <span class="kw">false</span></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a>);</span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">INDEX</span> <span class="kw">ON</span> vet.adoption_approval(person_id, valid_at <span class="kw">DESC</span>);</span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true" tabindex="-1"></a><span class="co">-- Conditional unique index makes sure we only have one latest</span></span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">UNIQUE</span> <span class="kw">INDEX</span> <span class="kw">ON</span> vet.adoption_approval(person_id, latest)</span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true" tabindex="-1"></a><span class="kw">WHERE</span> latest <span class="op">=</span> <span class="kw">true</span>;</span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true" tabindex="-1"></a><span class="co">-- Then a trigger to keep latest up to date</span></span>
<span id="cb11-22"><a href="#cb11-22" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">OR</span> <span class="kw">REPLACE</span> <span class="kw">FUNCTION</span> vet.set_adoption_approval_latest()</span>
<span id="cb11-23"><a href="#cb11-23" aria-hidden="true" tabindex="-1"></a> RETURNS <span class="kw">trigger</span></span>
<span id="cb11-24"><a href="#cb11-24" aria-hidden="true" tabindex="-1"></a> LANGUAGE plpgsql</span>
<span id="cb11-25"><a href="#cb11-25" aria-hidden="true" tabindex="-1"></a><span class="kw">AS</span> $function$</span>
<span id="cb11-26"><a href="#cb11-26" aria-hidden="true" tabindex="-1"></a><span class="cf">BEGIN</span></span>
<span id="cb11-27"><a href="#cb11-27" aria-hidden="true" tabindex="-1"></a>    <span class="kw">UPDATE</span> vet.adoption_approval</span>
<span id="cb11-28"><a href="#cb11-28" aria-hidden="true" tabindex="-1"></a>    <span class="kw">SET</span> latest <span class="op">=</span> <span class="kw">false</span></span>
<span id="cb11-29"><a href="#cb11-29" aria-hidden="true" tabindex="-1"></a>    <span class="kw">WHERE</span> latest <span class="op">=</span> <span class="kw">true</span> <span class="kw">and</span> person_id <span class="op">=</span> <span class="kw">NEW</span>.person_id;</span>
<span id="cb11-30"><a href="#cb11-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-31"><a href="#cb11-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">UPDATE</span> vet.adoption_approval</span>
<span id="cb11-32"><a href="#cb11-32" aria-hidden="true" tabindex="-1"></a>    <span class="kw">SET</span> latest <span class="op">=</span> <span class="kw">true</span></span>
<span id="cb11-33"><a href="#cb11-33" aria-hidden="true" tabindex="-1"></a>    <span class="kw">WHERE</span> <span class="kw">id</span> <span class="op">=</span> (</span>
<span id="cb11-34"><a href="#cb11-34" aria-hidden="true" tabindex="-1"></a>        <span class="kw">SELECT</span> <span class="kw">id</span> </span>
<span id="cb11-35"><a href="#cb11-35" aria-hidden="true" tabindex="-1"></a>        <span class="kw">FROM</span> vet.adoption_approval </span>
<span id="cb11-36"><a href="#cb11-36" aria-hidden="true" tabindex="-1"></a>        <span class="kw">WHERE</span> person_id <span class="op">=</span> <span class="kw">NEW</span>.person_id</span>
<span id="cb11-37"><a href="#cb11-37" aria-hidden="true" tabindex="-1"></a>        <span class="kw">ORDER</span> <span class="kw">BY</span> valid_at <span class="kw">DESC</span> </span>
<span id="cb11-38"><a href="#cb11-38" aria-hidden="true" tabindex="-1"></a>        <span class="kw">LIMIT</span> <span class="dv">1</span></span>
<span id="cb11-39"><a href="#cb11-39" aria-hidden="true" tabindex="-1"></a>    );</span>
<span id="cb11-40"><a href="#cb11-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-41"><a href="#cb11-41" aria-hidden="true" tabindex="-1"></a>    <span class="kw">RETURN</span> <span class="kw">null</span>;</span>
<span id="cb11-42"><a href="#cb11-42" aria-hidden="true" tabindex="-1"></a><span class="cf">END</span>;</span>
<span id="cb11-43"><a href="#cb11-43" aria-hidden="true" tabindex="-1"></a>$function$;</span>
<span id="cb11-44"><a href="#cb11-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-45"><a href="#cb11-45" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">TRIGGER</span> adoption_approval_insert_trigger</span>
<span id="cb11-46"><a href="#cb11-46" aria-hidden="true" tabindex="-1"></a>    <span class="kw">AFTER</span> <span class="kw">INSERT</span> <span class="kw">ON</span> vet.adoption_approval</span>
<span id="cb11-47"><a href="#cb11-47" aria-hidden="true" tabindex="-1"></a>    <span class="cf">FOR</span> <span class="kw">EACH</span> <span class="kw">ROW</span></span>
<span id="cb11-48"><a href="#cb11-48" aria-hidden="true" tabindex="-1"></a>    <span class="kw">EXECUTE</span> <span class="kw">FUNCTION</span> vet.set_adoption_approval_latest();</span></code></pre></div>
<h2 id="mark-special-rows-with-a-system_id">Mark special rows with a <code>system_id</code></h2>
<p>It's not uncommon to end up with "special rows." By this I mean rows in a table that the rest of your system will rely on the presence of to build up behavior.</p>
<p>All rows in an enum table are like this, but you will also end up with rows in tables of otherwise normal "generated during the course of normal use" rows. For these, give them a special <code>system_id</code>.</p>
<p>Unique indexes don't mind multiple rows with null values, so you can make a unique index on this <code>system_id</code> and look up your special rows later as you need to.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">TABLE</span> vet.contact_info(</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">id</span> uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> gen_random_uuid() <span class="kw">primary</span> <span class="kw">key</span>,</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>    created_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>    updated_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>    person_id uuid <span class="kw">references</span> vet.person(<span class="kw">id</span>)</span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">update</span> <span class="kw">restrict</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>                <span class="kw">on</span> <span class="kw">delete</span> <span class="kw">restrict</span>,</span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>    mailing_address text <span class="kw">not</span> <span class="kw">null</span>,</span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>    system_id text</span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>);</span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">UNIQUE</span> <span class="kw">INDEX</span> <span class="kw">ON</span> vet.contact_info(system_id);</span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a><span class="co">-- Not hard to imagine wanting to build functionality that</span></span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a><span class="co">-- automatically contacts the CDC for cases of rabies or similar,</span></span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true" tabindex="-1"></a><span class="co">-- but maybe every other bit of contact_info in the system is</span></span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true" tabindex="-1"></a><span class="co">-- for more &quot;normal&quot; purposes</span></span>
<span id="cb12-18"><a href="#cb12-18" aria-hidden="true" tabindex="-1"></a><span class="kw">INSERT</span> <span class="kw">INTO</span> vet.contact_info(system_id, mailing_address)</span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true" tabindex="-1"></a><span class="kw">VALUES</span> (<span class="st">&#39;cdc&#39;</span>, <span class="st">&#39;4770 Buford Highway, NE&#39;</span>);</span></code></pre></div>
<h2 id="use-views-sparingly">Use views sparingly</h2>
<p>Views are amazing and terrible.</p>
<p>They are amazing in their ability to wrap up a relatively complex or error-prone query into something that looks basically like a table.</p>
<p>They are terrible in that removing obsolete columns requires a drop and recreation, which can become a nightmare when you build views on views. The query planner also seems to have trouble seeing through them in general.</p>
<p>So do use views, but only as many as you need and be <a href="https://www.youtube.com/watch?v=CLnADKgurvc">very wary</a> of building views on views.</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">TABLE</span> vet.prescription(</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">id</span> uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> gen_random_uuid() <span class="kw">primary</span> <span class="kw">key</span>,</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>    created_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>    updated_at timestamptz <span class="kw">not</span> <span class="kw">null</span> <span class="kw">default</span> now(),</span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>    pet_id uuid <span class="kw">not</span> <span class="kw">null</span> <span class="kw">references</span> vet.pet(<span class="kw">id</span>)</span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>             <span class="kw">on</span> <span class="kw">update</span> <span class="kw">restrict</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>             <span class="kw">on</span> <span class="kw">delete</span> <span class="kw">restrict</span>,</span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>    issued_at timestamptz <span class="kw">not</span> <span class="kw">null</span>,</span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>    <span class="co">-- Instead of deleting a prescription,</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>    <span class="co">-- explicitly mark when it was revoked</span></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>    revoked_at timestamptz</span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a>);</span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">INDEX</span> <span class="kw">ON</span> vet.prescription(revoked_at);</span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a><span class="co">-- There are pros and cons to having this view</span></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">VIEW</span> vet.active_prescription <span class="kw">AS</span></span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">SELECT</span></span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a>        vet.prescription.<span class="kw">id</span>,</span>
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true" tabindex="-1"></a>        vet.prescription.created_at,</span>
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true" tabindex="-1"></a>        vet.prescription.updated_at,</span>
<span id="cb13-22"><a href="#cb13-22" aria-hidden="true" tabindex="-1"></a>        vet.prescription.pet_id,</span>
<span id="cb13-23"><a href="#cb13-23" aria-hidden="true" tabindex="-1"></a>        vet.prescription.issued_at</span>
<span id="cb13-24"><a href="#cb13-24" aria-hidden="true" tabindex="-1"></a>    <span class="kw">FROM</span></span>
<span id="cb13-25"><a href="#cb13-25" aria-hidden="true" tabindex="-1"></a>        vet.prescription</span>
<span id="cb13-26"><a href="#cb13-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">WHERE</span> </span>
<span id="cb13-27"><a href="#cb13-27" aria-hidden="true" tabindex="-1"></a>        vet.prescription.revoked_at <span class="kw">IS</span> <span class="kw">NULL</span>;</span></code></pre></div>
<h2 id="json-queries">JSON Queries</h2>
<p>You might have heard that Postgres "supports JSON." This is true, but I had mostly heard it in the context of storing and querying JSON. If you want a table with some blob of info slap a <code>jsonb</code> column on one your tables.</p>
<p>That is neat, but I've gotten way more mileage out of using JSON as the result of a query. This has definite downsides like losing type information, needing to realize your results all at once, and the overhead of writing into json.</p>
<p>But the giant upside is that you can get all the information you want from the database in <strong>one trip</strong>, no cartesian product nightmares or N+1 problems in sight.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">SELECT</span> jsonb_build_object(</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>  <span class="st">&#39;id&#39;</span>, vet.person.<span class="kw">id</span>,</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>  <span class="st">&#39;name&#39;</span>, vet.person.name,</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>  <span class="st">&#39;pets&#39;</span>, <span class="dt">array</span>(</span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">SELECT</span> jsonb_build_object(</span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>      <span class="st">&#39;id&#39;</span>, vet.pet.<span class="kw">id</span>,</span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>      <span class="st">&#39;name&#39;</span>, vet.pet.name,</span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>      <span class="st">&#39;prescriptions&#39;</span>, <span class="dt">array</span>(</span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">SELECT</span> jsonb_build_object(</span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a>          <span class="st">&#39;issued_at&#39;</span>, vet.prescription.issued_at</span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a>        )</span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a>        <span class="kw">FROM</span> vet.prescription</span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a>        <span class="kw">WHERE</span> vet.prescription.pet_id <span class="op">=</span> vet.pet.<span class="kw">id</span></span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a>      )</span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true" tabindex="-1"></a>    )</span>
<span id="cb14-16"><a href="#cb14-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">FROM</span> vet.person_pet</span>
<span id="cb14-17"><a href="#cb14-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">LEFT</span> <span class="kw">JOIN</span> vet.pet </span>
<span id="cb14-18"><a href="#cb14-18" aria-hidden="true" tabindex="-1"></a>      <span class="kw">ON</span> vet.pet.<span class="kw">id</span> <span class="op">=</span> vet.person_pet.pet_id</span>
<span id="cb14-19"><a href="#cb14-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">WHERE</span> vet.person_pet.person_id <span class="op">=</span> vet.person.<span class="kw">id</span></span>
<span id="cb14-20"><a href="#cb14-20" aria-hidden="true" tabindex="-1"></a>  ),</span>
<span id="cb14-21"><a href="#cb14-21" aria-hidden="true" tabindex="-1"></a>  <span class="st">&#39;contact_infos&#39;</span>, <span class="dt">array</span>(</span>
<span id="cb14-22"><a href="#cb14-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">SELECT</span> jsonb_build_object(</span>
<span id="cb14-23"><a href="#cb14-23" aria-hidden="true" tabindex="-1"></a>      <span class="st">&#39;mailing_address&#39;</span>, vet.contact_info.mailing_address</span>
<span id="cb14-24"><a href="#cb14-24" aria-hidden="true" tabindex="-1"></a>    )</span>
<span id="cb14-25"><a href="#cb14-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">FROM</span> vet.contact_info</span>
<span id="cb14-26"><a href="#cb14-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">WHERE</span> vet.contact_info.person_id <span class="op">=</span> vet.person.<span class="kw">id</span></span>
<span id="cb14-27"><a href="#cb14-27" aria-hidden="true" tabindex="-1"></a>  )</span>
<span id="cb14-28"><a href="#cb14-28" aria-hidden="true" tabindex="-1"></a>) </span>
<span id="cb14-29"><a href="#cb14-29" aria-hidden="true" tabindex="-1"></a><span class="kw">FROM</span> vet.person</span>
<span id="cb14-30"><a href="#cb14-30" aria-hidden="true" tabindex="-1"></a><span class="kw">WHERE</span> <span class="kw">id</span> <span class="op">=</span> <span class="st">&#39;29168a93-cd14-478f-8c70-a2b7a782c714&#39;</span>;</span></code></pre></div>
<p>Which can net you something like the following.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;id&quot;</span><span class="fu">:</span> <span class="st">&quot;29168a93-cd14-478f-8c70-a2b7a782c714&quot;</span><span class="fu">,</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;name&quot;</span><span class="fu">:</span> <span class="st">&quot;Jeff Computers&quot;</span><span class="fu">,</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;pets&quot;</span><span class="fu">:</span> <span class="ot">[</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>    <span class="fu">{</span></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>      <span class="dt">&quot;id&quot;</span><span class="fu">:</span> <span class="st">&quot;3e5557c0-c628-44ef-b4d1-86012c5f48bf&quot;</span><span class="fu">,</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>      <span class="dt">&quot;name&quot;</span><span class="fu">:</span> <span class="st">&quot;Rhodie&quot;</span><span class="fu">,</span></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>      <span class="dt">&quot;prescriptions&quot;</span><span class="fu">:</span> <span class="ot">[</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a>        <span class="fu">{</span></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a>          <span class="dt">&quot;issued_at&quot;</span><span class="fu">:</span> <span class="st">&quot;2025-03-11T23:46:18.345146+00:00&quot;</span></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a>        <span class="fu">}</span></span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a>      <span class="ot">]</span></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a>    <span class="fu">}</span><span class="ot">,</span></span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true" tabindex="-1"></a>    <span class="fu">{</span></span>
<span id="cb15-15"><a href="#cb15-15" aria-hidden="true" tabindex="-1"></a>      <span class="dt">&quot;id&quot;</span><span class="fu">:</span> <span class="st">&quot;ed63ca7d-3368-4353-9747-6b6b2fa6657a&quot;</span><span class="fu">,</span></span>
<span id="cb15-16"><a href="#cb15-16" aria-hidden="true" tabindex="-1"></a>      <span class="dt">&quot;name&quot;</span><span class="fu">:</span> <span class="st">&quot;Jenny&quot;</span><span class="fu">,</span></span>
<span id="cb15-17"><a href="#cb15-17" aria-hidden="true" tabindex="-1"></a>      <span class="dt">&quot;prescriptions&quot;</span><span class="fu">:</span> <span class="ot">[]</span></span>
<span id="cb15-18"><a href="#cb15-18" aria-hidden="true" tabindex="-1"></a>    <span class="fu">}</span></span>
<span id="cb15-19"><a href="#cb15-19" aria-hidden="true" tabindex="-1"></a>  <span class="ot">]</span><span class="fu">,</span></span>
<span id="cb15-20"><a href="#cb15-20" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;contact_infos&quot;</span><span class="fu">:</span> <span class="ot">[</span></span>
<span id="cb15-21"><a href="#cb15-21" aria-hidden="true" tabindex="-1"></a>    <span class="fu">{</span></span>
<span id="cb15-22"><a href="#cb15-22" aria-hidden="true" tabindex="-1"></a>      <span class="dt">&quot;mailing_address&quot;</span><span class="fu">:</span> <span class="st">&quot;123 Sesame St.&quot;</span></span>
<span id="cb15-23"><a href="#cb15-23" aria-hidden="true" tabindex="-1"></a>    <span class="fu">}</span></span>
<span id="cb15-24"><a href="#cb15-24" aria-hidden="true" tabindex="-1"></a>  <span class="ot">]</span></span>
<span id="cb15-25"><a href="#cb15-25" aria-hidden="true" tabindex="-1"></a><span class="fu">}</span></span></code></pre></div>
<p>You can find all the setup you'd need to do for that query <a href="https://gist.github.com/bowbahdoe/dee0a5d534d9a36c677dbf0de977b6de">here</a>. You can try it out on <a href="https://onecompiler.com/postgresql"><a href="https://onecompiler.com/postgresql">https://onecompiler.com/postgresql</a></a> if setting up a local postgres is a bit much.</p>
<hr />
<p>If there is something I missed or got wrong, tell me very loudly in person or here on the internet.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>New build tool in Java!</title><link>https://mccue.dev/pages/3-2-25-new-build-tool-in-java</link><description></description><pubDate>Sun, 02 Mar 0025 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>New build tool in Java!</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">New build tool in Java!</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
The title is a `? -> !` of [this recent thread on Reddit](https://www.reddit.com/r/java/s/ItXOn0eBmg)
and really a continuation of this series of posts ([1](https://mccue.dev/pages/1-11-24-cli-flow), [2](https://mccue.dev/pages/5-29-24-module-compilation), [3](https://mccue.dev/pages/5-30-24-module-libs-and-tests), [4](https://mccue.dev/pages/8-26-24-java-build-scripts)).

<p>So first I am going to go over a few of the Maven/Gradle alternatives listed in that Reddit thread and explain why they don't really scratch the itch I think we need scratched, give a small status update on what I've been working on, and end with something that you the reader (yes, you!) could help me with.</p>
<p>I am also going to be terse, biased, and perhaps a bit too harsh. Otherwise, this would drag on and not be an entertaining read.</p>
<h2 id="what-do-i-want">What do I want?</h2>
<p>I want there to be a smooth on-ramp from <code>java src/Main.java</code> to running that program with dependencies, packaging it up to share with other people, and making use of the tools that come with Java (<code>jlink</code>, <code>jpackage</code>, etc.) and available in the Java ecosystem (<code>junit</code>, <code>mapstruct</code>, etc.) Ideally there should be a way to split dependencies over the <code>--class-path</code>, <code>--module-path</code>, and all the other paths as well.</p>
<p>Importantly I don't care, and I think the people who most need this on-ramp don't care, about maximal efficiency. Whoopty doo basil, you can incrementally compile a 100 million line codebase. Fart noises.</p>
<h2 id="ant">Ant</h2>
<p>Easy one out-of-the-way first, <a href="https://ant.apache.org/"><code>Ant</code></a>. Ant is a cross-platform scripting language with targets. It's <a href="https://github.com/casey/just">just</a> but you write XML.</p>
<p>By itself it doesn't handle dependencies at all and outsources that to <a href="https://ant.apache.org/ivy/">Ivy</a>. This is a second XML file and, once you've filled it out, it downloads jars to a folder.</p>
<p>Even if you are an Ant-head there is a problem in that to use Ivy you are expected to be using Ant. Ant makes sense if you start by compiling code with <code>javac</code>, but that's no longer a thing you need to do. So the path from <code>java src/Main.java</code> isn't great.</p>
<p>One thing Ant has going for it is that it is clear how to use built-in tools. It loses points in my book though because the arguments you'd give to its tasks don't match up that closely to the arguments you would pass to the command line tools. For example, compare the <a href="https://ant.apache.org/manual/Tasks/javac.html">javac task</a> to the man page for <a href="https://docs.oracle.com/en/java/javase/17/docs/specs/man/javac.html">javac itself</a>.</p>
<p>Ivy also dumps jars into a single folder. This means it isn't exactly easy to put a few dependencies on the <code>--class-path</code> and others on the <code>--module-path</code>.</p>
<h3 id="scorecard">Scorecard</h3>
<ul>
<li>🔴 Clear path from <code>java src/Main.java</code></li>
<li>🟡 Clear path to making use of other tools</li>
<li>🔴 Split dependencies across different paths</li>
</ul>
<h2 id="mill">Mill</h2>
<p><a href="https://mill-build.org/">Mill</a> is a Scala build tool. Scala is a programming language with a history of breaking changes and higher kinded types.</p>
<p>This is the example Mill program for a "<a href="https://mill-build.org/mill/javalib/intro.html">simple Java program</a>."</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode scala"><code class="sourceCode scala"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span> build</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> mill<span class="op">.</span>_<span class="op">,</span> javalib<span class="op">.</span>_</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">object</span> foo <span class="kw">extends</span> JavaModule <span class="op">{</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">def</span> ivyDeps <span class="op">=</span> <span class="fu">Agg</span><span class="op">(</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    ivy<span class="st">&quot;net.sourceforge.argparse4j:argparse4j:0.9.0&quot;</span><span class="op">,</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    ivy<span class="st">&quot;org.thymeleaf:thymeleaf:3.1.1.RELEASE&quot;</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">)</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">object</span> test <span class="kw">extends</span> JavaTests <span class="kw">with</span> TestModule<span class="op">.</span>Junit4 <span class="op">{</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">def</span> ivyDeps <span class="op">=</span> <span class="kw">super</span><span class="op">.</span><span class="fu">ivyDeps</span><span class="op">()</span> <span class="op">++</span> <span class="fu">Agg</span><span class="op">(</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>      ivy<span class="st">&quot;com.google.guava:guava:33.3.0-jre&quot;</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>So very similarly to Ant, this jumps straight into building code. To understand what is happening here you need to understand Scala - an entirely separate programming language from Java. It uses a <code>Task</code> monad, which is like a burrito, to track what tasks depend on other tasks.</p>
<p>It is also <a href="https://mill-build.org/mill/comparisons/maven.html">very fast</a>, a property I will reiterate I do not care about.</p>
<p>For built-in tools Mill bundles modules, like its <a href="https://mill-build.org/mill/javalib/publishing.html#_java_app_and_bundles_using_jlink">JlinkModule</a>, which implicitly give access to the functionality provided. This has a very similar problem to maven plugins in that the distance between "what command is actually run and when" and "what you actually specify" is relatively large.</p>
<p>Let's say you wanted to compile some <code>.xsd</code> files into Java classes with <code>xjc</code>. Perhaps a little niche nowadays, but how would you do it? Are you falling back to <code>ProcessBuilder</code>? Are you learning how the <code>Task</code> monad works?</p>
<p>As for splitting things over multiple paths, <a href="https://github.com/com-lihaoyi/mill/blob/4d9eefb4e65e9c144bc380463ff726f0e98975c1/scalalib/src/mill/scalalib/JlinkModule.scala#L56">a quick look at that <code>JlinkModule</code></a> shows that its just reusing the <code>--class-path</code> for both the <code>--class-path</code> and <code>--module-path</code>.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode scala"><code class="sourceCode scala"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">val</span> classPath <span class="op">=</span> jars<span class="op">.</span><span class="fu">map</span><span class="op">(</span>_<span class="op">.</span>toString<span class="op">).</span><span class="fu">mkString</span><span class="op">(</span>sys<span class="op">.</span><span class="fu">props</span><span class="op">(</span><span class="st">&quot;path.separator&quot;</span><span class="op">))</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">val</span> args <span class="op">=</span> <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">val</span> baseArgs <span class="op">=</span> <span class="bu">Seq</span><span class="op">(</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    Jvm<span class="op">.</span><span class="fu">jdkTool</span><span class="op">(</span><span class="st">&quot;jmod&quot;</span><span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">zincWorker</span><span class="op">().</span><span class="fu">javaHome</span><span class="op">().</span><span class="fu">map</span><span class="op">(</span>_<span class="op">.</span>path<span class="op">)),</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;create&quot;</span><span class="op">,</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;--class-path&quot;</span><span class="op">,</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    classPath<span class="op">.</span>toString<span class="op">,</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;--main-class&quot;</span><span class="op">,</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>    mainClass<span class="op">,</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;--module-path&quot;</span><span class="op">,</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>    classPath<span class="op">.</span>toString<span class="op">,</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>    outputPath<span class="op">.</span>toString</span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>  <span class="op">)</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">val</span> versionArgs <span class="op">=</span> <span class="fu">jlinkModuleVersion</span><span class="op">().</span>toSeq<span class="op">.</span>flatMap <span class="op">{</span> version <span class="op">=&gt;</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Seq</span><span class="op">(</span><span class="st">&quot;--module-version&quot;</span><span class="op">,</span> version<span class="op">)</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>  baseArgs <span class="op">++</span> versionArgs</span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="scorecard-1">Scorecard</h3>
<ul>
<li>🔴 Clear path from <code>java src/Main.java</code></li>
<li>🔴 Clear path to making use of other tools</li>
<li>🔴 Split dependencies across different paths</li>
</ul>
<h2 id="bld">bld</h2>
<p><a href="https://github.com/rife2/bld">bld</a> is the build tool from the <a href="https://rife2.com/">Rife2</a> people. I've written <a href="https://foojay.io/today/getting-started-with-bld/">promo material</a> for it before and like to think appreciate it for what it is. That being said -</p>
<p>One problem is that it copies the maven directory layout and, to an extent, conceptual model. The education path gap issues that exist with Maven mandating <code>src/Main.java</code> -&gt; <code>src/main/java/Main.java</code> are equally present. Same goes for the artifact focus, scopes, etc.</p>
<p>It very much is a build tool and, while that is in its tech-startup-de-voweled name, it's not the aspect we care about.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co">// User model is pretty similar to maven, just with Java instead of XML</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> MyAppBuild <span class="kw">extends</span> Project <span class="op">{</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">MyAppBuild</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>        pkg <span class="op">=</span> <span class="st">&quot;com.example&quot;</span><span class="op">;</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>        name <span class="op">=</span> <span class="st">&quot;my-app&quot;</span><span class="op">;</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>        mainClass <span class="op">=</span> <span class="st">&quot;com.example.MyApp&quot;</span><span class="op">;</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>        version <span class="op">=</span> <span class="fu">version</span><span class="op">(</span><span class="dv">0</span><span class="op">,</span><span class="dv">1</span><span class="op">,</span><span class="dv">0</span><span class="op">);</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>        downloadSources <span class="op">=</span> <span class="kw">true</span><span class="op">;</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>        repositories <span class="op">=</span> <span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>MAVEN_CENTRAL<span class="op">,</span> RIFE2_RELEASES<span class="op">);</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>        <span class="fu">scope</span><span class="op">(</span>test<span class="op">)</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">include</span><span class="op">(</span><span class="fu">dependency</span><span class="op">(</span><span class="st">&quot;org.junit.jupiter&quot;</span><span class="op">,</span> <span class="st">&quot;junit-jupiter&quot;</span><span class="op">,</span> <span class="fu">version</span><span class="op">(</span><span class="dv">5</span><span class="op">,</span><span class="dv">11</span><span class="op">,</span><span class="dv">4</span><span class="op">)))</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">include</span><span class="op">(</span><span class="fu">dependency</span><span class="op">(</span><span class="st">&quot;org.junit.platform&quot;</span><span class="op">,</span> <span class="st">&quot;junit-platform-console-standalone&quot;</span><span class="op">,</span> <span class="fu">version</span><span class="op">(</span><span class="dv">1</span><span class="op">,</span><span class="dv">11</span><span class="op">,</span><span class="dv">4</span><span class="op">)));</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>        <span class="kw">new</span> <span class="fu">MyAppBuild</span><span class="op">().</span><span class="fu">start</span><span class="op">(</span>args<span class="op">);</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>But unlike Mill there is no overarching Task abstraction. bld <code>Operation</code>s are almost entirely ignorable if you want to run a tool separately. I'd count that as a clear path. Sure, you're using <code>ProcessBuilder</code> or <code>AbstractProcessOperation</code>, but at least you can "just" call the <code>xjc</code>s of the world and move on with your life.</p>
<p>Like Ivy, dependencies are dumped as just jars in folders. Unlike Ivy, there is explicit support for modules. You can opt to have a dependency be put on the module path and that just gets put in a different folder.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> ProjectBuild <span class="kw">extends</span> Project <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">ProjectBuild</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>        pkg <span class="op">=</span> <span class="st">&quot;project&quot;</span><span class="op">;</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>        name <span class="op">=</span> <span class="st">&quot;project&quot;</span><span class="op">;</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>        mainClass <span class="op">=</span> <span class="st">&quot;example.Main&quot;</span><span class="op">;</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>        version <span class="op">=</span> <span class="fu">version</span><span class="op">(</span><span class="dv">0</span><span class="op">,</span><span class="dv">1</span><span class="op">,</span><span class="dv">0</span><span class="op">);</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>        downloadSources <span class="op">=</span> <span class="kw">true</span><span class="op">;</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>        repositories <span class="op">=</span> <span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>MAVEN_CENTRAL<span class="op">,</span> RIFE2_RELEASES<span class="op">);</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>        <span class="fu">scope</span><span class="op">(</span>compile<span class="op">)</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>                <span class="co">// Will be on the --class-path</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">include</span><span class="op">(</span><span class="fu">dependency</span><span class="op">(</span><span class="st">&quot;commons-io&quot;</span><span class="op">,</span> <span class="st">&quot;commons-io&quot;</span><span class="op">,</span> <span class="st">&quot;2.18.0&quot;</span><span class="op">))</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>                <span class="co">// Will be on the --module-path</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">include</span><span class="op">(</span><span class="fu">module</span><span class="op">(</span><span class="st">&quot;com.fasterxml.jackson.core&quot;</span><span class="op">,</span> <span class="st">&quot;jackson-databind&quot;</span><span class="op">,</span> <span class="st">&quot;2.18.3&quot;</span><span class="op">));</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>        <span class="co">// Takes scopes from maven too</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>        <span class="fu">scope</span><span class="op">(</span>test<span class="op">)</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">include</span><span class="op">(</span><span class="fu">dependency</span><span class="op">(</span><span class="st">&quot;org.junit.jupiter&quot;</span><span class="op">,</span> <span class="st">&quot;junit-jupiter&quot;</span><span class="op">,</span> <span class="fu">version</span><span class="op">(</span><span class="dv">5</span><span class="op">,</span><span class="dv">11</span><span class="op">,</span><span class="dv">4</span><span class="op">)))</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">include</span><span class="op">(</span><span class="fu">dependency</span><span class="op">(</span><span class="st">&quot;org.junit.platform&quot;</span><span class="op">,</span> <span class="st">&quot;junit-platform-console-standalone&quot;</span><span class="op">,</span> <span class="fu">version</span><span class="op">(</span><span class="dv">1</span><span class="op">,</span><span class="dv">11</span><span class="op">,</span><span class="dv">4</span><span class="op">)));</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true" tabindex="-1"></a>        <span class="kw">new</span> <span class="fu">ProjectBuild</span><span class="op">().</span><span class="fu">start</span><span class="op">(</span>args<span class="op">);</span></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>But just because it does better than the other entries on this list doesn't mean I'll give it full points. It still doesn't have an obvious way of filling in any of the other paths you might want when executing a tool such as <code>--processor-module-path</code>, <code>--module-path</code>, <code>-Dsystem.library.path</code>, etc. You can at least get at the command line options (and <a href="https://github.com/rife2/bld-jacoco-report/blob/master/src/main/java/rife/bld/extension/JacocoReportOperation.java">the JaCoCo extension</a> makes use of that) but it's not trivial to use fill them in via dependency resolution.</p>
<h3 id="scorecard-2">Scorecard</h3>
<ul>
<li>🔴 Clear path from <code>java src/Main.java</code></li>
<li>🟢 Clear path to making use of other tools</li>
<li>🟡 Split dependencies across different paths</li>
</ul>
<h2 id="bach">bach</h2>
<p><a href="https://github.com/sormuras/bach">Bach</a> is a build tool built entirely around the assumption that you will be using Java modules. This means the path from <code>java src/Main.java</code> has to include a pit-stop where you add a <code>module-info.java</code> and put your code in a package like <code>java src/somepackage/Main.java</code>. That's at least a path, but it's not the best one.</p>
<p>Unlike the others on the list there is a focus explicitly on the JDK tools. So running different CLI tools is pretty directly supported.</p>
<p>It more or less abdicates getting dependencies to other tools, so it sorta just doesn't solve the core problem I care about. It doesn't have a solution that gets in the way, but it doesn't have a solution at all.</p>
<p>Also bach is lucky I'm not grading on documentation because "what documentation?" It's still a WIP from the author, and it's not like I do any better, but still.</p>
<h3 id="scorecard-disqualified">Scorecard (Disqualified)</h3>
<ul>
<li>🟡 Clear path from <code>java src/Main.java</code></li>
<li>🟢 Clear path to making use of other tools</li>
<li>🔴 Split dependencies across different paths</li>
</ul>
<h2 id="pottery">pottery</h2>
<p>So <a href="https://kmruiz.github.io/pottery/">pottery</a> - it's another "maven, but." This time the "but" is that it has a set of defaults more suited to the author's preferences and it uses a yaml file for config.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode yaml"><code class="sourceCode yaml"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu">parameters</span><span class="kw">:</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">junit.version</span><span class="kw">:</span><span class="at"> </span><span class="st">&quot;5.9.1&quot;</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">snakeyaml.version</span><span class="kw">:</span><span class="at"> </span><span class="st">&quot;1.33&quot;</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">chalk.version</span><span class="kw">:</span><span class="at"> </span><span class="st">&quot;1.0.2&quot;</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">picocli.version</span><span class="kw">:</span><span class="at"> </span><span class="st">&quot;4.7.0&quot;</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">junit.platform.version</span><span class="kw">:</span><span class="at"> </span><span class="st">&quot;1.9.0&quot;</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">junit.engine.version</span><span class="kw">:</span><span class="at"> </span><span class="st">&quot;5.9.1&quot;</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a><span class="fu">artifact</span><span class="kw">:</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">group</span><span class="kw">:</span><span class="at">    </span><span class="st">&quot;cat.pottery&quot;</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">id</span><span class="kw">:</span><span class="at">       </span><span class="st">&quot;pottery&quot;</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">version</span><span class="kw">:</span><span class="at">  </span><span class="st">&quot;0.3.2&quot;</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">platform</span><span class="kw">:</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="fu">version</span><span class="kw">:</span><span class="at"> </span><span class="st">&quot;17&quot;</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="fu">produces</span><span class="kw">:</span><span class="at"> </span><span class="st">&quot;fatjar&quot;</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">manifest</span><span class="kw">:</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="fu">main-class</span><span class="kw">:</span><span class="at"> </span><span class="st">&quot;cat.pottery.ui.cli.Bootstrap&quot;</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">dependencies</span><span class="kw">:</span></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="kw">-</span><span class="at"> </span><span class="fu">production</span><span class="kw">:</span><span class="at"> </span><span class="st">&quot;org.yaml:snakeyaml:${snakeyaml.version}&quot;</span></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="kw">-</span><span class="at"> </span><span class="fu">production</span><span class="kw">:</span><span class="at"> </span><span class="st">&quot;com.github.tomas-langer:chalk:${chalk.version}&quot;</span></span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="kw">-</span><span class="at"> </span><span class="fu">production</span><span class="kw">:</span><span class="at"> </span><span class="st">&quot;info.picocli:picocli:${picocli.version}&quot;</span></span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="kw">-</span><span class="at"> </span><span class="fu">production</span><span class="kw">:</span><span class="at"> </span><span class="st">&quot;org.junit.platform:junit-platform-launcher:${junit.platform.version}&quot;</span></span>
<span id="cb5-26"><a href="#cb5-26" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="kw">-</span><span class="at"> </span><span class="fu">production</span><span class="kw">:</span><span class="at"> </span><span class="st">&quot;org.junit.jupiter:junit-jupiter-engine:${junit.engine.version}&quot;</span></span>
<span id="cb5-27"><a href="#cb5-27" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="kw">-</span><span class="at"> </span><span class="fu">test</span><span class="kw">:</span><span class="at"> </span><span class="st">&quot;org.junit.jupiter:junit-jupiter-api:${junit.version}&quot;</span></span></code></pre></div>
<p>You can make an uberjar, docker image, and native image out of the box. You can't put things on the <code>--module-path</code> though. Its also pretty tightly bundled so its unclear where you would put a hypothetical call to <code>xjc</code>. Its also taking over everything wholesale, so no easy path from <code>java src/Main.java</code></p>
<h3 id="scorecard-3">Scorecard</h3>
<ul>
<li>🔴 Clear path from <code>java src/Main.java</code></li>
<li>🔴 Clear path to making use of other tools</li>
<li>🔴 Split dependencies across different paths</li>
</ul>
<h2 id="jbang">jbang</h2>
<p><a href="https://www.jbang.dev/">jbang</a> got extremely lucky that nobody was already using the name for a porn site. That's worth celebrating.</p>
<p>The way jbang works is that you put a comment at the top of a file with the dependencies you want, then if you launch the program with <code>jbang</code> it will automatically download those dependencies and use them.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="co">///usr/bin/env jbang &quot;$0&quot; &quot;$@&quot; ; exit $?</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="co">//DEPS ch.qos.reload4j:reload4j:1.2.19</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">static</span><span class="im"> java</span><span class="op">.</span><span class="im">lang</span><span class="op">.</span><span class="im">System</span><span class="op">.</span><span class="im">out</span><span class="op">;</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">apache</span><span class="op">.</span><span class="im">log4j</span><span class="op">.</span><span class="im">Logger</span><span class="op">;</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">apache</span><span class="op">.</span><span class="im">log4j</span><span class="op">.</span><span class="im">BasicConfigurator</span><span class="op">;</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">Arrays</span><span class="op">;</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> classpath_example <span class="op">{</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">final</span> <span class="bu">Logger</span> logger <span class="op">=</span> <span class="bu">Logger</span><span class="op">.</span><span class="fu">getLogger</span><span class="op">(</span>classpath_example<span class="op">.</span><span class="fu">class</span><span class="op">);</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a>        BasicConfigurator<span class="op">.</span><span class="fu">configure</span><span class="op">();</span> </span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a>        logger<span class="op">.</span><span class="fu">info</span><span class="op">(</span><span class="st">&quot;Welcome to jbang&quot;</span><span class="op">);</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Arrays</span><span class="op">.</span><span class="fu">asList</span><span class="op">(</span>args<span class="op">).</span><span class="fu">forEach</span><span class="op">(</span>arg <span class="op">-&gt;</span> logger<span class="op">.</span><span class="fu">warn</span><span class="op">(</span><span class="st">&quot;arg: &quot;</span> <span class="op">+</span> arg<span class="op">));</span></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a>        logger<span class="op">.</span><span class="fu">info</span><span class="op">(</span><span class="st">&quot;Hello from Java!&quot;</span><span class="op">);</span></span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>So going from <code>java src/Main.java</code> to <code>jbang src/Main.java</code> is no trouble at all. Gold star.</p>
<p>Problems start when you want to put something on the <code>--module-path</code>. Unless I missed something in the documentation (which is possible) that is not possible. It has <a href="https://www.jbang.dev/documentation/guide/latest/dependencies.html#javafx">special carve-out support for JavaFX</a>, but it's not doable in general.</p>
<p>If you want to use these dependencies in other tooling, like <code>jlink</code>, you are equally out of luck.</p>
<ul>
<li>🟢 Clear path from <code>java src/Main.java</code></li>
<li>🔴 Clear path to making use of other tools</li>
<li>🔴 Split dependencies across different paths</li>
</ul>
<h2 id="java-jpm">java-jpm</h2>
<p><a href="https://github.com/codejive/java-jpm">java-jpm</a> is kinda what it says it is - it takes the same approach as <code>npm</code> and just downloads dependencies into a folder. Well it downloads dependencies then symlinks them into a folder but spiritually the same thing.</p>
<p>It just dumps into one folder, so no support for different paths. <code>java src/Main.java</code> -&gt; <code>java -cp deps/* src/Main.java</code> is pretty straight forward as well.</p>
<p>Where I have to dock it points is in the platform-specificness. <code>-cp deps/*</code> isn't something that will work consistently across bash, powershell, fish, etc. Maybe that's unfair, but it's a real problem and none of the other options have it on account of making building CLI arguments outside a specific shell.</p>
<ul>
<li>🟡 Clear path from <code>java src/Main.java</code></li>
<li>🟡 Clear path to making use of other tools</li>
<li>🔴 Split dependencies across different paths</li>
</ul>
<h2 id="what-ive-been-working-on">What I've been working on</h2>
<p>So for a while now I've had the <a href="https://github.com/bowbahdoe/jresolve-cli"><code>jresolve</code></a> tool in my back pocket. It still has much the same deficiencies it had when I first shared it, sans a few bug fixes.</p>
<p>The tl;dr is that you could run</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ex">jresolve</span> pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.18.3</span></code></pre></div>
<p>And it would print to standard output a path with all the dependencies on it, separated by the requisite platform specific path separator.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ex">/Users/emccue/.jresolve/cache/https/repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.18.3/jackson-databind-2.18.3.jar:/Users/emccue/.jresolve/cache/https/repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/2.18.3/jackson-core-2.18.3.jar:/Users/emccue/.jresolve/cache/https/repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.18.3/jackson-annotations-2.18.3.jar</span></span></code></pre></div>
<p>Nesting commands is very platform specific</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="co"># only works in bash</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="ex">java</span> <span class="at">-cp</span> <span class="va">$(</span><span class="ex">jresolve</span> pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.18.3<span class="va">)</span> src/Main.java</span></code></pre></div>
<p>So I first added the <code>--output-file</code> argument, which would let you dump the path to a file without anything overly platform specific. You could then use the "argfile" syntax - <code>@filename</code> - to use the resolved path in future commands.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ex">jresolve</span> <span class="at">--output-file</span> libs pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.18.3</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="ex">java</span> <span class="at">-cp</span> @libs src/Main.java</span></code></pre></div>
<p>But what became clear very quickly is that I had no clue how to teach an IDE how to read dependencies from a file with a path in it.</p>
<p>So that's when I added <code>--output-directory</code>. You can at least tell an IDE to use all the jars in a folder.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ex">jresolve</span> <span class="at">--output-directory</span> libs pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.18.3</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="ex">java</span> <span class="at">-cp</span> libs/<span class="pp">*</span> src/Main.java</span></code></pre></div>
<p>But, as is the issue with java-jpm, the <code>libs/*</code> syntax is platform specific. It was then I started becoming biased towards using the <code>--module-path</code>. That at least you could just point to a folder.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ex">jresolve</span> <span class="at">--output-directory</span> libs pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.18.3</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="ex">java</span> <span class="at">--module-path</span> libs <span class="at">--add-modules</span> ALL-MODULE-PATH src/Main.java</span></code></pre></div>
<p>And when the list of dependencies got too big I could put them in an argfile of their own.</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ex">jresolve</span> <span class="at">--output-directory</span> libs @libs.txt</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="ex">java</span> <span class="at">--module-path</span> libs <span class="at">--add-modules</span> ALL-MODULE-PATH src/Main.java</span></code></pre></div>
<p>And that's where <code>jresolve</code> sat for a bit over a year. I'd keep using it for one-off projects and bashing my head against the "<code>--module-path</code> or <code>--class-path</code>, pick one" problem every time I did.</p>
<p>Even in that state you can bootstrap build programs and <a href="https://mccue.dev/pages/8-26-24-java-build-scripts">I wrote libraries to support that goal</a>. With a tasteful enough use of argfiles and picocli you could get it down to</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="ex">jresolve</span> @bootstrap</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="ex">java</span> @project compile</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a><span class="ex">java</span> @project test</span></code></pre></div>
<p>And that felt <em>good</em>, but problems remain. For one, the split path issue. For two, those <code>libs.txt</code> files kinda suck. It got me thinking about how Python started with <code>requirements.txt</code> and eventually that mutated into <code>pyproject.toml</code>.</p>
<p>So that's where I went with it. In the newest version of <code>jresolve</code> if you run <code>jresolve install</code> it will look for a <code>jproject.toml</code></p>
<div class="sourceCode" id="cb15"><pre class="sourceCode toml"><code class="sourceCode toml"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">[</span><span class="dt">project</span><span class="kw">]</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="dt">defaultUsage</span><span class="op">=</span><span class="st">&quot;--class-path&quot;</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="kw">[[</span><span class="dt">project</span><span class="kw">.</span><span class="dt">dependencies</span><span class="kw">]]</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a><span class="dt">coordinate</span><span class="op">=</span><span class="st">&quot;pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.18.2&quot;</span></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a><span class="kw">[[</span><span class="dt">project</span><span class="kw">.</span><span class="dt">dependencies</span><span class="kw">]]</span></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a><span class="dt">coordinate</span><span class="op">=</span><span class="st">&quot;pkg:maven/org.junit.jupiter/junit-jupiter-api@5.11.4&quot;</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a><span class="dt">dependencySets</span><span class="op">=[</span><span class="st">&quot;test&quot;</span><span class="op">]</span></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a><span class="kw">[</span><span class="dt">project</span><span class="kw">.</span><span class="dt">dependencySets</span><span class="kw">.</span><span class="dt">test</span><span class="kw">]</span></span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a><span class="dt">extends</span><span class="op">=</span><span class="st">&quot;default&quot;</span></span></code></pre></div>
<p>And this will dump out argfiles in a predictable structure. So with the <code>jproject.toml</code> above you will end up with</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="ex">dependencySets/</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>  <span class="ex">default</span> </span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>  <span class="bu">test</span></span></code></pre></div>
<p>Where each argument file has not only the paths, but the <code>--class-path</code> preceding them. This finally gives a place to specify "this dependency goes on the <code>--module-path</code>."</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode toml"><code class="sourceCode toml"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">[</span><span class="dt">project</span><span class="kw">]</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="dt">defaultUsage</span><span class="op">=</span><span class="st">&quot;--class-path&quot;</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a><span class="kw">[[</span><span class="dt">project</span><span class="kw">.</span><span class="dt">dependencies</span><span class="kw">]]</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a><span class="dt">coordinate</span><span class="op">=</span><span class="st">&quot;pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.18.2&quot;</span></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a><span class="kw">[[</span><span class="dt">project</span><span class="kw">.</span><span class="dt">dependencies</span><span class="kw">]]</span></span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a><span class="dt">coordinate</span><span class="op">=</span><span class="st">&quot;pkg:maven/commons-io/commons-io@2.18.0&quot;</span></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a><span class="dt">usage</span><span class="op">=</span><span class="st">&quot;--module-path&quot;</span></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a><span class="kw">[[</span><span class="dt">project</span><span class="kw">.</span><span class="dt">dependencies</span><span class="kw">]]</span></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a><span class="dt">coordinate</span><span class="op">=</span><span class="st">&quot;pkg:maven/org.junit.jupiter/junit-jupiter-api@5.11.4&quot;</span></span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a><span class="dt">dependencySets</span><span class="op">=[</span><span class="st">&quot;test&quot;</span><span class="op">]</span></span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a><span class="kw">[</span><span class="dt">project</span><span class="kw">.</span><span class="dt">dependencySets</span><span class="kw">.</span><span class="dt">test</span><span class="kw">]</span></span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a><span class="dt">extends</span><span class="op">=</span><span class="st">&quot;default&quot;</span></span></code></pre></div>
<p>It would even let you do exotic things like put libraries on the <code>-Dsystem.library.path</code></p>
<div class="sourceCode" id="cb18"><pre class="sourceCode toml"><code class="sourceCode toml"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="kw">[</span><span class="dt">project</span><span class="kw">]</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="dt">defaultUsage</span><span class="op">=</span><span class="st">&quot;--class-path&quot;</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><span class="kw">[[</span><span class="dt">project</span><span class="kw">.</span><span class="dt">dependencies</span><span class="kw">]]</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a><span class="dt">coordinate</span><span class="op">=</span><span class="st">&quot;pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.18.2&quot;</span></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a><span class="kw">[[</span><span class="dt">project</span><span class="kw">.</span><span class="dt">dependencies</span><span class="kw">]]</span></span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a><span class="dt">coordinate</span><span class="op">=</span><span class="st">&quot;pkg:maven/commons-io/commons-io@2.18.0&quot;</span></span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a><span class="dt">usage</span><span class="op">=</span><span class="st">&quot;--module-path&quot;</span></span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a><span class="kw">[[</span><span class="dt">project</span><span class="kw">.</span><span class="dt">dependencies</span><span class="kw">]]</span></span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a><span class="dt">coordinate</span><span class="op">=</span><span class="st">&quot;SDL/build&quot;</span></span>
<span id="cb18-13"><a href="#cb18-13" aria-hidden="true" tabindex="-1"></a><span class="dt">usage</span><span class="op">=</span><span class="st">&quot;-Dsystem.library.path&quot;</span></span>
<span id="cb18-14"><a href="#cb18-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-15"><a href="#cb18-15" aria-hidden="true" tabindex="-1"></a><span class="kw">[[</span><span class="dt">project</span><span class="kw">.</span><span class="dt">dependencies</span><span class="kw">]]</span></span>
<span id="cb18-16"><a href="#cb18-16" aria-hidden="true" tabindex="-1"></a><span class="dt">coordinate</span><span class="op">=</span><span class="st">&quot;pkg:maven/org.junit.jupiter/junit-jupiter-api@5.11.4&quot;</span></span>
<span id="cb18-17"><a href="#cb18-17" aria-hidden="true" tabindex="-1"></a><span class="dt">dependencySets</span><span class="op">=[</span><span class="st">&quot;test&quot;</span><span class="op">]</span></span>
<span id="cb18-18"><a href="#cb18-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-19"><a href="#cb18-19" aria-hidden="true" tabindex="-1"></a><span class="kw">[</span><span class="dt">project</span><span class="kw">.</span><span class="dt">dependencySets</span><span class="kw">.</span><span class="dt">test</span><span class="kw">]</span></span>
<span id="cb18-20"><a href="#cb18-20" aria-hidden="true" tabindex="-1"></a><span class="dt">extends</span><span class="op">=</span><span class="st">&quot;default&quot;</span></span></code></pre></div>
<p>And running your program goes from <code>java src/Main.java</code> to <code>java @dependencySets/default src/Main.java</code>, perhaps with a <code>--add-modules ALL-MODULE-PATH</code>.</p>
<p>Now all I wish is that the <code>java</code> launcher itself accepted "nested" argfiles. If it did, we could put <code>@dependencySets/default src/Main.java</code> into a file named <code>run</code> and get <code>java @run</code>. Or have a dependency set for your build program and get <code>java @project build</code>. In that last situation you could slot in whatever build program you want or need. But that's where I am going to pause for the moment.</p>
<p>If you want to try any of that out you can run this command on Mac/Linux to get the tool.</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="fu">bash</span> <span class="op">&lt;</span> <span class="op">&lt;(</span><span class="ex">curl</span> <span class="at">-s</span>  https://raw.githubusercontent.com/bowbahdoe/jresolve-cli/main/install<span class="op">)</span></span></code></pre></div>
<p>If you are on Windows then you can download the jar <a href="https://github.com/bowbahdoe/jresolve-cli/releases/tag/v2025.02.15">from the latest release</a> and use <code>java -jar jresolve.jar</code>.</p>
<h2 id="what-i-need-help-with">What I need help with</h2>
<p>I still have no clue how to teach an IDE how to read dependencies from an argument file. I've had several false starts on making an IntelliJ plugin to do so. The closest I've gotten is with the Oracle extension for VSCode, but <a href="https://github.com/oracle/javavscode/issues/375">that has issues of its own</a></p>
<p>If you or someone you know has the knowledge required to pull that off please do.</p>
<p>Separately, if you can think of a convincing reason for the <code>java</code> launcher to support nested argfiles beyond it just making me happy file an issue in support of that. Also, there are tools like <code>jshell</code> which don't support argfiles for no reason in particular.</p>
<p>And one thing that seems to have happened in the Python world after the introduction of <code>pyproject.toml</code> is that a whole universe of tools started looking in that file for their own config. I don't know which is the chicken and which is the egg, but whatever goes in a <code>jproject.toml</code> it might be nice for a variety of things to use it for their config.</p>
<hr />
<p>I also wrote this in a daze on a Sunday afternoon, there's likely things I missed or described wrong. I'll try to respond to comments below or wherever it ends up being shared.</p>
<p>EDIT: I've made some edits to this since I originally shared it. The older, somewhat meaner, text is on the wayback machine.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>The Ultimate Guide to Data Structures and Algorithms (DSA)</title><link>https://mccue.dev/pages/1-22-25-the-ultimate-guide-to-data-structures-and-algorithms</link><description></description><pubDate>Wed, 22 Jan 0025 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>The Ultimate Guide to Data Structures and Algorithms (DSA)</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">The Ultimate Guide to Data Structures and Algorithms (DSA)</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
This guide has two sections, one for employers and one for prospective employees.
We'll start with employees.

<h2 id="for-employees">For Employees</h2>
<h3 id="step-1">Step 1.</h3>
<p>Obtain a copy of "Algorithm Design" by Jon Kleinberg and Éva Tardos. Any edition is fine.</p>
<h3 id="step-2">Step 2.</h3>
<p>Follow structured coursework on that book or otherwise go through it in a way that you can manage. Slowly work your way through while living your life.</p>
<p><a href="https://www.cs.princeton.edu/~wayne/kleinberg-tardos/">Here</a> are some slides and <a href="https://www.edx.org/learn/algorithms/stanford-university-algorithms-design-and-analysis-part-1">here</a> is an edX course from standford.</p>
<p>If this does not satisfy you, seek out a book of similar character.</p>
<h3 id="step-3">Step 3.</h3>
<p>Branch out. I understand why you are stressed about "Data Structures and Algorithms," but I guarantee that time spent elsewhere is going to be more valuable for you.</p>
<p>If you've done step 1 and 2 you have enough background info to begin to tackle whatever hard problems you run into in practice, focus instead on getting practical experience building things.</p>
<p>It doesn't matter if those things are trivial either: hastily writing a jank calorie tracker website or virtual shrine to Edward Cullen will provide more long term value to you than spending your evenings grinding Leetcode.</p>
<p>Only do "Competitive Programming" if it is truly an interest of yours. It's fine if it is, but you don't need to do that kind of stuff to be qualified to perform most software jobs. Even the "prestigious" ones.</p>
<h2 id="for-employers">For Employers</h2>
<h3 id="step-1-1">Step 1.</h3>
<p>Please, for the love of god, cut the shit.</p>
<p>If the position you are hiring someone for does not require implementing or understanding Gale-Shapley or reversing a linked list, do not make testing someone on that part of the interview process.</p>
<p>I do not care if you fancy yourself an "elite institution" and want to "uphold standards." It's the TSA of hiring practices. All theater, no usefulness. When people know that's what they'll be tested on they spend time practicing for the test and not their actual responsibilities. This helps no one.</p>
<h3 id="step-2-1">Step 2.</h3>
<p>Rework your hiring processes to be more holistic. This will cost time and energy, but it will cost orders of magnitude less time and energy than having employees who can balance a trie but store passwords in plaintext.</p>
<p>If you don't know where to start, give your technical interviewers this mind map and the explanation following it. <a href="/pages/1-22-25-interview-mind-map.pdf">PDF link here</a>.</p>
<img src="/pages/1-22-25-interview-mind-map.png" alt="Mind map of topics to cover in an interview" />

<blockquote>
<p>It's mostly a memory aid for making sure I cover topics in an interview but it's also an ordered guide. I start at the top right and work my way down that side. I drill into the branches if a) the candidate is enthusiastic about a topic or b) they are very reticent. Once I get down the right hand side (mostly "soft" skills stuff), I move to the top left and work my way down that side (more technical/process skills stuff). I skip any topic they've already covered. I print out a fresh map for each candidate and make brief notes around the edge of the page.</p>
<p>The "conflict resolution" branch tends to come up in the "worst project" area but it's there as a reminder to make sure it's covered if they haven't mentioned it elsewhere.</p>
<p>Overall, it was written as a general guide, not specific to any particular programming language, so you have to play it by ear somewhat if you're interviewing for a senior FP role and you're only interested in FP, for example, or if you're interviewing for, say, a scrum master, or an ops role -- anything really specialized.</p>
<p>Prior to the interview, I'll also use the map as a guide for highlighting things on their resume/CV that I want to dig into during the interview -- I may highlight parts of the resume or add "pre-notes" to their map, and use both side-by-side.</p>
<p>I try to couch all of it in "tell me about ..." open-ended questions and avoid quizzing them on specific technology as much as possible. If they don't mention some of the specific tech organically that I want to hear about, I will "guide" them back to that at appropriate points.</p>
</blockquote>
<p>The diagram and explanation comes from <a href="https://github.com/seancorfield">Sean Corfield</a>. He does not know I am writing this or quoting him.</p>
<h3 id="step-3-1">Step 3.</h3>
<p>Stop paying Leetcode and companies like them for candidates. It is in their best interests to feed slop into the slop trough. Do not gobble their slop.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How to use SDL3 from Java</title><link>https://mccue.dev/pages/12-26-24-sdl3-java</link><description></description><pubDate>Thu, 26 Dec 0024 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How to use SDL3 from Java</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How to use SDL3 from Java</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
Using native code libraries from Java is both easier than its ever been
and still a little bit frustrating.

<p>To understand that duality I wrote this pretty basic tutorial on how to use the newly-ish released <a href="https://wiki.libsdl.org/SDL3/FrontPage">SDL3</a> from Java.</p>
<p>This should be useful both for those invested in the Java ecosystem and those who have a more practical desire to use SDL3 for their own projects. While all I am going to do will be focused on Java, feel free to generalize to Clojure, Kotlin, Scala, or <a href="https://flix.dev/">flix</a><sup><a href="#1">1</a></sup>.</p>
<h2 id="prerequisites">Prerequisites</h2>
<ul>
<li>Git</li>
<li>SDKMan (<code>curl -s "https://get.sdkman.io" | bash</code>)</li>
<li>JExtract (<code>sdk install jextract</code>)</li>
<li><a href="https://adoptium.net/temurin/releases/?version=23">Java 22+</a></li>
<li>Linux-like system. (Just to make this easier for me to write and test.)</li>
<li><a href="https://github.com/casey/just">Just</a> (Or just run the commands. I like using this.)</li>
</ul>
<h2 id="tutorial">Tutorial</h2>
<h3 id="0-make-a-hello-world-project">0. Make a Hello World project</h3>
<pre><code>src/
    Main.java</code></pre>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Hello, world&quot;</span><span class="op">);</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>As part of this, make a <code>Justfile</code> with a recipe to run the project.</p>
<pre><code>help:
    just --list
    
run:
    java src/Main.java</code></pre>
<h3 id="1-clone-and-build-sdl">1. Clone and Build SDL</h3>
<p>SDL is one of those dependencies you still get from source. There are platform specific ways to get this and other native libraries, but those are all nightmares in their own right.</p>
<p>You can find the build instructions for your platform <a href="https://wiki.libsdl.org/SDL3/Installation">here</a>.</p>
<pre><code>help:
    just --list

# Clone and Build SDL    
sdl:
    rm -rf SDL
    git clone https://github.com/libsdl-org/SDL
    cd SDL &amp;&amp; mkdir build
    cd SDL/build &amp;&amp; cmake -DCMAKE_BUILD_TYPE=Release ..
    cd SDL/build &amp;&amp; cmake --build . --config Release --parallel
    cd SDL/build &amp;&amp; sudo cmake --install . --config Release
    
run:
    java src/Main.java</code></pre>
<p>Whether you want to keep SDL as a git submodule, clone it fresh every time, or something else is up to you.</p>
<p>On my machine (M1 Mac) running the build outputs some warnings which leads to a non-zero exit code. While annoying, it does manage to finish the build so whatever. So long as you don't see errors you should be fine.</p>
<h3 id="2-generate-java-bindings">2. Generate Java Bindings</h3>
<p>To do this we will use <code>jextract</code>.</p>
<pre class="shell"><code>jextract \
      --include-dir SDL/include \
      --dump-includes includes.txt \
      SDL/include/SDL3/SDL.h</code></pre>
<p>This will create a file with the command-line flags needed to include every symbol. This is useful so you can trim down the functions Java code will be generated for. Basically just go through this file and remove everything that doesn't start with <code>SDL_</code> or similar.</p>
<p>Then, using that list of symbols to include, generate Java code.</p>
<p>As part of this you should use the <code>--use-system-load-library</code> flag. This will generate the code such that it will pull <code>libsdl3</code> from the directly configurable <code>java.library.path</code>.</p>
<pre class="shell"><code>jextract \
      --include-dir SDL/include \
      --output src \
      --target-package bindings.sdl \
      --library SDL3 \
      --use-system-load-library \
      @includes.txt \
      SDL/include/SDL3/SDL.h</code></pre>
<h3 id="3-update-run-configuration">3. Update Run Configuration</h3>
<p>In order to call into native code you need to pass a flag to enable native access. This is because, in general, calling arbitrary C code can crash or otherwise bork the JVM.</p>
<p>Native access permissions are given per-module. By default (unless you make a <code>module-info.java</code>) your code will be on the unnamed module, so we will use <code>ALL-UNNAMED</code>.</p>
<pre class="shell"><code>java --enable-native-access=ALL-UNNAMED src/Main.java</code></pre>
<p>A known quirk of using a library like SDL on Mac is that you need to also pass <code>-XstartOnFirstThread</code>. On non-mac platforms I think you can leave this off.</p>
<pre class="shell"><code>java \
    -XstartOnFirstThread \
    --enable-native-access=ALL-UNNAMED \
    src/Main.java</code></pre>
<p>And then we need to pass the path of our build SDL shared library.</p>
<pre class="shell"><code>java \
    -XstartOnFirstThread \
    --enable-native-access=ALL-UNNAMED \
    -Djava.library.path=SDL/build \
    src/Main.java</code></pre>
<p>If you are unfamiliar with <code>-Djava.library.path</code> - isn't that crazy? Consequence of build tools only caring about <code>--class-path</code> I think.</p>
<h3 id="4-make-some-calls-to-sdl">4. Make some calls to SDL</h3>
<p>The following is translated from <a href="https://github.com/libsdl-org/SDL/blob/main/examples/renderer/02-primitives/primitives.c">one of the SDL examples</a>. Note that while the C example its based on has some callbacks, in Java you need to manually implement those lifecycle bits.</p>
<p>Also note the uses of <code>try/finally</code>. One big difference between C and Java is that Java has exceptions. If you want cleanup code to always run (such as <code>SDL_DestroyWindow</code>) you need to account for exceptions.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">bindings</span><span class="op">.</span><span class="im">sdl</span><span class="op">.</span><span class="im">SDL_Event</span><span class="op">;</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">bindings</span><span class="op">.</span><span class="im">sdl</span><span class="op">.</span><span class="im">SDL_FPoint</span><span class="op">;</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">bindings</span><span class="op">.</span><span class="im">sdl</span><span class="op">.</span><span class="im">SDL_FRect</span><span class="op">;</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">lang</span><span class="op">.</span><span class="im">foreign</span><span class="op">.</span><span class="im">Arena</span><span class="op">;</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">static</span><span class="im"> bindings</span><span class="op">.</span><span class="im">sdl</span><span class="op">.</span><span class="im">SDL_h</span><span class="op">.*;</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span>var arena <span class="op">=</span> Arena<span class="op">.</span><span class="fu">ofConfined</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a>            <span class="fu">SDL_SetAppMetadata</span><span class="op">(</span></span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a>                    arena<span class="op">.</span><span class="fu">allocateFrom</span><span class="op">(</span><span class="st">&quot;Example Renderer Primitives&quot;</span><span class="op">),</span></span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a>                    arena<span class="op">.</span><span class="fu">allocateFrom</span><span class="op">(</span><span class="st">&quot;1.0&quot;</span><span class="op">),</span></span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a>                    arena<span class="op">.</span><span class="fu">allocateFrom</span><span class="op">(</span><span class="st">&quot;com.example.renderer-primitives&quot;</span><span class="op">)</span></span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(!</span><span class="fu">SDL_Init</span><span class="op">(</span><span class="fu">SDL_INIT_VIDEO</span><span class="op">()))</span> <span class="op">{</span></span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true" tabindex="-1"></a>                <span class="bu">System</span><span class="op">.</span><span class="fu">err</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span></span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true" tabindex="-1"></a>                        <span class="st">&quot;Couldn&#39;t initialize SDL: &quot;</span></span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true" tabindex="-1"></a>                                <span class="op">+</span> <span class="fu">SDL_GetError</span><span class="op">().</span><span class="fu">getString</span><span class="op">(</span><span class="dv">0</span><span class="op">));</span></span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span><span class="op">;</span></span>
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb10-24"><a href="#cb10-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-25"><a href="#cb10-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-26"><a href="#cb10-26" aria-hidden="true" tabindex="-1"></a>            var windowPtr <span class="op">=</span> arena<span class="op">.</span><span class="fu">allocate</span><span class="op">(</span>C_POINTER<span class="op">);</span></span>
<span id="cb10-27"><a href="#cb10-27" aria-hidden="true" tabindex="-1"></a>            var rendererPtr <span class="op">=</span> arena<span class="op">.</span><span class="fu">allocate</span><span class="op">(</span>C_POINTER<span class="op">);</span></span>
<span id="cb10-28"><a href="#cb10-28" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(!</span><span class="fu">SDL_CreateWindowAndRenderer</span><span class="op">(</span></span>
<span id="cb10-29"><a href="#cb10-29" aria-hidden="true" tabindex="-1"></a>                    arena<span class="op">.</span><span class="fu">allocateFrom</span><span class="op">(</span><span class="st">&quot;examples/renderer/clear&quot;</span><span class="op">),</span></span>
<span id="cb10-30"><a href="#cb10-30" aria-hidden="true" tabindex="-1"></a>                    <span class="dv">640</span><span class="op">,</span></span>
<span id="cb10-31"><a href="#cb10-31" aria-hidden="true" tabindex="-1"></a>                    <span class="dv">480</span><span class="op">,</span></span>
<span id="cb10-32"><a href="#cb10-32" aria-hidden="true" tabindex="-1"></a>                    <span class="dv">0</span><span class="op">,</span></span>
<span id="cb10-33"><a href="#cb10-33" aria-hidden="true" tabindex="-1"></a>                    windowPtr<span class="op">,</span></span>
<span id="cb10-34"><a href="#cb10-34" aria-hidden="true" tabindex="-1"></a>                    rendererPtr</span>
<span id="cb10-35"><a href="#cb10-35" aria-hidden="true" tabindex="-1"></a>            <span class="op">))</span> <span class="op">{</span></span>
<span id="cb10-36"><a href="#cb10-36" aria-hidden="true" tabindex="-1"></a>                <span class="bu">System</span><span class="op">.</span><span class="fu">err</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span></span>
<span id="cb10-37"><a href="#cb10-37" aria-hidden="true" tabindex="-1"></a>                        <span class="st">&quot;Couldn&#39;t create window/renderer: &quot;</span></span>
<span id="cb10-38"><a href="#cb10-38" aria-hidden="true" tabindex="-1"></a>                                <span class="op">+</span> <span class="fu">SDL_GetError</span><span class="op">().</span><span class="fu">getString</span><span class="op">(</span><span class="dv">0</span><span class="op">));</span></span>
<span id="cb10-39"><a href="#cb10-39" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span><span class="op">;</span></span>
<span id="cb10-40"><a href="#cb10-40" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb10-41"><a href="#cb10-41" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-42"><a href="#cb10-42" aria-hidden="true" tabindex="-1"></a>            var window <span class="op">=</span> windowPtr<span class="op">.</span><span class="fu">get</span><span class="op">(</span>C_POINTER<span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb10-43"><a href="#cb10-43" aria-hidden="true" tabindex="-1"></a>            var renderer <span class="op">=</span> rendererPtr<span class="op">.</span><span class="fu">get</span><span class="op">(</span>C_POINTER<span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb10-44"><a href="#cb10-44" aria-hidden="true" tabindex="-1"></a>            <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb10-45"><a href="#cb10-45" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-46"><a href="#cb10-46" aria-hidden="true" tabindex="-1"></a>                <span class="dt">int</span> numberOfPoints <span class="op">=</span> <span class="dv">500</span><span class="op">;</span></span>
<span id="cb10-47"><a href="#cb10-47" aria-hidden="true" tabindex="-1"></a>                var points <span class="op">=</span> SDL_FPoint<span class="op">.</span><span class="fu">allocateArray</span><span class="op">(</span>numberOfPoints<span class="op">,</span> arena<span class="op">);</span></span>
<span id="cb10-48"><a href="#cb10-48" aria-hidden="true" tabindex="-1"></a>                <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> numberOfPoints<span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb10-49"><a href="#cb10-49" aria-hidden="true" tabindex="-1"></a>                    var point <span class="op">=</span> SDL_FPoint<span class="op">.</span><span class="fu">asSlice</span><span class="op">(</span>points<span class="op">,</span> i<span class="op">);</span></span>
<span id="cb10-50"><a href="#cb10-50" aria-hidden="true" tabindex="-1"></a>                    SDL_FPoint<span class="op">.</span><span class="fu">x</span><span class="op">(</span></span>
<span id="cb10-51"><a href="#cb10-51" aria-hidden="true" tabindex="-1"></a>                            point<span class="op">,</span></span>
<span id="cb10-52"><a href="#cb10-52" aria-hidden="true" tabindex="-1"></a>                            <span class="op">(</span><span class="fu">SDL_randf</span><span class="op">()</span> <span class="op">*</span> <span class="fl">440.0f</span><span class="op">)</span> <span class="op">+</span> <span class="fl">100.0f</span></span>
<span id="cb10-53"><a href="#cb10-53" aria-hidden="true" tabindex="-1"></a>                    <span class="op">);</span></span>
<span id="cb10-54"><a href="#cb10-54" aria-hidden="true" tabindex="-1"></a>                    SDL_FPoint<span class="op">.</span><span class="fu">y</span><span class="op">(</span></span>
<span id="cb10-55"><a href="#cb10-55" aria-hidden="true" tabindex="-1"></a>                            point<span class="op">,</span></span>
<span id="cb10-56"><a href="#cb10-56" aria-hidden="true" tabindex="-1"></a>                            <span class="op">(</span><span class="fu">SDL_randf</span><span class="op">()</span> <span class="op">*</span> <span class="fl">280.0f</span><span class="op">)</span> <span class="op">+</span> <span class="fl">100.0f</span></span>
<span id="cb10-57"><a href="#cb10-57" aria-hidden="true" tabindex="-1"></a>                    <span class="op">);</span></span>
<span id="cb10-58"><a href="#cb10-58" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb10-59"><a href="#cb10-59" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-60"><a href="#cb10-60" aria-hidden="true" tabindex="-1"></a>                var event <span class="op">=</span> SDL_Event<span class="op">.</span><span class="fu">allocate</span><span class="op">(</span>arena<span class="op">);</span></span>
<span id="cb10-61"><a href="#cb10-61" aria-hidden="true" tabindex="-1"></a>                var rect <span class="op">=</span> SDL_FRect<span class="op">.</span><span class="fu">allocate</span><span class="op">(</span>arena<span class="op">);</span></span>
<span id="cb10-62"><a href="#cb10-62" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-63"><a href="#cb10-63" aria-hidden="true" tabindex="-1"></a>                program<span class="op">:</span></span>
<span id="cb10-64"><a href="#cb10-64" aria-hidden="true" tabindex="-1"></a>                <span class="cf">while</span> <span class="op">(</span><span class="kw">true</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-65"><a href="#cb10-65" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">while</span> <span class="op">(</span><span class="fu">SDL_PollEvent</span><span class="op">(</span>event<span class="op">))</span> <span class="op">{</span></span>
<span id="cb10-66"><a href="#cb10-66" aria-hidden="true" tabindex="-1"></a>                        var type <span class="op">=</span> SDL_Event<span class="op">.</span><span class="fu">type</span><span class="op">(</span>event<span class="op">);</span></span>
<span id="cb10-67"><a href="#cb10-67" aria-hidden="true" tabindex="-1"></a>                        <span class="cf">if</span> <span class="op">(</span>type <span class="op">==</span> <span class="fu">SDL_EVENT_QUIT</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb10-68"><a href="#cb10-68" aria-hidden="true" tabindex="-1"></a>                            <span class="bu">System</span><span class="op">.</span><span class="fu">err</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Quitting&quot;</span><span class="op">);</span></span>
<span id="cb10-69"><a href="#cb10-69" aria-hidden="true" tabindex="-1"></a>                            <span class="cf">break</span> program<span class="op">;</span></span>
<span id="cb10-70"><a href="#cb10-70" aria-hidden="true" tabindex="-1"></a>                        <span class="op">}</span></span>
<span id="cb10-71"><a href="#cb10-71" aria-hidden="true" tabindex="-1"></a>                    <span class="op">}</span></span>
<span id="cb10-72"><a href="#cb10-72" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-73"><a href="#cb10-73" aria-hidden="true" tabindex="-1"></a>                    <span class="co">/* as you can see from this, rendering draws over whatever was drawn before it. */</span></span>
<span id="cb10-74"><a href="#cb10-74" aria-hidden="true" tabindex="-1"></a>                    <span class="fu">SDL_SetRenderDrawColor</span><span class="op">(</span></span>
<span id="cb10-75"><a href="#cb10-75" aria-hidden="true" tabindex="-1"></a>                            renderer<span class="op">,</span></span>
<span id="cb10-76"><a href="#cb10-76" aria-hidden="true" tabindex="-1"></a>                            <span class="op">(</span><span class="dt">byte</span><span class="op">)</span> <span class="dv">33</span><span class="op">,</span> <span class="op">(</span><span class="dt">byte</span><span class="op">)</span> <span class="dv">33</span><span class="op">,</span> <span class="op">(</span><span class="dt">byte</span><span class="op">)</span> <span class="dv">33</span><span class="op">,</span> <span class="op">(</span><span class="dt">byte</span><span class="op">)</span> <span class="fu">SDL_ALPHA_OPAQUE</span><span class="op">()</span></span>
<span id="cb10-77"><a href="#cb10-77" aria-hidden="true" tabindex="-1"></a>                    <span class="op">);</span>  <span class="co">/* dark gray, full alpha */</span></span>
<span id="cb10-78"><a href="#cb10-78" aria-hidden="true" tabindex="-1"></a>                    <span class="fu">SDL_RenderClear</span><span class="op">(</span>renderer<span class="op">);</span>  <span class="co">/* start with a blank canvas. */</span></span>
<span id="cb10-79"><a href="#cb10-79" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-80"><a href="#cb10-80" aria-hidden="true" tabindex="-1"></a>                    <span class="co">/* draw a filled rectangle in the middle of the canvas. */</span></span>
<span id="cb10-81"><a href="#cb10-81" aria-hidden="true" tabindex="-1"></a>                    <span class="fu">SDL_SetRenderDrawColor</span><span class="op">(</span></span>
<span id="cb10-82"><a href="#cb10-82" aria-hidden="true" tabindex="-1"></a>                            renderer<span class="op">,</span></span>
<span id="cb10-83"><a href="#cb10-83" aria-hidden="true" tabindex="-1"></a>                            <span class="op">(</span><span class="dt">byte</span><span class="op">)</span> <span class="dv">0</span><span class="op">,</span> <span class="op">(</span><span class="dt">byte</span><span class="op">)</span> <span class="dv">0</span><span class="op">,</span> <span class="op">(</span><span class="dt">byte</span><span class="op">)</span> <span class="dv">255</span><span class="op">,</span> <span class="op">(</span><span class="dt">byte</span><span class="op">)</span> <span class="fu">SDL_ALPHA_OPAQUE</span><span class="op">()</span></span>
<span id="cb10-84"><a href="#cb10-84" aria-hidden="true" tabindex="-1"></a>                    <span class="op">);</span>  <span class="co">/* blue, full alpha */</span></span>
<span id="cb10-85"><a href="#cb10-85" aria-hidden="true" tabindex="-1"></a>                    SDL_FRect<span class="op">.</span><span class="fu">x</span><span class="op">(</span>rect<span class="op">,</span> <span class="dv">100</span><span class="op">);</span></span>
<span id="cb10-86"><a href="#cb10-86" aria-hidden="true" tabindex="-1"></a>                    SDL_FRect<span class="op">.</span><span class="fu">y</span><span class="op">(</span>rect<span class="op">,</span> <span class="dv">100</span><span class="op">);</span></span>
<span id="cb10-87"><a href="#cb10-87" aria-hidden="true" tabindex="-1"></a>                    SDL_FRect<span class="op">.</span><span class="fu">w</span><span class="op">(</span>rect<span class="op">,</span> <span class="dv">440</span><span class="op">);</span></span>
<span id="cb10-88"><a href="#cb10-88" aria-hidden="true" tabindex="-1"></a>                    SDL_FRect<span class="op">.</span><span class="fu">h</span><span class="op">(</span>rect<span class="op">,</span> <span class="dv">280</span><span class="op">);</span></span>
<span id="cb10-89"><a href="#cb10-89" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-90"><a href="#cb10-90" aria-hidden="true" tabindex="-1"></a>                    <span class="fu">SDL_RenderFillRect</span><span class="op">(</span>renderer<span class="op">,</span> rect<span class="op">);</span></span>
<span id="cb10-91"><a href="#cb10-91" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-92"><a href="#cb10-92" aria-hidden="true" tabindex="-1"></a>                    <span class="co">/* draw some points across the canvas. */</span></span>
<span id="cb10-93"><a href="#cb10-93" aria-hidden="true" tabindex="-1"></a>                    <span class="fu">SDL_SetRenderDrawColor</span><span class="op">(</span></span>
<span id="cb10-94"><a href="#cb10-94" aria-hidden="true" tabindex="-1"></a>                            renderer<span class="op">,</span></span>
<span id="cb10-95"><a href="#cb10-95" aria-hidden="true" tabindex="-1"></a>                            <span class="op">(</span><span class="dt">byte</span><span class="op">)</span> <span class="dv">255</span><span class="op">,</span> <span class="op">(</span><span class="dt">byte</span><span class="op">)</span> <span class="dv">0</span><span class="op">,</span> <span class="op">(</span><span class="dt">byte</span><span class="op">)</span> <span class="dv">0</span><span class="op">,</span> <span class="op">(</span><span class="dt">byte</span><span class="op">)</span> <span class="fu">SDL_ALPHA_OPAQUE</span><span class="op">()</span></span>
<span id="cb10-96"><a href="#cb10-96" aria-hidden="true" tabindex="-1"></a>                    <span class="op">);</span>  <span class="co">/* red, full alpha */</span></span>
<span id="cb10-97"><a href="#cb10-97" aria-hidden="true" tabindex="-1"></a>                    <span class="fu">SDL_RenderPoints</span><span class="op">(</span>renderer<span class="op">,</span> points<span class="op">,</span> numberOfPoints<span class="op">);</span></span>
<span id="cb10-98"><a href="#cb10-98" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-99"><a href="#cb10-99" aria-hidden="true" tabindex="-1"></a>                    <span class="co">/* draw a unfilled rectangle in-set a little bit. */</span></span>
<span id="cb10-100"><a href="#cb10-100" aria-hidden="true" tabindex="-1"></a>                    <span class="fu">SDL_SetRenderDrawColor</span><span class="op">(</span></span>
<span id="cb10-101"><a href="#cb10-101" aria-hidden="true" tabindex="-1"></a>                            renderer<span class="op">,</span></span>
<span id="cb10-102"><a href="#cb10-102" aria-hidden="true" tabindex="-1"></a>                            <span class="op">(</span><span class="dt">byte</span><span class="op">)</span> <span class="dv">0</span><span class="op">,</span> <span class="op">(</span><span class="dt">byte</span><span class="op">)</span> <span class="dv">255</span><span class="op">,</span> <span class="op">(</span><span class="dt">byte</span><span class="op">)</span> <span class="dv">0</span><span class="op">,</span> <span class="op">(</span><span class="dt">byte</span><span class="op">)</span> <span class="fu">SDL_ALPHA_OPAQUE</span><span class="op">()</span></span>
<span id="cb10-103"><a href="#cb10-103" aria-hidden="true" tabindex="-1"></a>                    <span class="op">);</span>  <span class="co">/* green, full alpha */</span></span>
<span id="cb10-104"><a href="#cb10-104" aria-hidden="true" tabindex="-1"></a>                    SDL_FRect<span class="op">.</span><span class="fu">x</span><span class="op">(</span></span>
<span id="cb10-105"><a href="#cb10-105" aria-hidden="true" tabindex="-1"></a>                            rect<span class="op">,</span></span>
<span id="cb10-106"><a href="#cb10-106" aria-hidden="true" tabindex="-1"></a>                            SDL_FRect<span class="op">.</span><span class="fu">x</span><span class="op">(</span>rect<span class="op">)</span> <span class="op">+</span> <span class="dv">30</span></span>
<span id="cb10-107"><a href="#cb10-107" aria-hidden="true" tabindex="-1"></a>                    <span class="op">);</span></span>
<span id="cb10-108"><a href="#cb10-108" aria-hidden="true" tabindex="-1"></a>                    SDL_FRect<span class="op">.</span><span class="fu">y</span><span class="op">(</span></span>
<span id="cb10-109"><a href="#cb10-109" aria-hidden="true" tabindex="-1"></a>                            rect<span class="op">,</span></span>
<span id="cb10-110"><a href="#cb10-110" aria-hidden="true" tabindex="-1"></a>                            SDL_FRect<span class="op">.</span><span class="fu">y</span><span class="op">(</span>rect<span class="op">)</span> <span class="op">+</span> <span class="dv">30</span></span>
<span id="cb10-111"><a href="#cb10-111" aria-hidden="true" tabindex="-1"></a>                    <span class="op">);</span></span>
<span id="cb10-112"><a href="#cb10-112" aria-hidden="true" tabindex="-1"></a>                    SDL_FRect<span class="op">.</span><span class="fu">w</span><span class="op">(</span></span>
<span id="cb10-113"><a href="#cb10-113" aria-hidden="true" tabindex="-1"></a>                            rect<span class="op">,</span></span>
<span id="cb10-114"><a href="#cb10-114" aria-hidden="true" tabindex="-1"></a>                            SDL_FRect<span class="op">.</span><span class="fu">w</span><span class="op">(</span>rect<span class="op">)</span> <span class="op">-</span> <span class="dv">60</span></span>
<span id="cb10-115"><a href="#cb10-115" aria-hidden="true" tabindex="-1"></a>                    <span class="op">);</span></span>
<span id="cb10-116"><a href="#cb10-116" aria-hidden="true" tabindex="-1"></a>                    SDL_FRect<span class="op">.</span><span class="fu">h</span><span class="op">(</span></span>
<span id="cb10-117"><a href="#cb10-117" aria-hidden="true" tabindex="-1"></a>                            rect<span class="op">,</span></span>
<span id="cb10-118"><a href="#cb10-118" aria-hidden="true" tabindex="-1"></a>                            SDL_FRect<span class="op">.</span><span class="fu">h</span><span class="op">(</span>rect<span class="op">)</span> <span class="op">-</span> <span class="dv">60</span></span>
<span id="cb10-119"><a href="#cb10-119" aria-hidden="true" tabindex="-1"></a>                    <span class="op">);</span></span>
<span id="cb10-120"><a href="#cb10-120" aria-hidden="true" tabindex="-1"></a>                    <span class="fu">SDL_RenderRect</span><span class="op">(</span>renderer<span class="op">,</span> rect<span class="op">);</span></span>
<span id="cb10-121"><a href="#cb10-121" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-122"><a href="#cb10-122" aria-hidden="true" tabindex="-1"></a>                    <span class="co">/* draw two lines in an X across the whole canvas. */</span></span>
<span id="cb10-123"><a href="#cb10-123" aria-hidden="true" tabindex="-1"></a>                    <span class="fu">SDL_SetRenderDrawColor</span><span class="op">(</span></span>
<span id="cb10-124"><a href="#cb10-124" aria-hidden="true" tabindex="-1"></a>                            renderer<span class="op">,</span></span>
<span id="cb10-125"><a href="#cb10-125" aria-hidden="true" tabindex="-1"></a>                            <span class="op">(</span><span class="dt">byte</span><span class="op">)</span> <span class="dv">255</span><span class="op">,</span> <span class="op">(</span><span class="dt">byte</span><span class="op">)</span> <span class="dv">255</span><span class="op">,</span> <span class="op">(</span><span class="dt">byte</span><span class="op">)</span> <span class="dv">0</span><span class="op">,</span> <span class="op">(</span><span class="dt">byte</span><span class="op">)</span> <span class="fu">SDL_ALPHA_OPAQUE</span><span class="op">()</span></span>
<span id="cb10-126"><a href="#cb10-126" aria-hidden="true" tabindex="-1"></a>                    <span class="op">);</span>  <span class="co">/* yellow, full alpha */</span></span>
<span id="cb10-127"><a href="#cb10-127" aria-hidden="true" tabindex="-1"></a>                    <span class="fu">SDL_RenderLine</span><span class="op">(</span>renderer<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">640</span><span class="op">,</span> <span class="dv">480</span><span class="op">);</span></span>
<span id="cb10-128"><a href="#cb10-128" aria-hidden="true" tabindex="-1"></a>                    <span class="fu">SDL_RenderLine</span><span class="op">(</span>renderer<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">480</span><span class="op">,</span> <span class="dv">640</span><span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb10-129"><a href="#cb10-129" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-130"><a href="#cb10-130" aria-hidden="true" tabindex="-1"></a>                    <span class="fu">SDL_RenderPresent</span><span class="op">(</span>renderer<span class="op">);</span>  <span class="co">/* put it all on the screen! */</span></span>
<span id="cb10-131"><a href="#cb10-131" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb10-132"><a href="#cb10-132" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-133"><a href="#cb10-133" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> <span class="cf">finally</span> <span class="op">{</span></span>
<span id="cb10-134"><a href="#cb10-134" aria-hidden="true" tabindex="-1"></a>                <span class="fu">SDL_DestroyRenderer</span><span class="op">(</span>renderer<span class="op">);</span></span>
<span id="cb10-135"><a href="#cb10-135" aria-hidden="true" tabindex="-1"></a>                <span class="fu">SDL_DestroyWindow</span><span class="op">(</span>window<span class="op">);</span></span>
<span id="cb10-136"><a href="#cb10-136" aria-hidden="true" tabindex="-1"></a>                <span class="fu">SDL_Quit</span><span class="op">();</span></span>
<span id="cb10-137"><a href="#cb10-137" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb10-138"><a href="#cb10-138" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb10-139"><a href="#cb10-139" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-140"><a href="#cb10-140" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Run the code with the flags discussed above. You should see a window pop up with a rectangle and some dots.</p>
<p><img src="./12-26-24-sdl-window.png"></img></p>
<h2 id="annoyances">Annoyances</h2>
<p>So while this is easy from top to bottom, there are some interesting properties you should be aware of.</p>
<h3 id="1-sdl_h-doesnt-actually-have-all-the-functions">1. <code>SDL_h</code> doesn't actually have all the functions.</h3>
<p>I assume because of limits on class size, with a library the size of SDL the <code>jextract</code>-generated binding code is split over multiple files. <code>SDL_h</code>, <code>SDL_h_1</code>, <code>SDL_h_2</code>, etc. This isn't an issue normally since you can just add more static imports, but it can be an issue for binary compatibility. If you end up directly accessing the static properties of <code>SDL_h_2</code> you might be in for a bad surprise if those symbols end up in a different class file when you next update.</p>
<p>It's not a problem when the generated binding code is just part of your build, but it is an issue if you wanted to make a stable <code>sdl</code> artifact to share with other people.</p>
<h3 id="2-the-generated-java-code-is-per-platform">2. The generated Java code is per-platform.</h3>
<p>Java doesn't actually have a C api - it has a "foreign function and memory" api. This means that the descriptions of native memory layouts include platform specific padding. <code>jextract</code> uses <code>clang</code> to figure out what the memory layouts for structs are and dumps those as part of its generated code.</p>
<p>This means that if you want to use <code>jextract</code> generated code across different platforms you need to either make distinct artifacts per-platform or handle things dynamically at runtime.</p>
<p>An easy way to get access to different platforms (which you should think of as target triples - <code>(operating system, architecture, libc)</code>) is via GitHub actions. Exercise for the reader on how to integrate that, <a href="https://github.com/bowbahdoe/tui/blob/main/.github/workflows/mac_aarch64.yaml">though I have one example</a>.</p>
<h3 id="3-it-would-be-work-to-share-this">3. It would be work to share this</h3>
<p>Distributing a library which uses C code over the usual Java library channels like Maven Central can be annoying. The standard build tools (maven, gradle, etc.) do not provide an easy way to set <code>java.library.path</code> or get dependencies that should go there. What most people have historically done is to embed one or multiple shared libraries in a jar and extract them at runtime.<sup><a href="#2">2</a></sup></p>
<p>This is some bunk, but kinda the lowest common denominator approach. You can read <a href="https://github.com/fusesource/jansi/blob/master/src/main/java/org/fusesource/jansi/internal/JansiLoader.java">some of that nonsense here</a>.</p>
<p>The binary compatibility issues alluded to above would also be something to consider.</p>
<p>All that is to say - don't go just publishing libraries for every C library you want bindings for. At least at the moment there are some caveats and the ecosystem isn't super ready for it. If you are going to do that, provide a layer on top of the auto-generated <code>jextract</code> code. Have some value that is worth the time investment.</p>
<h3 id="4-you-need-to-care-about-memory-lifetimes">4. You need to care about memory lifetimes</h3>
<p>In the example code there is only one <code>Arena</code> and it lives for the entire program. If you have a need to allocate memory for a shorter timespan you'll need to make at least one allocator. While this is better than directly dealing with <code>malloc</code>/<code>free</code> it is still more responsibility than you usually have in Java code.</p>
<p>It can be tempting to build APIs that use foreign memory the same as if they did not, but unless you have a really clear seam behind which to hide the memory shenanigans it is probably going to backfire.</p>
<h2 id="conclusion">Conclusion</h2>
<p>If you want to make a game or game engine, this should be a good start. You can pivot to more C oriented SDL tutorials and translate the calls needed to open windows, render graphics, etc.</p>
<p>If you want to do something similar for another native library, this should serve as a decent starting point.</p>
<p>You can find the code for this demo <a href="https://github.com/bowbahdoe/sdl-java-tutorial">here</a>.</p>
<p id="1" style="font-size: 14px">1: Sidenote, but I think flix could kill Scala as the JVM language for Haskell-likin-types. 
Other than implicits + some basic type level stuff: Java has already taken or will take most of what made Scala interesting.
"Stratified Negation," "Lattice Semantics," and "Associated Effects" intimidate me in a way I haven't felt in a while.</p>
<p id="2" style="font-size: 14px">2: There is one method of distribution that doesn't have these problems: <i>.jmod</i>. JMods have
a special place for shared libraries and will merge them in to a JDK it's linked with. I'm investigating the possibilities of 
that on the side.</p>

<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Java Build Scripts</title><link>https://mccue.dev/pages/8-26-24-java-build-scripts</link><description></description><pubDate>Mon, 26 Aug 0024 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Java Build Scripts</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Java Build Scripts</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 

<p>I've written before about how I think that while they need some bolstering (<a href="https://mccue.dev/pages/1-11-24-cli-flow">here</a>) using the CLI tools to build Java code is more practical than you might think (<a href="https://mccue.dev/pages/5-29-24-module-compilation">here</a> and <a href="https://mccue.dev/pages/5-30-24-module-libs-and-tests">here</a>).</p>
<p>What I didn't talk about, or tip-toed around, is that writing build scripts in <code>bash</code>, <code>PowerShell</code>, <code>cmd.exe</code>, etc. is not very cross-platform.</p>
<p>You can install <code>bash</code> on Windows and run in <a href="https://learn.microsoft.com/en-us/windows/wsl/install">WSL</a>, but that feels unideal. An extra setup step is one thing, but needing to ask students who just learned that the command line exists to also make sure they aren't accidentally running in <code>PowerShell</code> is painful.</p>
<p>You could also just ignore the problem. "Real" developers use Mac or Linux, right? Well those same developers sometimes pick an extra special shell for themselves like <code>zsh</code>, <code>nushell</code>, or <code>fish</code>. You have a similar, if less serious, problem.</p>
<p>Using any of those shells for experimenting or testing out commands is fine. Until you write <code>$()</code> or a file path they are all more or less the same. What we really need is some way of writing out commands that will work on Windows, Mac, and Linux and regardless of if someone is using <code>bash</code>, <code>Powershell</code>, <code>cmd.exe</code>, <code>zsh</code>, <code>nushell</code>, or <code>fish</code>.</p>
<p>If only we had a language that could be written once and then ran anywhere.</p>
<h2 id="just">just</h2>
<p>Since Java 22 we've been able to write <code>java Main.java</code> and execute a potentially multi-file program. Before that there was a significant bootstrap problem. If you write Java code to compile Java code, who compiles that Java code?</p>
<p>Now that that's there, we can start to consider what it would look like to run a CLI tool from Java code and compare that to the alternatives.</p>
<p>The alternative I've been using is <a href="https://github.com/casey/just"><code>just</code></a>. <code>just</code> is a command runner similar to <code>make</code> but without any of the caching <code>make</code> does or the wild syntax and history <code>make</code> is burdened with.</p>
<p>You write the name of a "recipe", a <code>:</code> then an indented list of commands to run.</p>
<pre class="just"><code>demo:
    javac --version
    jlink --version</code></pre>
<p>For this, if you run <code>just demo</code> and then it will run each command in sequence.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> just demo</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="ex">javac</span> <span class="at">--version</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="ex">javac</span> 22.0.1</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="ex">jlink</span> <span class="at">--version</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="ex">22.0.1</span></span></code></pre></div>
<p>If any command gives you a non-zero exit code it fails immediately.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">javac</span> <span class="at">--v</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="ex">error:</span> invalid flag: <span class="at">--v</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="ex">Usage:</span> javac <span class="op">&lt;</span>options<span class="op">&gt;</span> <span class="op">&lt;</span>source files<span class="op">&gt;</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="ex">use</span> <span class="at">--help</span> for a list of possible options</span></code></pre></div>
<p>And, by default, it will echo the command its about to run before it runs it.</p>
<p>All of these properties are useful for different reasons.</p>
<ul>
<li>Printing the command before its run is useful when something fails. You can usually just copy-paste the command and tweak it until it works. Then you can just copy-paste the working command back in place.</li>
<li>Failing immediately on a non-zero exit code is a good default for what I feel are obvious reasons.</li>
<li>Being able to refer to a command or group of commands by an alias is almost required to do anything interesting. <code>just compile</code> is much more ergonomic to use than <code>javac -d build --module-source-path "./*/src --module example</code>.</li>
</ul>
<p>Also, and it feels small but isn't, you can get a list of all the commands + a comment on how to use them with <code>just --list</code>.</p>
<pre><code>$ just --list
Available recipes:
    demo</code></pre>
<h2 id="run-commands-in-java">Run commands in Java</h2>
<p>I want all of these properties so let's see how we can get them in <code>Java</code>.</p>
<p>To run a command we can use the <code>ProcessBuilder</code>.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">List</span><span class="op">;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Project <span class="op">{</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>        var cmd <span class="op">=</span> <span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;javac&quot;</span><span class="op">,</span> <span class="st">&quot;--version&quot;</span><span class="op">);</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>        var pb <span class="op">=</span> <span class="kw">new</span> <span class="bu">ProcessBuilder</span><span class="op">(</span>cmd<span class="op">);</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Then all we need to do is start the command, wait for it to finish, and record the exit status. If its non-zero throw.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Project <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>        var cmd <span class="op">=</span> <span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;javac&quot;</span><span class="op">,</span> <span class="st">&quot;--version&quot;</span><span class="op">);</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>        var pb <span class="op">=</span> <span class="kw">new</span> <span class="bu">ProcessBuilder</span><span class="op">(</span>cmd<span class="op">);</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>            <span class="dt">int</span> exitStatus <span class="op">=</span> pb<span class="op">.</span><span class="fu">inheritIO</span><span class="op">().</span><span class="fu">start</span><span class="op">().</span><span class="fu">waitFor</span><span class="op">();</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>exitStatus <span class="op">!=</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>                <span class="cf">throw</span> <span class="kw">new</span> <span class="bu">RuntimeException</span><span class="op">(</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>                        <span class="st">&quot;Non-zero exit status: &quot;</span> <span class="op">+</span> exitStatus</span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>                <span class="op">);</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span><span class="bu">InterruptedException</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a>            <span class="cf">throw</span> <span class="kw">new</span> <span class="bu">RuntimeException</span><span class="op">(</span>e<span class="op">);</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span><span class="bu">IOException</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a>            <span class="cf">throw</span> <span class="kw">new</span> <span class="fu">UncheckedIOException</span><span class="op">(</span>e<span class="op">);</span></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Yeesh. So that sucks. We haven't even gotten to printing out the command or labelling groups of commands yet.</p>
<h2 id="construction-zone-">🚧Construction Zone 🚧</h2>
<p>I've been noodling on this for a time and this weekend<sup><a href="#2 ">2</a></sup> I think I finally came up with a half-decent API.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">tools</span><span class="op">.</span><span class="im">ExitStatusException</span><span class="op">;</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">tools</span><span class="op">.</span><span class="im">Tool</span><span class="op">;</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Project <span class="op">{</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>            <span class="kw">throws</span> ExitStatusException <span class="op">{</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Tool</span><span class="op">.</span><span class="fu">ofSubprocess</span><span class="op">(</span><span class="st">&quot;javac&quot;</span><span class="op">)</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">run</span><span class="op">(</span><span class="st">&quot;--version&quot;</span><span class="op">);</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This will print out the command to <code>System.err</code>, run it, throw an exception if needed, and pipe output to <code>System.out</code>/<code>System.err</code> as needed.</p>
<p>Problem is that now we've introduced a dependency.</p>
<p>Hand-waving how you get the dependency<sup><a href="#1">1</a></sup>, the command you need to run the code changes from <code>java scripts/Main.java</code> to <code>java --module-path scripts/libs --add-modules ALL-MODULE-PATH scripts/Main.java</code>.</p>
<p>That's simply too much to remember.</p>
<h3 id="argument-files">Argument Files</h3>
<p>To deal with this we can use argument files.</p>
<p>If we make a file called <code>project</code> at the top level of our project with the following contents.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ex">--module-path</span> scripts/libs <span class="at">--add-modules</span> ALL-MODULE-PATH</span></code></pre></div>
<p>Now we can run the script with just <code>java @project</code>. This works as if all the arguments in the file were applied inline in the invocation. Most tools that come with Java, including the <code>java</code> launcher itself, support this.</p>
<h3 id="picocli">picocli</h3>
<p>As for identifying groups of commands, there is a solution there too. Now that we've opened the floodgates on our Java build script having dependencies, what's one more?</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">tools</span><span class="op">.</span><span class="im">ExitStatusException</span><span class="op">;</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">tools</span><span class="op">.</span><span class="im">Tool</span><span class="op">;</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">picocli</span><span class="op">.</span><span class="im">CommandLine</span><span class="op">;</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a><span class="at">@CommandLine</span><span class="op">.</span><span class="fu">Command</span><span class="op">(</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>        name <span class="op">=</span> <span class="st">&quot;project&quot;</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a><span class="op">)</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> Project <span class="op">{</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">new</span> <span class="fu">CommandLine</span><span class="op">(</span><span class="kw">new</span> <span class="fu">Project</span><span class="op">()).</span><span class="fu">execute</span><span class="op">(</span>args<span class="op">);</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a>    <span class="at">@CommandLine</span><span class="op">.</span><span class="fu">Command</span><span class="op">(</span>name <span class="op">=</span> <span class="st">&quot;demo&quot;</span><span class="op">)</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">demo</span><span class="op">()</span> <span class="kw">throws</span> ExitStatusException <span class="op">{</span></span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Tool</span><span class="op">.</span><span class="fu">ofSubprocess</span><span class="op">(</span><span class="st">&quot;javac&quot;</span><span class="op">)</span></span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">run</span><span class="op">(</span><span class="st">&quot;--version&quot;</span><span class="op">);</span></span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>If we use <code>picocli</code>, then it's trivial. Our build script is a CLI program like any other, why not use normal CLI libraries?</p>
<p>We get the ability to run commands by name.</p>
<pre><code>$ java @project demo  
javac --version
javac 22.0.1</code></pre>
<p>And we even get to list commands in a way.</p>
<pre><code>$ java @project                                                               
Missing required subcommand
Usage: project [COMMAND]
Commands:
  demo</code></pre>
<p>Yay!</p>
<h3 id="tool-tailored-apis">Tool Tailored APIs</h3>
<p>While <code>Tool.ofSubprocess("javac").run("--version");</code> is complete in a sense, it's not very fun to use.</p>
<p>What we generally want from a Java API is method-level autocomplete. Having to separately reference a man page doesn't spark joy in me, and it shouldn't spark joy in you.</p>
<p>I started this particular adventure wanting to translate options from the CLI more or less 1-1. This is for two broad reasons.</p>
<ol type="1">
<li>I think learning how to use the CLI from Java should be transferable knowledge when writing commands the old fashioned way and vice-versa.</li>
<li>There are a lot of CLI tools and coming up with a creative name for every argument that can only be specified as <code>-g</code> is painful and a lot of work.</li>
</ol>
<p>The transform I started with was for every argument that <code>--looks-like-this</code> I would add a method to an arguments object that <code>looksLikeThis</code>.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>Javadoc<span class="op">.</span><span class="fu">run</span><span class="op">(</span>arguments <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>    arguments</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">moduleSourcePath</span><span class="op">(</span><span class="st">&quot;./modules/*/src&quot;</span><span class="op">)</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">d</span><span class="op">(</span>Path<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;build/javadoc&quot;</span><span class="op">))</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">module</span><span class="op">(</span><span class="st">&quot;dev.mccue.tools&quot;</span><span class="op">)</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a><span class="op">});</span></span></code></pre></div>
<p>This works pretty well, but look at these two options from <code>javadoc</code>.</p>
<pre><code>javadoc --help
...
    --version     Print version information
...
    -version      Include @version paragraphs
...</code></pre>
<p>It has both <code>-version</code> and <code>--version</code> and they do wildly different things. Great. Awesome.</p>
<p>This is a one-off example, but CLI tools are fundamentally textual apis. <code>--some-thing</code> to <code>someThing</code> isn't just a stylistic change, it's a lossy transformation.</p>
<p>So I gave up. My only strategy now is to take arguments that <code>--look-like-this</code> and turn them into ones that <code>__look_like_this</code>. It might be ugly, but at least I don't run into strange problems anymore. As a side benefit, it does now look a lot more 1-1 with the CLI api.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>Javadoc<span class="op">.</span><span class="fu">run</span><span class="op">(</span>arguments <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>    arguments</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">__module_source_path</span><span class="op">(</span><span class="st">&quot;./modules/*/src&quot;</span><span class="op">)</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">_d</span><span class="op">(</span>Path<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;build/javadoc&quot;</span><span class="op">))</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">__module</span><span class="op">(</span><span class="st">&quot;dev.mccue.tools&quot;</span><span class="op">)</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a><span class="op">});</span></span></code></pre></div>
<h2 id="conclusion">Conclusion</h2>
<p>I translated the spring demo repo I was using for some previous posts to use this approach. It includes running junit tests and managing multiple modules. You can find it <a href="https://github.com/bowbahdoe/java-project-spring-demo">here</a> and the build script specifically <a href="https://github.com/bowbahdoe/java-project-spring-demo/blob/main/scripts/src/Project.java">here</a>.</p>
<p>Note that the libraries I referenced, save for picocli, are very likely to change in backwards-incompatible ways as I iterate on them. Don't use them for anything serious yet, but you can find them <a href="https://central.sonatype.com/artifact/dev.mccue/tools-jdk">here</a>.</p>
<p>There are still some bootstrap and polish issues, but I think this approach is becoming more and more viable as its chipped away at.</p>
<hr />
<p>Share thoughts, design feedback, etc. in the comments below.</p>
<p id="1" style="font-size: 14px">1: <code>jresolve --output-directory scripts/libs pkg:maven/dev.mccue/tools-jdk@2024.08.25.5</code>.</p>
<p id="2" style="font-size: 14px">2: This approach/outlook on tooling has a lot of similarities to bach and the work Christian Stein
has been doing. Will likely elaborate more on the difference between this approach, bach's approach, bld's approach,
etc. when I personally have more mental clarity on it.</p>

<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>C Growable Arrays: In Depth</title><link>https://mccue.dev/pages/8-21-24-c-growable-arrays-in-depth</link><description></description><pubDate>Wed, 21 Aug 0024 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>C Growable Arrays: In Depth</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">C Growable Arrays: In Depth</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
An extremely common question people have when using `C` for the first time is how to 
make an array of elements that can grow over time.

<p>I know this is a common question because one older post on this website where I explained the concept (badly) gets tons of organic traffic.</p>
<p>It's not a bad question either. Nearly every language you might be coming at <code>C</code> from has an equivalent.</p>
<ul>
<li>Python: <code>list</code></li>
<li>JavaScript: <code>Array</code></li>
<li>Java: <code>ArrayList</code></li>
<li>... etc.</li>
</ul>
<p>And, ignoring primacy, <code>C</code> classes often have students make data structures for their assignments.</p>
<p>So I figure it might be useful to at least one person to give a walkthrough of how that data structure works in the <code>C</code> world.</p>
<p>Just keep in mind that I am not a professional <code>C</code> programmer. If I get anything wrong or there is something you wish I mentioned, feel free to mention it in the comments below or wherever. I'll make corrections.</p>
<h2 id="arrays">Arrays</h2>
<p>An array is a fixed size collection of data.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> numbers<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="dv">1</span><span class="op">,</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="dv">2</span><span class="op">,</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="dv">3</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span></code></pre></div>
<p>Being fixed size means that if an array starts out with enough space for 3 elements, there is no way to make space for a 4th.</p>
<p>C arrays are also, more or less, equivalent to pointers that just so happen to point to the start of a chunk of memory. So whenever you see something like <code>int[]</code> in code you can mentally translate that to <code>int*</code>.</p>
<p>Most languages' array-equivalents can have their size queried at runtime. <code>C</code> is a bit special in that there is no way to recover the number of elements in an array after you make it. It is just a pointer to a chunk of memory after all.</p>
<p>This means you have two basic options for being able to figure out the size of an array.</p>
<h3 id="1-have-a-sentinel-terminate-the-array">1. Have a sentinel terminate the array</h3>
<p>One way to be able to figure out the size of an array is to put a special sentinel value as its last element. Code working with the array can then proceed forward until that special value is reached.</p>
<p>This may or may not be an option depending on the kind of data being stored in an array. The most common use of this actually comes from how <code>C</code> stores strings.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span><span class="op">*</span> hello1 <span class="op">=</span> <span class="st">&quot;Hello&quot;</span><span class="op">;</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span> hello2<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span> <span class="ch">&#39;H&#39;</span><span class="op">,</span> <span class="ch">&#39;e&#39;</span><span class="op">,</span> <span class="ch">&#39;l&#39;</span><span class="op">,</span> <span class="ch">&#39;l&#39;</span><span class="op">,</span> <span class="ch">&#39;o&#39;</span><span class="op">,</span> <span class="ch">&#39;\0&#39;</span> <span class="op">};</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    printf<span class="op">(</span><span class="st">&quot;%s</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> hello1<span class="op">);</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>    printf<span class="op">(</span><span class="st">&quot;%s</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> hello2<span class="op">);</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>"C style strings" are an array of characters terminated by a null character. If you want to find the length of something like this, just keep looping until you get to that terminator.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span><span class="op">*</span> hello <span class="op">=</span> <span class="st">&quot;Hello&quot;</span><span class="op">;</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> <span class="op">(</span>hello<span class="op">[</span>i<span class="op">]</span> <span class="op">!=</span> <span class="ch">&#39;\0&#39;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>        printf<span class="op">(</span><span class="st">&quot;%c</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> hello<span class="op">[</span>i<span class="op">]);</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>        i<span class="op">++;</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>An upside to this approach is that its simple to understand. A downside is that you need to go through every element in the array to find its size, which is a pain.</p>
<h3 id="2-store-it-when-you-make-the-array">2. Store it when you make the Array</h3>
<p>If we don't want to have the null terminator we need to store a number.</p>
<p>One way to do this is to just manually count out how big an array is.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> numbers<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>        <span class="dv">6</span><span class="op">,</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>        <span class="dv">4</span><span class="op">,</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>        <span class="dv">7</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>    <span class="co">// I counted it with my eyes</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> numbers_size <span class="op">=</span> <span class="dv">3</span><span class="op">;</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> <span class="op">(</span>i <span class="op">&lt;</span> numbers_size<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>        printf<span class="op">(</span><span class="st">&quot;%d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> numbers<span class="op">[</span>i<span class="op">]);</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>        i<span class="op">++;</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>If when you initialize your array you write the number of elements directly, you can make use of <code>sizeof</code> to calculate the size.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> numbers<span class="op">[</span><span class="dv">3</span><span class="op">]</span> <span class="op">=</span> <span class="op">{</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>        <span class="dv">6</span><span class="op">,</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>        <span class="dv">4</span><span class="op">,</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>        <span class="dv">7</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Because of the literal [3] above, C can figure out</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>    <span class="co">// how many elements there are by dividing the total</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>    <span class="co">// size of the array by the size of an individual</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a>    <span class="co">// element.</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> numbers_size <span class="op">=</span> <span class="kw">sizeof</span><span class="op">(</span>numbers<span class="op">)</span> <span class="op">/</span> <span class="kw">sizeof</span><span class="op">(</span>numbers<span class="op">[</span><span class="dv">0</span><span class="op">]);</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> <span class="op">(</span>i <span class="op">&lt;</span> numbers_size<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a>        printf<span class="op">(</span><span class="st">&quot;%d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> numbers<span class="op">[</span>i<span class="op">]);</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a>        i<span class="op">++;</span></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>You then need to handle passing that size around with the array whenever you give it to a function that takes an array as an argument. A good deal of the <code>C</code> standard library works like this.</p>
<h2 id="size_t"><code>size_t</code></h2>
<p>Small digression. When you make a variable to store an index into array or that stores the size of an array you are intended to use <code>size_t</code>.</p>
<p>If you don't it seems like its usually "fine," but I wouldn't risk the wrath of the undefined behavior demons.</p>
<p>To have <code>size_t</code> be available you should put <code>#include &lt;stddef.h&gt;</code> at the top of your program.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stddef.h&gt;</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> numbers<span class="op">[</span><span class="dv">3</span><span class="op">]</span> <span class="op">=</span> <span class="op">{</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>        <span class="dv">6</span><span class="op">,</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>        <span class="dv">4</span><span class="op">,</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>        <span class="dv">7</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> numbers_size <span class="op">=</span> <span class="kw">sizeof</span><span class="op">(</span>numbers<span class="op">)</span> <span class="op">/</span> <span class="kw">sizeof</span><span class="op">(</span>numbers<span class="op">[</span><span class="dv">0</span><span class="op">]);</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> <span class="op">(</span>i <span class="op">&lt;</span> numbers_size<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a>        printf<span class="op">(</span><span class="st">&quot;%d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> numbers<span class="op">[</span>i<span class="op">]);</span></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a>        i<span class="op">++;</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="heap-allocation">Heap Allocation</h2>
<p>At runtime, you can get an arbitrarily large block of memory in various ways.</p>
<p>The most commonly known is <code>malloc</code>. You give it a size then it gives you a pointer to the start of that memory. You need <code>#include &lt;stdlib.h&gt;</code> to use it.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stddef.h&gt;</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdlib.h&gt;</span><span class="pp"> </span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> numbers_size <span class="op">=</span> <span class="dv">3</span><span class="op">;</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span><span class="op">*</span> numbers <span class="op">=</span> malloc<span class="op">(</span><span class="kw">sizeof</span><span class="op">(</span><span class="dt">int</span><span class="op">)</span> <span class="op">*</span> numbers_size<span class="op">);</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>    numbers<span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">=</span> <span class="dv">6</span><span class="op">;</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>    numbers<span class="op">[</span><span class="dv">1</span><span class="op">]</span> <span class="op">=</span> <span class="dv">4</span><span class="op">;</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>    numbers<span class="op">[</span><span class="dv">2</span><span class="op">]</span> <span class="op">=</span> <span class="dv">7</span><span class="op">;</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> <span class="op">(</span>i <span class="op">&lt;</span> numbers_size<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a>        printf<span class="op">(</span><span class="st">&quot;%d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> numbers<span class="op">[</span>i<span class="op">]);</span></span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true" tabindex="-1"></a>        i<span class="op">++;</span></span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The one we will use is <code>calloc</code>. It works mostly the same as its cousin <code>malloc</code> with two major differences.</p>
<p>The first is that you don't give it the full size of the array you want. You give it the size of each element and the number of elements you want seperately.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stddef.h&gt;</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdlib.h&gt;</span><span class="pp"> </span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> numbers_size <span class="op">=</span> <span class="dv">3</span><span class="op">;</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span><span class="op">*</span> numbers <span class="op">=</span> calloc<span class="op">(</span><span class="kw">sizeof</span><span class="op">(</span><span class="dt">int</span><span class="op">),</span> numbers_size<span class="op">);</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>    numbers<span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">=</span> <span class="dv">6</span><span class="op">;</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>    numbers<span class="op">[</span><span class="dv">1</span><span class="op">]</span> <span class="op">=</span> <span class="dv">4</span><span class="op">;</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>    numbers<span class="op">[</span><span class="dv">2</span><span class="op">]</span> <span class="op">=</span> <span class="dv">7</span><span class="op">;</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> <span class="op">(</span>i <span class="op">&lt;</span> numbers_size<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>        printf<span class="op">(</span><span class="st">&quot;%d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> numbers<span class="op">[</span>i<span class="op">]);</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a>        i<span class="op">++;</span></span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The second is that the memory returned is already "zeroed." This means that you know that every element is in its zero-valued state. So for <code>int</code> it will literally be <code>0</code>, <code>_Bool</code>s will be <code>false</code>, pointers will be <code>NULL</code>, etc.</p>
<p>Often that doesn't matter but, because there isn't "uninitialized" memory with random data in it, it feels more predictable.</p>
<p>For both approaches you need to later <code>free</code> that allocated memory. You will be technically exempt from needing to do this if your program doesn't run for long enough to run out of memory. I think it is best to be a "good citizen" and <code>free</code> your memory regardless.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stddef.h&gt;</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdlib.h&gt;</span><span class="pp"> </span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> numbers_size <span class="op">=</span> <span class="dv">3</span><span class="op">;</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span><span class="op">*</span> numbers <span class="op">=</span> calloc<span class="op">(</span><span class="kw">sizeof</span><span class="op">(</span><span class="dt">int</span><span class="op">),</span> numbers_size<span class="op">);</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>    numbers<span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">=</span> <span class="dv">6</span><span class="op">;</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>    numbers<span class="op">[</span><span class="dv">1</span><span class="op">]</span> <span class="op">=</span> <span class="dv">4</span><span class="op">;</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>    numbers<span class="op">[</span><span class="dv">2</span><span class="op">]</span> <span class="op">=</span> <span class="dv">7</span><span class="op">;</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> <span class="op">(</span>i <span class="op">&lt;</span> numbers_size<span class="op">)</span> <span class="op">{</span></span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true" tabindex="-1"></a>        printf<span class="op">(</span><span class="st">&quot;%d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> numbers<span class="op">[</span>i<span class="op">]);</span></span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true" tabindex="-1"></a>        i<span class="op">++;</span></span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-19"><a href="#cb9-19" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb9-20"><a href="#cb9-20" aria-hidden="true" tabindex="-1"></a>    free<span class="op">(</span>numbers<span class="op">);</span></span>
<span id="cb9-21"><a href="#cb9-21" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb9-22"><a href="#cb9-22" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb9-23"><a href="#cb9-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Technically speaking <code>malloc</code>, <code>calloc</code>, etc. can fail if the system is out of memory. We are going to ignore that possibility for the rest of this, but the lower level software you write the larger chance you will need to care about very limited memory scenarios.</p>
<h2 id="single-type-growable-arrays">Single Type Growable Arrays</h2>
<p>The basic concept of a growable array is to group three pieces of information. A pointer to an array of things, the number of elements allocated for that array, and the number of elements "actually" in the array.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> GrowableIntArray <span class="op">{</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span><span class="op">*</span> data<span class="op">;</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> allocated<span class="op">;</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> size<span class="op">;</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>So for a new array with nothing in it, the <code>data</code> pointer would be null and both numbers would be <code>0</code>.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> GrowableIntArray growable_int_array_empty<span class="op">()</span> <span class="op">{</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> GrowableIntArray empty <span class="op">=</span> <span class="op">{</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>       <span class="op">.</span>data <span class="op">=</span> NULL<span class="op">,</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>       <span class="op">.</span>allocated <span class="op">=</span> <span class="dv">0</span><span class="op">,</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>       <span class="op">.</span>size <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> empty<span class="op">;</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>To add an element to the array, you check if adding the element would make the size of the array larger than what was allocated.</p>
<p>If it won't, you set an element in your <code>data</code> array and bump the size.</p>
<p>If it will, you need to make a new array that is bigger than the last one. How much bigger is more art than science, but generally people find success allocating around twice as many elements as were there before.</p>
<p>That sounds crazy, but at worst you are only wasting half your memory. That's not that bad in the scope of things.</p>
<p>Then you copy over all the elements from the last array and free the old one.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> growable_int_array_add<span class="op">(</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> GrowableIntArray<span class="op">*</span> array<span class="op">,</span> </span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> value</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">// If we wouldn&#39;t have enough room</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>array<span class="op">-&gt;</span>size <span class="op">+</span> <span class="dv">1</span> <span class="op">&gt;</span> array<span class="op">-&gt;</span>allocated<span class="op">)</span> <span class="op">{</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>       <span class="co">// Double the size of the last array</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>       <span class="dt">size_t</span> new_allocated<span class="op">;</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>       <span class="cf">if</span> <span class="op">(</span>array<span class="op">-&gt;</span>size <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>           new_allocated <span class="op">=</span> <span class="dv">2</span><span class="op">;</span></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>       <span class="op">}</span></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a>       <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a>           new_allocated <span class="op">=</span> array<span class="op">-&gt;</span>size <span class="op">*</span> <span class="dv">2</span><span class="op">;</span></span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a>       <span class="op">}</span></span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a>       </span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true" tabindex="-1"></a>       <span class="co">// Make a new array that size</span></span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true" tabindex="-1"></a>       <span class="dt">int</span><span class="op">*</span> new_data <span class="op">=</span> calloc<span class="op">(</span><span class="kw">sizeof</span><span class="op">(</span><span class="dt">int</span><span class="op">),</span> new_allocated<span class="op">);</span></span>
<span id="cb12-18"><a href="#cb12-18" aria-hidden="true" tabindex="-1"></a>       <span class="dt">int</span><span class="op">*</span> old_data <span class="op">=</span> array<span class="op">-&gt;</span>data<span class="op">;</span></span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true" tabindex="-1"></a>       </span>
<span id="cb12-20"><a href="#cb12-20" aria-hidden="true" tabindex="-1"></a>       <span class="co">// Copy all the old elements to it</span></span>
<span id="cb12-21"><a href="#cb12-21" aria-hidden="true" tabindex="-1"></a>       <span class="cf">if</span> <span class="op">(</span>old_data <span class="op">!=</span> NULL<span class="op">)</span> <span class="op">{</span></span>
<span id="cb12-22"><a href="#cb12-22" aria-hidden="true" tabindex="-1"></a>           <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> array<span class="op">-&gt;</span>size<span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb12-23"><a href="#cb12-23" aria-hidden="true" tabindex="-1"></a>               new_data<span class="op">[</span>i<span class="op">]</span> <span class="op">=</span> old_data<span class="op">[</span>i<span class="op">];</span></span>
<span id="cb12-24"><a href="#cb12-24" aria-hidden="true" tabindex="-1"></a>           <span class="op">}</span></span>
<span id="cb12-25"><a href="#cb12-25" aria-hidden="true" tabindex="-1"></a>       <span class="op">}</span></span>
<span id="cb12-26"><a href="#cb12-26" aria-hidden="true" tabindex="-1"></a>       </span>
<span id="cb12-27"><a href="#cb12-27" aria-hidden="true" tabindex="-1"></a>       <span class="co">// Then free the old array</span></span>
<span id="cb12-28"><a href="#cb12-28" aria-hidden="true" tabindex="-1"></a>       free<span class="op">(</span>old_data<span class="op">);</span></span>
<span id="cb12-29"><a href="#cb12-29" aria-hidden="true" tabindex="-1"></a>       </span>
<span id="cb12-30"><a href="#cb12-30" aria-hidden="true" tabindex="-1"></a>       <span class="co">// And patch up the pointers </span></span>
<span id="cb12-31"><a href="#cb12-31" aria-hidden="true" tabindex="-1"></a>       array<span class="op">-&gt;</span>data <span class="op">=</span> new_data<span class="op">;</span></span>
<span id="cb12-32"><a href="#cb12-32" aria-hidden="true" tabindex="-1"></a>       array<span class="op">-&gt;</span>allocated <span class="op">=</span> new_allocated<span class="op">;</span></span>
<span id="cb12-33"><a href="#cb12-33" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb12-34"><a href="#cb12-34" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb12-35"><a href="#cb12-35" aria-hidden="true" tabindex="-1"></a>    <span class="co">// And put in the new element</span></span>
<span id="cb12-36"><a href="#cb12-36" aria-hidden="true" tabindex="-1"></a>    array<span class="op">-&gt;</span>data<span class="op">[</span>array<span class="op">-&gt;</span>size<span class="op">]</span> <span class="op">=</span> value<span class="op">;</span></span>
<span id="cb12-37"><a href="#cb12-37" aria-hidden="true" tabindex="-1"></a>    array<span class="op">-&gt;</span>size<span class="op">++;</span></span>
<span id="cb12-38"><a href="#cb12-38" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Which is a chunky function, but now you should be good to go on making something which you can use as an array but which dynamically grows as elements are added.</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> GrowableIntArray numbers </span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>        <span class="op">=</span> growable_int_array_empty<span class="op">();</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>    growable_int_array_add<span class="op">(&amp;</span>numbers<span class="op">,</span> <span class="dv">6</span><span class="op">);</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>    growable_int_array_add<span class="op">(&amp;</span>numbers<span class="op">,</span> <span class="dv">4</span><span class="op">);</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>    growable_int_array_add<span class="op">(&amp;</span>numbers<span class="op">,</span> <span class="dv">7</span><span class="op">);</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> <span class="op">(</span>i <span class="op">&lt;</span> numbers<span class="op">.</span>size<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>        printf<span class="op">(</span><span class="st">&quot;%d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> numbers<span class="op">.</span>data<span class="op">[</span>i<span class="op">]);</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a>        i<span class="op">++;</span></span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>From there it's all a matter of personal taste. Many would want to implement their own <code>growable_int_array_size</code> and <code>growable_int_array_get</code>. Both of these are relatively straight forward and useful if your goal is to avoid accessing struct members directly</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="dt">size_t</span> growable_int_array_size<span class="op">(</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> GrowableIntArray<span class="op">*</span> array</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> array<span class="op">-&gt;</span>size<span class="op">;</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> growable_int_array_get<span class="op">(</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> GrowableIntArray<span class="op">*</span> array<span class="op">,</span> </span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> i</span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a>    <span class="co">// You can do precondition checks and crash early if someone</span></span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a>    <span class="co">// tries to out of bounds if you want.</span></span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> array<span class="op">-&gt;</span>data<span class="op">[</span>i<span class="op">];</span></span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb15"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> GrowableIntArray numbers </span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>        <span class="op">=</span> growable_int_array_empty<span class="op">();</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>    growable_int_array_add<span class="op">(&amp;</span>numbers<span class="op">,</span> <span class="dv">6</span><span class="op">);</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>    growable_int_array_add<span class="op">(&amp;</span>numbers<span class="op">,</span> <span class="dv">4</span><span class="op">);</span></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>    growable_int_array_add<span class="op">(&amp;</span>numbers<span class="op">,</span> <span class="dv">7</span><span class="op">);</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> <span class="op">(</span>i <span class="op">&lt;</span> growable_int_array_size<span class="op">(&amp;</span>numbers<span class="op">))</span> <span class="op">{</span></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a>        printf<span class="op">(</span><span class="st">&quot;%d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> growable_int_array_get<span class="op">(&amp;</span>numbers<span class="op">,</span> i<span class="op">));</span></span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true" tabindex="-1"></a>        i<span class="op">++;</span></span>
<span id="cb15-15"><a href="#cb15-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb15-16"><a href="#cb15-16" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb15-17"><a href="#cb15-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>But all of this has a <strong>major</strong> flaw. Do you see it?</p>
<p>It only works with <code>int</code>s! If you want to have a growable array of <code>long</code>s or <code>Position</code>s or whatever, you need to copy and paste all of this code, change the types around, and make brand-new functions.</p>
<p>What we want is the ability to write code for a growable array once and then have that work for any kind of data we want to store. That gives leaves us with two options.</p>
<ol type="1">
<li>Make a growable array that can be used for anything at runtime</li>
<li>Make a growable array that can be specialized for anything at compile-time.</li>
</ol>
<h2 id="runtime-generic-growable-arrays">Runtime Generic Growable Arrays</h2>
<p>What do an <code>int</code>, a <code>char</code> and a <code>struct Position</code> have in common? Nothing. Save some really strange layout choices by a compiler, all of these data types require different amounts of memory.</p>
<p>What do an <code>int*</code>, a <code>char*</code>, and a <code>struct Position*</code> have in common? Turns out all of them can be safely converted to and from a <code>void*</code>.</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> eight <span class="op">=</span> <span class="dv">8</span><span class="op">;</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span><span class="op">*</span> eightPointer <span class="op">=</span> <span class="op">&amp;</span>eight<span class="op">;</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span><span class="op">*</span> voidPointer <span class="op">=</span> <span class="op">(</span><span class="dt">void</span><span class="op">*)</span> eightPointer<span class="op">;</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>    eightPointer <span class="op">=</span> <span class="op">(</span><span class="dt">int</span><span class="op">*)</span> voidPointer<span class="op">;</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>    printf<span class="op">(</span><span class="st">&quot;%d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> <span class="op">*</span>eightPointer<span class="op">);</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>A <code>void*</code> is a pointer to "something." The <code>C</code> compiler forgets what kind of information is actually stored in it. All pointers in <code>C</code> have the same size, so now we have our way of storing anything.</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> GrowableArray <span class="op">{</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span><span class="op">**</span> data<span class="op">;</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> allocated<span class="op">;</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> size<span class="op">;</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>At first, it might seem like we can just do that and find+replace <code>int</code> with <code>void*</code> in the code from before. And you'd be right. Just be aware that things which were once <code>int*</code> will become <code>void**</code>. A pointer to an array of <code>void</code> pointers.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> growable_array_add<span class="op">(</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> GrowableArray<span class="op">*</span> array<span class="op">,</span> </span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span><span class="op">*</span> value</span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">// If we wouldn&#39;t have enough room</span></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>array<span class="op">-&gt;</span>size <span class="op">+</span> <span class="dv">1</span> <span class="op">&gt;</span> array<span class="op">-&gt;</span>allocated<span class="op">)</span> <span class="op">{</span></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a>       <span class="co">// Double the size of the last array</span></span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a>       <span class="dt">size_t</span> new_allocated<span class="op">;</span></span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a>       <span class="cf">if</span> <span class="op">(</span>array<span class="op">-&gt;</span>size <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a>           new_allocated <span class="op">=</span> <span class="dv">2</span><span class="op">;</span></span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a>       <span class="op">}</span></span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a>       <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb18-13"><a href="#cb18-13" aria-hidden="true" tabindex="-1"></a>           new_allocated <span class="op">=</span> array<span class="op">-&gt;</span>size <span class="op">*</span> <span class="dv">2</span><span class="op">;</span></span>
<span id="cb18-14"><a href="#cb18-14" aria-hidden="true" tabindex="-1"></a>       <span class="op">}</span></span>
<span id="cb18-15"><a href="#cb18-15" aria-hidden="true" tabindex="-1"></a>       </span>
<span id="cb18-16"><a href="#cb18-16" aria-hidden="true" tabindex="-1"></a>       <span class="co">// Make a new array that size</span></span>
<span id="cb18-17"><a href="#cb18-17" aria-hidden="true" tabindex="-1"></a>       <span class="dt">void</span><span class="op">**</span> new_data <span class="op">=</span> <span class="op">(</span><span class="dt">void</span><span class="op">**)</span> calloc<span class="op">(</span></span>
<span id="cb18-18"><a href="#cb18-18" aria-hidden="true" tabindex="-1"></a>            <span class="kw">sizeof</span><span class="op">(</span><span class="dt">void</span><span class="op">*),</span> </span>
<span id="cb18-19"><a href="#cb18-19" aria-hidden="true" tabindex="-1"></a>            new_allocated</span>
<span id="cb18-20"><a href="#cb18-20" aria-hidden="true" tabindex="-1"></a>       <span class="op">);</span></span>
<span id="cb18-21"><a href="#cb18-21" aria-hidden="true" tabindex="-1"></a>       <span class="dt">void</span><span class="op">**</span> old_data <span class="op">=</span> array<span class="op">-&gt;</span>data<span class="op">;</span></span>
<span id="cb18-22"><a href="#cb18-22" aria-hidden="true" tabindex="-1"></a>       </span>
<span id="cb18-23"><a href="#cb18-23" aria-hidden="true" tabindex="-1"></a>       <span class="co">// Copy all the old elements to it</span></span>
<span id="cb18-24"><a href="#cb18-24" aria-hidden="true" tabindex="-1"></a>       <span class="cf">if</span> <span class="op">(</span>old_data <span class="op">!=</span> NULL<span class="op">)</span> <span class="op">{</span></span>
<span id="cb18-25"><a href="#cb18-25" aria-hidden="true" tabindex="-1"></a>           <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> array<span class="op">-&gt;</span>size<span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb18-26"><a href="#cb18-26" aria-hidden="true" tabindex="-1"></a>               new_data<span class="op">[</span>i<span class="op">]</span> <span class="op">=</span> old_data<span class="op">[</span>i<span class="op">];</span></span>
<span id="cb18-27"><a href="#cb18-27" aria-hidden="true" tabindex="-1"></a>           <span class="op">}</span></span>
<span id="cb18-28"><a href="#cb18-28" aria-hidden="true" tabindex="-1"></a>       <span class="op">}</span></span>
<span id="cb18-29"><a href="#cb18-29" aria-hidden="true" tabindex="-1"></a>       </span>
<span id="cb18-30"><a href="#cb18-30" aria-hidden="true" tabindex="-1"></a>       <span class="co">// Then free the old array</span></span>
<span id="cb18-31"><a href="#cb18-31" aria-hidden="true" tabindex="-1"></a>       free<span class="op">(</span>old_data<span class="op">);</span></span>
<span id="cb18-32"><a href="#cb18-32" aria-hidden="true" tabindex="-1"></a>       </span>
<span id="cb18-33"><a href="#cb18-33" aria-hidden="true" tabindex="-1"></a>       <span class="co">// And patch up the pointers </span></span>
<span id="cb18-34"><a href="#cb18-34" aria-hidden="true" tabindex="-1"></a>       array<span class="op">-&gt;</span>data <span class="op">=</span> new_data<span class="op">;</span></span>
<span id="cb18-35"><a href="#cb18-35" aria-hidden="true" tabindex="-1"></a>       array<span class="op">-&gt;</span>allocated <span class="op">=</span> new_allocated<span class="op">;</span></span>
<span id="cb18-36"><a href="#cb18-36" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb18-37"><a href="#cb18-37" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb18-38"><a href="#cb18-38" aria-hidden="true" tabindex="-1"></a>    <span class="co">// And put in the new element</span></span>
<span id="cb18-39"><a href="#cb18-39" aria-hidden="true" tabindex="-1"></a>    array<span class="op">-&gt;</span>data<span class="op">[</span>array<span class="op">-&gt;</span>size<span class="op">]</span> <span class="op">=</span> value<span class="op">;</span></span>
<span id="cb18-40"><a href="#cb18-40" aria-hidden="true" tabindex="-1"></a>    array<span class="op">-&gt;</span>size<span class="op">++;</span></span>
<span id="cb18-41"><a href="#cb18-41" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="usability">Usability</h3>
<p>The first problems that will arise are around usability.</p>
<p>To pass a pointer in, it can't be an <code>rvalue</code>. An <code>rvalue</code> is something that should go on the <em>right</em> hand size of an equals sign. That's where the <code>r</code> comes from.</p>
<p>This means that you can't just directly pass in a pointer to an <code>int</code>.</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>growable_array_add<span class="op">(&amp;</span>numbers<span class="op">,</span> <span class="op">&amp;</span><span class="dv">6</span><span class="op">);</span></span></code></pre></div>
<p><code>&amp;6</code> doesn't have a meaning to <code>C</code>. You need to have constant values first assigned to a variable.</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> n <span class="op">=</span> <span class="dv">6</span><span class="op">;</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>growable_array_add<span class="op">(&amp;</span>numbers<span class="op">,</span> <span class="op">&amp;</span>n<span class="op">);</span></span></code></pre></div>
<p>This can be annoying to write out, but you might get used to it. Even harder to come to terms with is needing to recover the type of a pointer whenever you get it out.</p>
<p>You need to both convert the <code>void*</code> to an <code>int*</code> or whatever actual type you stored and, if it's something like <code>int</code>, dereference that pointer to get at the actual value.</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> value <span class="op">=</span> <span class="op">*((</span><span class="dt">int</span><span class="op">*)</span> growable_array_get<span class="op">(&amp;</span>numbers<span class="op">,</span> i<span class="op">));</span></span></code></pre></div>
<p>The <code>C</code> compiler doesn't take kindly to mishandled <code>void*</code>s. If you get this wrong you get teleported to Florida.</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> GrowableArray numbers </span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>        <span class="op">=</span> growable_array_empty<span class="op">();</span></span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a>      </span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> a <span class="op">=</span> <span class="dv">6</span><span class="op">;</span></span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> b <span class="op">=</span> <span class="dv">4</span><span class="op">;</span></span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> c <span class="op">=</span> <span class="dv">7</span><span class="op">;</span></span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a>    growable_array_add<span class="op">(&amp;</span>numbers<span class="op">,</span> <span class="op">&amp;</span>a<span class="op">);</span></span>
<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a>    growable_array_add<span class="op">(&amp;</span>numbers<span class="op">,</span> <span class="op">&amp;</span>b<span class="op">);</span></span>
<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a>    growable_array_add<span class="op">(&amp;</span>numbers<span class="op">,</span> <span class="op">&amp;</span>c<span class="op">);</span></span>
<span id="cb22-13"><a href="#cb22-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-14"><a href="#cb22-14" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb22-15"><a href="#cb22-15" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb22-16"><a href="#cb22-16" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> <span class="op">(</span>i <span class="op">&lt;</span> growable_array_size<span class="op">(&amp;</span>numbers<span class="op">))</span> <span class="op">{</span></span>
<span id="cb22-17"><a href="#cb22-17" aria-hidden="true" tabindex="-1"></a>        printf<span class="op">(</span><span class="st">&quot;%d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> <span class="op">*((</span><span class="dt">int</span><span class="op">*)</span> growable_array_get<span class="op">(&amp;</span>numbers<span class="op">,</span> i<span class="op">)));</span></span>
<span id="cb22-18"><a href="#cb22-18" aria-hidden="true" tabindex="-1"></a>        i<span class="op">++;</span></span>
<span id="cb22-19"><a href="#cb22-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb22-20"><a href="#cb22-20" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb22-21"><a href="#cb22-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="pointer-lifetimes">Pointer Lifetimes</h3>
<p>Pointers don't all "live" the same amount of time. You can take a pointer to a local variable, but that pointer is only valid so long as you are still within that function.</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span><span class="op">*</span> example<span class="op">()</span> <span class="op">{</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>   <span class="dt">int</span> x <span class="op">=</span> <span class="dv">5</span><span class="op">;</span></span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>   <span class="dt">int</span><span class="op">*</span> xPointer <span class="op">=</span> <span class="op">&amp;</span>x<span class="op">;</span></span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>   </span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a>   <span class="co">// Can use xPointer freely</span></span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a>   </span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a>   <span class="co">// But if you return the pointer out it won&#39;t</span></span>
<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a>   <span class="co">// be valid</span></span>
<span id="cb23-9"><a href="#cb23-9" aria-hidden="true" tabindex="-1"></a>   <span class="cf">return</span> xPointer<span class="op">;</span></span>
<span id="cb23-10"><a href="#cb23-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>You can make pointers that live longer with <code>calloc</code>, but you later need to call <code>free</code> on them.</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span><span class="op">*</span> example<span class="op">()</span> <span class="op">{</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>   <span class="dt">int</span><span class="op">*</span> xPointer <span class="op">=</span> calloc<span class="op">(</span><span class="kw">sizeof</span><span class="op">(</span><span class="dt">int</span><span class="op">),</span> <span class="dv">1</span><span class="op">);</span></span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>   <span class="op">*</span>xPointer <span class="op">=</span> <span class="dv">5</span><span class="op">;</span></span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>   </span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a>   <span class="co">// Valid to return, but something eventually</span></span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a>   <span class="co">// should free it.</span></span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a>   <span class="cf">return</span> xPointer<span class="op">;</span></span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This presents a problem for our array of <code>void*</code>s. If all the pointers are pointing to local variables on the stack then your cleanup should just be to call <code>free</code> on <code>array.data</code>.</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> growable_array_cleanup<span class="op">(</span><span class="kw">struct</span> GrowableArray array<span class="op">)</span> <span class="op">{</span></span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a>    free<span class="op">(</span>array<span class="op">.</span>data<span class="op">);</span></span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>But if the pointers are pointing to heap allocated memory then someone needs to clean them up later.</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> growable_array_cleanup<span class="op">(</span><span class="kw">struct</span> GrowableArray<span class="op">*</span> array<span class="op">)</span> <span class="op">{</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> array<span class="op">-&gt;</span>size<span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a>        free<span class="op">(</span>array<span class="op">-&gt;</span>data<span class="op">[</span>i<span class="op">]);</span></span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a>    free<span class="op">(</span>array<span class="op">-&gt;</span>data<span class="op">);</span></span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Even worse than that, some things don't just need to be <code>free</code>-ed. They might have been allocated outside the <code>calloc</code>/<code>free</code> system or, like our <code>GrowableArray</code>, they might have some custom cleanup process.</p>
<p>To deal with the sheer variety of situations we need to store how we want to clean up elements in the array itself.</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> GrowableArray <span class="op">{</span></span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span><span class="op">**</span> data<span class="op">;</span></span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> allocated<span class="op">;</span></span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> size<span class="op">;</span></span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="op">(*</span>cleanup<span class="op">)(</span><span class="dt">void</span><span class="op">*);</span></span>
<span id="cb27-6"><a href="#cb27-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This syntax - <code>void (*cleanup)(void*)</code> - is how you declare a pointer to a function. In this case a function whose return type is <code>void</code> and whose sole argument is a <code>void*</code>. If it looks confusing to you don't worry. It confuses me too.</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> GrowableIntArray growable_array_empty<span class="op">(</span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="op">(*</span>cleanup<span class="op">)(</span><span class="dt">void</span><span class="op">*)</span></span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> growable_array_empty<span class="op">(</span>NULL<span class="op">);</span></span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> GrowableArray growable_array_empty<span class="op">(</span></span>
<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="op">(*</span>cleanup<span class="op">)(</span><span class="dt">void</span><span class="op">*)</span></span>
<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> GrowableArray empty <span class="op">=</span> <span class="op">{</span></span>
<span id="cb28-11"><a href="#cb28-11" aria-hidden="true" tabindex="-1"></a>       <span class="op">.</span>data <span class="op">=</span> NULL<span class="op">,</span></span>
<span id="cb28-12"><a href="#cb28-12" aria-hidden="true" tabindex="-1"></a>       <span class="op">.</span>allocated <span class="op">=</span> <span class="dv">0</span><span class="op">,</span></span>
<span id="cb28-13"><a href="#cb28-13" aria-hidden="true" tabindex="-1"></a>       <span class="op">.</span>size <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb28-14"><a href="#cb28-14" aria-hidden="true" tabindex="-1"></a>       <span class="op">.</span>cleanup <span class="op">=</span> cleanup</span>
<span id="cb28-15"><a href="#cb28-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb28-16"><a href="#cb28-16" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb28-17"><a href="#cb28-17" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> empty<span class="op">;</span></span>
<span id="cb28-18"><a href="#cb28-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Once you have the cleanup function stored you can make a general cleanup function for the growable array itself.</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> growable_array_cleanup<span class="op">(</span><span class="kw">struct</span> GrowableArray<span class="op">*</span> array<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>array<span class="op">-&gt;</span>cleanup <span class="op">!=</span> NULL<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> array<span class="op">-&gt;</span>size<span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a>            array<span class="op">-&gt;</span>cleanup<span class="op">(</span>array<span class="op">-&gt;</span>data<span class="op">[</span>i<span class="op">]);</span></span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb29-6"><a href="#cb29-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb29-7"><a href="#cb29-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-8"><a href="#cb29-8" aria-hidden="true" tabindex="-1"></a>    free<span class="op">(</span>array<span class="op">-&gt;</span>data<span class="op">);</span></span>
<span id="cb29-9"><a href="#cb29-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>If their data is on the stack, you skip trying to <code>free</code> it. If it needs to be <code>free</code>-ed that can be done same as if you need to call <code>special_framework_destroy</code>.</p>
<p>While this might seem like we've solved the problem, notice that no matter what we need to now track when to call a special <code>growable_array_cleanup</code>, each array has an extra pointer of memory, and has to check if <code>array-&gt;cleanup != NULL</code> at close. Everything comes at a cost.</p>
<h3 id="memory-locality">Memory Locality</h3>
<p>Following the same theme, this sort of structure is forced to have subpar memory locality.</p>
<p>If you were to make an <code>int</code> array, the memory would be laid out like this with each <code>int</code> being directly next to the others.</p>
<div class="sourceCode" id="cb30"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="op">-------------</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a><span class="op">|</span> <span class="dv">5</span> <span class="op">|</span> <span class="dv">4</span> <span class="op">|</span> <span class="dv">3</span> <span class="op">|</span></span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a><span class="op">-------------</span></span></code></pre></div>
<p>When we make an array of <code>int</code> pointers the memory layout looks like this.</p>
<div class="sourceCode" id="cb31"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a><span class="op">-------------------</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a><span class="op">|</span> ptr <span class="op">|</span> ptr <span class="op">|</span> ptr <span class="op">|</span></span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a><span class="op">---|-----|-----|---</span></span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a>   V     <span class="op">|</span>     <span class="op">|</span></span>
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a>   <span class="dv">5</span>     V     <span class="op">|</span></span>
<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a>         <span class="dv">4</span>     V</span>
<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a>               <span class="dv">3</span></span></code></pre></div>
<p>Modern CPUs love going through arrays in order. They hate following pointers. This memory layout is almost guaranteed to lead to subpar performance compared to the tightly packed array.</p>
<p>Notice also that we didn't choose this memory layout because we wanted to. We chose it because we didn't want to write out the data structure more than once.</p>
<h2 id="compile-time-generic-growable-arrays">Compile-Time Generic Growable Arrays</h2>
<p>If we don't want everything behind a <code>void*</code> we need a perfect vinaigrette of clever and stupid.</p>
<h3 id="template-headers">Template Headers</h3>
<p>The only things that need to change between a growable <code>int</code> array and a growable <code>struct Position</code> array are the struct names, function names, return types, and arguments.</p>
<div class="sourceCode" id="cb32"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> GrowableIntArray <span class="op">{</span></span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span><span class="op">*</span> data<span class="op">;</span></span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> allocated<span class="op">;</span></span>
<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> size<span class="op">;</span></span>
<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> GrowablePositionArray <span class="op">{</span></span>
<span id="cb32-8"><a href="#cb32-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> Position<span class="op">*</span> data<span class="op">;</span></span>
<span id="cb32-9"><a href="#cb32-9" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> allocated<span class="op">;</span></span>
<span id="cb32-10"><a href="#cb32-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> size<span class="op">;</span></span>
<span id="cb32-11"><a href="#cb32-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>But we don't need to do that by hand. We have the <code>C</code> preprocessor.</p>
<div class="sourceCode" id="cb33"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#define GROWABLE_ARRAY_STRUCT struct GrowableIntArray</span></span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#define GROWABLE_ARRAY_DATA_POINTER int*</span></span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a>GROWABLE_ARRAY_STRUCT <span class="op">{</span></span>
<span id="cb33-5"><a href="#cb33-5" aria-hidden="true" tabindex="-1"></a>    GROWABLE_ARRAY_DATA_POINTER data<span class="op">;</span></span>
<span id="cb33-6"><a href="#cb33-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> allocated<span class="op">;</span></span>
<span id="cb33-7"><a href="#cb33-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> size<span class="op">;</span></span>
<span id="cb33-8"><a href="#cb33-8" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span></code></pre></div>
<p>If you've made a <code>C</code> header file before you've probably seen a prelude like this.</p>
<div class="sourceCode" id="cb34"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#ifndef SOME_FILE_H</span></span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#define SOME_FILE_H</span></span>
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a><span class="co">// ... CODE FOR HEADER HERE ...</span></span>
<span id="cb34-5"><a href="#cb34-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb34-6"><a href="#cb34-6" aria-hidden="true" tabindex="-1"></a><span class="pp">#endif</span></span></code></pre></div>
<p>The purpose of this is so that if more than one file includes the header the code for it only shows up once.</p>
<p>Here we don't want to do that. We want it to be able to be included multiple times in one compilation.</p>
<p>In our <code>growable_array.h</code> we want to assume that <code>GROWABLE_ARRAY_STRUCT</code>, <code>GROWABLE_ARRAY_DATA_POINTER</code>, and whatever else we need defined are already defined by whatever code is including the header. <code>#ifndef</code> and <code>#error</code> can give some basic guardrails for that.</p>
<div class="sourceCode" id="cb35"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#ifndef GROWABLE_ARRAY_STRUCT</span></span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#error &quot;GROWABLE_ARRAY_STRUCT not defined&quot;</span></span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#endif</span></span>
<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-5"><a href="#cb35-5" aria-hidden="true" tabindex="-1"></a><span class="pp">#ifndef GROWABLE_ARRAY_DATA_POINTER</span></span>
<span id="cb35-6"><a href="#cb35-6" aria-hidden="true" tabindex="-1"></a><span class="pp">#error &quot;GROWABLE_ARRAY_DATA_POINTER not defined&quot;</span></span>
<span id="cb35-7"><a href="#cb35-7" aria-hidden="true" tabindex="-1"></a><span class="pp">#endif</span></span>
<span id="cb35-8"><a href="#cb35-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-9"><a href="#cb35-9" aria-hidden="true" tabindex="-1"></a>GROWABLE_ARRAY_STRUCT <span class="op">{</span></span>
<span id="cb35-10"><a href="#cb35-10" aria-hidden="true" tabindex="-1"></a>    GROWABLE_ARRAY_DATA_POINTER data<span class="op">;</span></span>
<span id="cb35-11"><a href="#cb35-11" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> allocated<span class="op">;</span></span>
<span id="cb35-12"><a href="#cb35-12" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> size<span class="op">;</span></span>
<span id="cb35-13"><a href="#cb35-13" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span></code></pre></div>
<p>Then we make one header file for each "specialization" we want of the growable array. So for <code>int</code>s we would make <code>growable_int_array.h</code> and put something like the following in it.</p>
<div class="sourceCode" id="cb36"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#ifndef GROWABLE_INT_ARRAY_H</span></span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#define GROWABLE_INT_ARRAY_H</span></span>
<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-4"><a href="#cb36-4" aria-hidden="true" tabindex="-1"></a><span class="pp">#define GROWABLE_ARRAY_STRUCT struct GrowableIntArray</span></span>
<span id="cb36-5"><a href="#cb36-5" aria-hidden="true" tabindex="-1"></a><span class="pp">#define GROWABLE_ARRAY_DATA_POINTER int*</span></span>
<span id="cb36-6"><a href="#cb36-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-7"><a href="#cb36-7" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&quot;growable_array.h&quot;</span></span>
<span id="cb36-8"><a href="#cb36-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-9"><a href="#cb36-9" aria-hidden="true" tabindex="-1"></a><span class="pp">#undef GROWABLE_ARRAY_STRUCT</span></span>
<span id="cb36-10"><a href="#cb36-10" aria-hidden="true" tabindex="-1"></a><span class="pp">#undef GROWABLE_ARRAY_DATA_POINTER</span></span>
<span id="cb36-11"><a href="#cb36-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-12"><a href="#cb36-12" aria-hidden="true" tabindex="-1"></a><span class="pp">#endif</span></span></code></pre></div>
<p>First, the normal header prelude. We don't want the growable int array to be defined more than once. Then we define the variables needed for our template header, include that header, and <code>#undef</code> those variables afterward.</p>
<p>The reason we bother with <code>#undef</code> is the same reason this works in the first place. The <code>C</code> preprocessor just does text replacements. When we include <code>growable_array.h</code> it literally spits the contents of that file in place. If we don't <code>#undef</code> a variable we defined it can lead to some head-scratchers compiling some other file.</p>
<p>But now all other code needs to do is include <code>growable_int_array.h</code> to get a growable array for <code>int</code>s. All we need to do to get a growable array for a specific type is do some <code>#define</code>s. Rinse and repeat for any other kind of growable array we want.</p>
<h3 id="pointer-lifetimes-1">Pointer Lifetimes</h3>
<p>Using <code>void*</code> might have forced us to always handle the lifetimes of those pointers and using <code>int</code> or whatever else without indirection lets us skip over memory management.</p>
<p>Unfortunately memory management is a fact of life in <code>C</code>. If the kind of thing we are storing needs to be cleaned up we need to track that.</p>
<div class="sourceCode" id="cb37"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stddef.h&gt;</span></span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdlib.h&gt;</span><span class="pp"> </span></span>
<span id="cb37-3"><a href="#cb37-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-4"><a href="#cb37-4" aria-hidden="true" tabindex="-1"></a><span class="pp">#ifndef GROWABLE_ARRAY_STRUCT</span></span>
<span id="cb37-5"><a href="#cb37-5" aria-hidden="true" tabindex="-1"></a><span class="pp">#error &quot;GROWABLE_ARRAY_STRUCT not defined&quot;</span></span>
<span id="cb37-6"><a href="#cb37-6" aria-hidden="true" tabindex="-1"></a><span class="pp">#endif</span></span>
<span id="cb37-7"><a href="#cb37-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-8"><a href="#cb37-8" aria-hidden="true" tabindex="-1"></a><span class="pp">#ifndef GROWABLE_ARRAY_DATA_POINTER</span></span>
<span id="cb37-9"><a href="#cb37-9" aria-hidden="true" tabindex="-1"></a><span class="pp">#error &quot;GROWABLE_ARRAY_DATA_POINTER not defined&quot;</span></span>
<span id="cb37-10"><a href="#cb37-10" aria-hidden="true" tabindex="-1"></a><span class="pp">#endif</span></span>
<span id="cb37-11"><a href="#cb37-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-12"><a href="#cb37-12" aria-hidden="true" tabindex="-1"></a><span class="pp">#ifndef GROWABLE_ARRAY_STRUCT_POINTER</span></span>
<span id="cb37-13"><a href="#cb37-13" aria-hidden="true" tabindex="-1"></a><span class="pp">#error &quot;GROWABLE_ARRAY_STRUCT_POINTER not defined&quot;</span></span>
<span id="cb37-14"><a href="#cb37-14" aria-hidden="true" tabindex="-1"></a><span class="pp">#endif</span></span>
<span id="cb37-15"><a href="#cb37-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-16"><a href="#cb37-16" aria-hidden="true" tabindex="-1"></a><span class="pp">#ifndef GROWABLE_ARRAY_CLEANUP_FUNCTION_NAME</span></span>
<span id="cb37-17"><a href="#cb37-17" aria-hidden="true" tabindex="-1"></a><span class="pp">#error &quot;GROWABLE_ARRAY_CLEANUP_FUNCTION_NAME not defined&quot;</span></span>
<span id="cb37-18"><a href="#cb37-18" aria-hidden="true" tabindex="-1"></a><span class="pp">#endif</span></span>
<span id="cb37-19"><a href="#cb37-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-20"><a href="#cb37-20" aria-hidden="true" tabindex="-1"></a>GROWABLE_ARRAY_STRUCT <span class="op">{</span></span>
<span id="cb37-21"><a href="#cb37-21" aria-hidden="true" tabindex="-1"></a>    GROWABLE_ARRAY_DATA_POINTER data<span class="op">;</span></span>
<span id="cb37-22"><a href="#cb37-22" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> allocated<span class="op">;</span></span>
<span id="cb37-23"><a href="#cb37-23" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> size<span class="op">;</span></span>
<span id="cb37-24"><a href="#cb37-24" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb37-25"><a href="#cb37-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-26"><a href="#cb37-26" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> GROWABLE_ARRAY_CLEANUP_FUNCTION_NAME<span class="op">(</span></span>
<span id="cb37-27"><a href="#cb37-27" aria-hidden="true" tabindex="-1"></a>    GROWABLE_ARRAY_STRUCT_POINTER array</span>
<span id="cb37-28"><a href="#cb37-28" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb37-29"><a href="#cb37-29" aria-hidden="true" tabindex="-1"></a>    <span class="pp">#ifdef GROWABLE_ARRAY_ITEM_CLEANUP_FUNCTION_NAME</span></span>
<span id="cb37-30"><a href="#cb37-30" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> array<span class="op">-&gt;</span>size<span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb37-31"><a href="#cb37-31" aria-hidden="true" tabindex="-1"></a>            GROWABLE_ARRAY_ITEM_CLEANUP_FUNCTION_NAME<span class="op">(</span>array<span class="op">-&gt;</span>data<span class="op">[</span>i<span class="op">]);</span></span>
<span id="cb37-32"><a href="#cb37-32" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb37-33"><a href="#cb37-33" aria-hidden="true" tabindex="-1"></a>    <span class="pp">#endif</span></span>
<span id="cb37-34"><a href="#cb37-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-35"><a href="#cb37-35" aria-hidden="true" tabindex="-1"></a>    free<span class="op">(</span>array<span class="op">-&gt;</span>data<span class="op">);</span></span>
<span id="cb37-36"><a href="#cb37-36" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The good news is that with the template approach that tracking doesn't need to happen at runtime. The bad news is that it needs to happen in the <code>C</code> preprocessor.</p>
<h3 id="implementor-experience">Implementor Experience</h3>
<p>You might notice that there wouldn't be a warning if <code>GROWABLE_ARRAY_ITEM_CLEANUP_FUNCTION_NAME</code> was not defined. There also is a dearth of good names to give these things. It's understandable to get tripped up by the difference between <code>GROWABLE_ARRAY_ITEM_CLEANUP_FUNCTION_NAME</code> and <code>GROWABLE_ARRAY_CLEANUP_FUNCTION_NAME</code>.</p>
<p>Best case scenario if you fill in one of these preprocessor defines wrongly is that your code doesn't compile. Worst case is that you get some insane and hard to debug behavior.</p>
<p>There will also end up being more than a few <code>#define</code>s you need to make. I'm not making use of <a href="https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html">concatenation</a> for clarity, but even that doesn't trim the number down <em>that</em> far. If we write out some of the other functions you will see how this can be burdensome.</p>
<div class="sourceCode" id="cb38"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#ifndef GROWABLE_ARRAY_STRUCT</span></span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#error &quot;GROWABLE_ARRAY_STRUCT not defined&quot;</span></span>
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#endif</span></span>
<span id="cb38-4"><a href="#cb38-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-5"><a href="#cb38-5" aria-hidden="true" tabindex="-1"></a><span class="pp">#ifndef GROWABLE_ARRAY_STRUCT_POINTER</span></span>
<span id="cb38-6"><a href="#cb38-6" aria-hidden="true" tabindex="-1"></a><span class="pp">#error &quot;GROWABLE_ARRAY_STRUCT_POINTER not defined&quot;</span></span>
<span id="cb38-7"><a href="#cb38-7" aria-hidden="true" tabindex="-1"></a><span class="pp">#endif</span></span>
<span id="cb38-8"><a href="#cb38-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-9"><a href="#cb38-9" aria-hidden="true" tabindex="-1"></a><span class="pp">#ifndef GROWABLE_ARRAY_DATA</span></span>
<span id="cb38-10"><a href="#cb38-10" aria-hidden="true" tabindex="-1"></a><span class="pp">#error &quot;GROWABLE_ARRAY_DATA not defined&quot;</span></span>
<span id="cb38-11"><a href="#cb38-11" aria-hidden="true" tabindex="-1"></a><span class="pp">#endif</span></span>
<span id="cb38-12"><a href="#cb38-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-13"><a href="#cb38-13" aria-hidden="true" tabindex="-1"></a><span class="pp">#ifndef GROWABLE_ARRAY_DATA_POINTER</span></span>
<span id="cb38-14"><a href="#cb38-14" aria-hidden="true" tabindex="-1"></a><span class="pp">#error &quot;GROWABLE_ARRAY_DATA_POINTER not defined&quot;</span></span>
<span id="cb38-15"><a href="#cb38-15" aria-hidden="true" tabindex="-1"></a><span class="pp">#endif</span></span>
<span id="cb38-16"><a href="#cb38-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-17"><a href="#cb38-17" aria-hidden="true" tabindex="-1"></a><span class="pp">#ifndef GROWABLE_ARRAY_EMPTY_FUNCTION_NAME</span></span>
<span id="cb38-18"><a href="#cb38-18" aria-hidden="true" tabindex="-1"></a><span class="pp">#error &quot;GROWABLE_ARRAY_EMPTY_FUNCTION_NAME not defined&quot;</span></span>
<span id="cb38-19"><a href="#cb38-19" aria-hidden="true" tabindex="-1"></a><span class="pp">#endif</span></span>
<span id="cb38-20"><a href="#cb38-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-21"><a href="#cb38-21" aria-hidden="true" tabindex="-1"></a><span class="pp">#ifndef GROWABLE_ARRAY_CLEANUP_FUNCTION_NAME</span></span>
<span id="cb38-22"><a href="#cb38-22" aria-hidden="true" tabindex="-1"></a><span class="pp">#error &quot;GROWABLE_ARRAY_CLEANUP_FUNCTION_NAME not defined&quot;</span></span>
<span id="cb38-23"><a href="#cb38-23" aria-hidden="true" tabindex="-1"></a><span class="pp">#endif</span></span>
<span id="cb38-24"><a href="#cb38-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-25"><a href="#cb38-25" aria-hidden="true" tabindex="-1"></a><span class="pp">#ifndef GROWABLE_ARRAY_ADD_FUNCTION_NAME</span></span>
<span id="cb38-26"><a href="#cb38-26" aria-hidden="true" tabindex="-1"></a><span class="pp">#error &quot;GROWABLE_ARRAY_ADD_FUNCTION_NAME not defined&quot;</span></span>
<span id="cb38-27"><a href="#cb38-27" aria-hidden="true" tabindex="-1"></a><span class="pp">#endif</span></span>
<span id="cb38-28"><a href="#cb38-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-29"><a href="#cb38-29" aria-hidden="true" tabindex="-1"></a>GROWABLE_ARRAY_STRUCT <span class="op">{</span></span>
<span id="cb38-30"><a href="#cb38-30" aria-hidden="true" tabindex="-1"></a>    GROWABLE_ARRAY_DATA_POINTER data<span class="op">;</span></span>
<span id="cb38-31"><a href="#cb38-31" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> allocated<span class="op">;</span></span>
<span id="cb38-32"><a href="#cb38-32" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> size<span class="op">;</span></span>
<span id="cb38-33"><a href="#cb38-33" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb38-34"><a href="#cb38-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-35"><a href="#cb38-35" aria-hidden="true" tabindex="-1"></a>GROWABLE_ARRAY_STRUCT GROWABLE_ARRAY_EMPTY_FUNCTION_NAME<span class="op">()</span> <span class="op">{</span></span>
<span id="cb38-36"><a href="#cb38-36" aria-hidden="true" tabindex="-1"></a>    GROWABLE_ARRAY_STRUCT empty <span class="op">=</span> <span class="op">{</span></span>
<span id="cb38-37"><a href="#cb38-37" aria-hidden="true" tabindex="-1"></a>       <span class="op">.</span>data <span class="op">=</span> NULL<span class="op">,</span></span>
<span id="cb38-38"><a href="#cb38-38" aria-hidden="true" tabindex="-1"></a>       <span class="op">.</span>allocated <span class="op">=</span> <span class="dv">0</span><span class="op">,</span></span>
<span id="cb38-39"><a href="#cb38-39" aria-hidden="true" tabindex="-1"></a>       <span class="op">.</span>size <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb38-40"><a href="#cb38-40" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb38-41"><a href="#cb38-41" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb38-42"><a href="#cb38-42" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> empty<span class="op">;</span></span>
<span id="cb38-43"><a href="#cb38-43" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb38-44"><a href="#cb38-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-45"><a href="#cb38-45" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> GROWABLE_ARRAY_CLEANUP_FUNCTION_NAME<span class="op">(</span></span>
<span id="cb38-46"><a href="#cb38-46" aria-hidden="true" tabindex="-1"></a>    GROWABLE_ARRAY_STRUCT_POINTER array</span>
<span id="cb38-47"><a href="#cb38-47" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb38-48"><a href="#cb38-48" aria-hidden="true" tabindex="-1"></a>    <span class="pp">#ifdef GROWABLE_ARRAY_ITEM_CLEANUP_FUNCTION_NAME</span></span>
<span id="cb38-49"><a href="#cb38-49" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> array<span class="op">-&gt;</span>size<span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb38-50"><a href="#cb38-50" aria-hidden="true" tabindex="-1"></a>            GROWABLE_ARRAY_ITEM_CLEANUP_FUNCTION_NAME<span class="op">(</span>array<span class="op">-&gt;</span>data<span class="op">[</span>i<span class="op">]);</span></span>
<span id="cb38-51"><a href="#cb38-51" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb38-52"><a href="#cb38-52" aria-hidden="true" tabindex="-1"></a>    <span class="pp">#endif</span></span>
<span id="cb38-53"><a href="#cb38-53" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-54"><a href="#cb38-54" aria-hidden="true" tabindex="-1"></a>    free<span class="op">(</span>array<span class="op">-&gt;</span>data<span class="op">);</span></span>
<span id="cb38-55"><a href="#cb38-55" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb38-56"><a href="#cb38-56" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-57"><a href="#cb38-57" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> GROWABLE_ARRAY_ADD_FUNCTION_NAME<span class="op">(</span></span>
<span id="cb38-58"><a href="#cb38-58" aria-hidden="true" tabindex="-1"></a>    GROWABLE_ARRAY_STRUCT_POINTER array<span class="op">,</span> </span>
<span id="cb38-59"><a href="#cb38-59" aria-hidden="true" tabindex="-1"></a>    GROWABLE_ARRAY_DATA value</span>
<span id="cb38-60"><a href="#cb38-60" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb38-61"><a href="#cb38-61" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>array<span class="op">-&gt;</span>size <span class="op">+</span> <span class="dv">1</span> <span class="op">&gt;</span> array<span class="op">-&gt;</span>allocated<span class="op">)</span> <span class="op">{</span></span>
<span id="cb38-62"><a href="#cb38-62" aria-hidden="true" tabindex="-1"></a>       <span class="dt">size_t</span> new_allocated<span class="op">;</span></span>
<span id="cb38-63"><a href="#cb38-63" aria-hidden="true" tabindex="-1"></a>       <span class="cf">if</span> <span class="op">(</span>array<span class="op">-&gt;</span>size <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb38-64"><a href="#cb38-64" aria-hidden="true" tabindex="-1"></a>           new_allocated <span class="op">=</span> <span class="dv">2</span><span class="op">;</span></span>
<span id="cb38-65"><a href="#cb38-65" aria-hidden="true" tabindex="-1"></a>       <span class="op">}</span></span>
<span id="cb38-66"><a href="#cb38-66" aria-hidden="true" tabindex="-1"></a>       <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb38-67"><a href="#cb38-67" aria-hidden="true" tabindex="-1"></a>           new_allocated <span class="op">=</span> array<span class="op">-&gt;</span>size <span class="op">*</span> <span class="dv">2</span><span class="op">;</span></span>
<span id="cb38-68"><a href="#cb38-68" aria-hidden="true" tabindex="-1"></a>       <span class="op">}</span></span>
<span id="cb38-69"><a href="#cb38-69" aria-hidden="true" tabindex="-1"></a>       </span>
<span id="cb38-70"><a href="#cb38-70" aria-hidden="true" tabindex="-1"></a>       GROWABLE_ARRAY_DATA_POINTER new_data </span>
<span id="cb38-71"><a href="#cb38-71" aria-hidden="true" tabindex="-1"></a>            <span class="op">=</span> <span class="op">(</span>GROWABLE_ARRAY_DATA_POINTER<span class="op">)</span> calloc<span class="op">(</span><span class="kw">sizeof</span><span class="op">(</span><span class="dt">void</span><span class="op">*),</span> new_allocated<span class="op">);</span></span>
<span id="cb38-72"><a href="#cb38-72" aria-hidden="true" tabindex="-1"></a>       GROWABLE_ARRAY_DATA_POINTER old_data <span class="op">=</span> array<span class="op">-&gt;</span>data<span class="op">;</span></span>
<span id="cb38-73"><a href="#cb38-73" aria-hidden="true" tabindex="-1"></a>       </span>
<span id="cb38-74"><a href="#cb38-74" aria-hidden="true" tabindex="-1"></a>       <span class="co">// Copy all the old elements to it</span></span>
<span id="cb38-75"><a href="#cb38-75" aria-hidden="true" tabindex="-1"></a>       <span class="cf">if</span> <span class="op">(</span>old_data <span class="op">!=</span> NULL<span class="op">)</span> <span class="op">{</span></span>
<span id="cb38-76"><a href="#cb38-76" aria-hidden="true" tabindex="-1"></a>           <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> array<span class="op">-&gt;</span>size<span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb38-77"><a href="#cb38-77" aria-hidden="true" tabindex="-1"></a>               new_data<span class="op">[</span>i<span class="op">]</span> <span class="op">=</span> old_data<span class="op">[</span>i<span class="op">];</span></span>
<span id="cb38-78"><a href="#cb38-78" aria-hidden="true" tabindex="-1"></a>           <span class="op">}</span></span>
<span id="cb38-79"><a href="#cb38-79" aria-hidden="true" tabindex="-1"></a>       <span class="op">}</span></span>
<span id="cb38-80"><a href="#cb38-80" aria-hidden="true" tabindex="-1"></a>       </span>
<span id="cb38-81"><a href="#cb38-81" aria-hidden="true" tabindex="-1"></a>       free<span class="op">(</span>old_data<span class="op">);</span></span>
<span id="cb38-82"><a href="#cb38-82" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-83"><a href="#cb38-83" aria-hidden="true" tabindex="-1"></a>       array<span class="op">-&gt;</span>data <span class="op">=</span> new_data<span class="op">;</span></span>
<span id="cb38-84"><a href="#cb38-84" aria-hidden="true" tabindex="-1"></a>       array<span class="op">-&gt;</span>allocated <span class="op">=</span> new_allocated<span class="op">;</span></span>
<span id="cb38-85"><a href="#cb38-85" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb38-86"><a href="#cb38-86" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb38-87"><a href="#cb38-87" aria-hidden="true" tabindex="-1"></a>    array<span class="op">-&gt;</span>data<span class="op">[</span>array<span class="op">-&gt;</span>size<span class="op">]</span> <span class="op">=</span> value<span class="op">;</span></span>
<span id="cb38-88"><a href="#cb38-88" aria-hidden="true" tabindex="-1"></a>    array<span class="op">-&gt;</span>size<span class="op">++;</span></span>
<span id="cb38-89"><a href="#cb38-89" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>All of which still needs to be handled in each specialization.</p>
<div class="sourceCode" id="cb39"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#ifndef GROWABLE_INT_ARRAY_H</span></span>
<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#define GROWABLE_INT_ARRAY_H</span></span>
<span id="cb39-3"><a href="#cb39-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb39-4"><a href="#cb39-4" aria-hidden="true" tabindex="-1"></a><span class="pp">#define GROWABLE_ARRAY_STRUCT struct GrowableIntArray</span></span>
<span id="cb39-5"><a href="#cb39-5" aria-hidden="true" tabindex="-1"></a><span class="pp">#define GROWABLE_ARRAY_STRUCT_POINTER struct GrowableIntArray*</span></span>
<span id="cb39-6"><a href="#cb39-6" aria-hidden="true" tabindex="-1"></a><span class="pp">#define GROWABLE_ARRAY_DATA int</span></span>
<span id="cb39-7"><a href="#cb39-7" aria-hidden="true" tabindex="-1"></a><span class="pp">#define GROWABLE_ARRAY_DATA_POINTER int*</span></span>
<span id="cb39-8"><a href="#cb39-8" aria-hidden="true" tabindex="-1"></a><span class="pp">#define GROWABLE_ARRAY_EMPTY_FUNCTION_NAME growable_int_array_empty</span></span>
<span id="cb39-9"><a href="#cb39-9" aria-hidden="true" tabindex="-1"></a><span class="pp">#define GROWABLE_ARRAY_ADD_FUNCTION_NAME growable_int_array_add</span></span>
<span id="cb39-10"><a href="#cb39-10" aria-hidden="true" tabindex="-1"></a><span class="pp">#define GROWABLE_ARRAY_CLEANUP_FUNCTION_NAME growable_int_array_cleanup</span></span>
<span id="cb39-11"><a href="#cb39-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb39-12"><a href="#cb39-12" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&quot;growable_array.h&quot;</span></span>
<span id="cb39-13"><a href="#cb39-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb39-14"><a href="#cb39-14" aria-hidden="true" tabindex="-1"></a><span class="pp">#undef GROWABLE_ARRAY_STRUCT</span></span>
<span id="cb39-15"><a href="#cb39-15" aria-hidden="true" tabindex="-1"></a><span class="pp">#undef GROWABLE_ARRAY_DATA_POINTER</span></span>
<span id="cb39-16"><a href="#cb39-16" aria-hidden="true" tabindex="-1"></a><span class="pp">#undef GROWABLE_ARRAY_DATA</span></span>
<span id="cb39-17"><a href="#cb39-17" aria-hidden="true" tabindex="-1"></a><span class="pp">#undef GROWABLE_ARRAY_DATA_POINTER</span></span>
<span id="cb39-18"><a href="#cb39-18" aria-hidden="true" tabindex="-1"></a><span class="pp">#undef GROWABLE_ARRAY_EMPTY_FUNCTION_NAME</span></span>
<span id="cb39-19"><a href="#cb39-19" aria-hidden="true" tabindex="-1"></a><span class="pp">#undef GROWABLE_ARRAY_ADD_FUNCTION_NAME</span></span>
<span id="cb39-20"><a href="#cb39-20" aria-hidden="true" tabindex="-1"></a><span class="pp">#undef GROWABLE_ARRAY_CLEANUP_FUNCTION_NAME</span></span>
<span id="cb39-21"><a href="#cb39-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb39-22"><a href="#cb39-22" aria-hidden="true" tabindex="-1"></a><span class="pp">#endif</span></span></code></pre></div>
<p>While this is all technically less work than making all the logic for a growable array from scratch ten times, It's certainly not pretty.</p>
<p>If you've ever had the life lesson of working with <code>C++</code> templates, this is the sort of thing that language feature is intended to replace.</p>
<div class="sourceCode" id="cb40"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> GrowableArray <span class="op">{</span></span>
<span id="cb40-3"><a href="#cb40-3" aria-hidden="true" tabindex="-1"></a>   T<span class="op">*</span> data<span class="op">;</span></span>
<span id="cb40-4"><a href="#cb40-4" aria-hidden="true" tabindex="-1"></a>   <span class="dt">size_t</span> allocated<span class="op">;</span></span>
<span id="cb40-5"><a href="#cb40-5" aria-hidden="true" tabindex="-1"></a>   <span class="dt">size_t</span> size<span class="op">;</span>  </span>
<span id="cb40-6"><a href="#cb40-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>If you haven't, don't get too excited. There lie demons also.</p>
<h2 id="conclusion">Conclusion</h2>
<p>And that is basically it.</p>
<p>To grow an array you allocate a new array and copy data into it. To be efficient you allocate more memory than you need each time you grow.</p>
<p>If you want to make that data structure for more than one specific data type you either need to rely on runtime indirection and pointers or you need to dive into the C preprocessor and make template headers.</p>
<p>If you are a student who has a question you can ask below. You can find complete examples of all these approaches in <a href="https://github.com/bowbahdoe/c-growable-array">this GitHub repo</a>.</p>
<p>Corrections welcome.</p>
<h2 id="corrections">Corrections</h2>
<h3 id="realloc"><code>realloc</code></h3>
<p>Instead of <code>calloc</code> for everything it is more efficient to use <code>realloc</code>. When <code>malloc</code> and co. give you a chunk of memory that memory might secretly be larger than you requested. If it is, you can avoid having to do much of the work of the allocator.</p>
<h3 id="efficient-runtime-generic-growable-arrays">Efficient Runtime Generic Growable Arrays</h3>
<p>One thing that was pointed out to me is that using a <code>void**</code> for the runtime is a naive strategy. We can avoid the memory indirection implied by having an array of pointers by storing the byte size of each element in the struct.</p>
<div class="sourceCode" id="cb41"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> GrowableArray <span class="op">{</span></span>
<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span><span class="op">*</span> data<span class="op">;</span></span>
<span id="cb41-3"><a href="#cb41-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> allocated<span class="op">;</span></span>
<span id="cb41-4"><a href="#cb41-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> size<span class="op">;</span></span>
<span id="cb41-5"><a href="#cb41-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="op">(*</span>cleanup<span class="op">)(</span><span class="dt">void</span><span class="op">*);</span></span>
<span id="cb41-6"><a href="#cb41-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> element_size<span class="op">;</span></span>
<span id="cb41-7"><a href="#cb41-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Then when we allocate data we get <code>void*</code> instead of a <code>void**</code> for our storage. Functions like <code>growable_array_get</code> will still have to return a <code>void*</code> as a result, but those can be cast dereferenced. What is important is that the data behind the <code>void*</code> will have the ideal memory layout.</p>
<h3 id="calloc-behavior"><code>calloc</code> behavior</h3>
<p>Small but important in some contexts point: <code>calloc</code> doesn't give you "the zero" for every type. It does fill the memory with <code>0</code> bytes, but I have been informed that for <code>float</code>s and similar all zero bytes might not be a zero value.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Just use Postgres</title><link>https://mccue.dev/pages/8-16-24-just-use-postgres</link><description></description><pubDate>Fri, 16 Aug 0024 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Just use Postgres</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Just use Postgres</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
This is one part actionable advice, one part question for the audience.

<p>Advice: When you are making a new application that requires persistent storage of data, like is the case for most web applications, your default choice should be <code>Postgres</code>.</p>
<h3 id="why-not-sqlite">Why not <code>sqlite</code>?</h3>
<p><code>sqlite</code> is a pretty good database, but its data is stored in a single file.</p>
<p>This implies that whatever your application is, it is running on one machine and one machine only. Or at least one shared filesystem.</p>
<p>If you are making a desktop or mobile app, that's perfect. If you are making a website it might not be.</p>
<p>There are many success stories of using <code>sqlite</code> for a website, but they mostly involve people who set up their own servers and infrastructure. Platforms as a service-s like Heroku, Railway, Render, etc. generally expect you to use a database accessed over network boundary. It's not <em>wrong</em> to give up some of the benefits of those platforms, but do consider if the benefits of <code>sqlite</code> are worth giving up platform provided automatic database backups and the ability to provision more than one application server.</p>
<p><a href="https://www.sqlite.org/whentouse.html">The official documentation</a> has a good guide with some more specifics.</p>
<h3 id="why-not-dynamodb-cassandra-or-mongodb">Why not <code>DynamoDB</code>, <code>Cassandra</code>, or <code>MongoDB</code>?</h3>
<p>Wherever Rick Houlihan is, I hope he is having a good day.</p>
<p>I watch a lot of conference talks, but his <a href="https://www.youtube.com/watch?v=HaEPXoXVf2k">2018 DynamoDB Deep Dive</a> might be the one I've watched the most. I know very few of you are going to watch an hour-long talk, but you really should. It's a good one.</p>
<p>The thrust of it is that databases that are in the same genre as <code>DynamoDB</code> - which includes <code>Cassandra</code> and <code>MongoDB</code> - are fantastic <strong>if</strong> - and this is a load bearing if:</p>
<ul>
<li>You know exactly what your app needs to do, up-front</li>
<li>You know exactly what your access patterns will be, up-front</li>
<li>You have a known need to scale to really large sizes of data</li>
<li>You are okay giving up some level of consistency</li>
</ul>
<p>This is because this sort of database is basically a giant distributed hash map. The only operations that work without needing to scan the entire database are lookups by partition key and scans that make use of a sort key.</p>
<p>Whatever queries you need to make, you need to encode that knowledge in one of those indexes before you store it. You want to store users and look them up by either first name or last name? Well you best have a sort key that looks like <code>&lt;FIRST NAME&gt;$&lt;LAST NAME&gt;</code>. Your access patterns should be baked into how you store your data. If your access patterns change significantly, you might need to reprocess all of your data.</p>
<p>It's annoying because, especially with <code>MongoDB</code>, people come into it having been sold on it being a more "flexible" database. Yes, you don't need to give it a schema. Yes, you can just dump untyped JSON into collections. No, this is not a flexible kind of database. It is an efficient one.</p>
<p>With a relational database you can go from getting all the pets of a person to getting all the owners of a pet by slapping an index or two on your tables. With this genre of NoSQL, that can be a tall order.</p>
<p>Its also not amazing if you need to run analytics queries. Arbitrary questions like "How many users signed up in the last month" can be trivially answered by writing a SQL query, perhaps on a read-replica if you are worried about running an expensive query on the same machine that is dealing with customer traffic. It's just outside the scope of this kind of database. You need to be ETL-ing your data out to handle it.</p>
<p>If you see a college student or fresh grad using <code>MongoDB</code> stop them. They need help. They have been led astray.</p>
<h3 id="why-not-valkey">Why not <code>Valkey</code>?</h3>
<p>The artist formerly known as <code>Redis</code> is best known for being an efficient out-of-process cache. You compute something expensive once and slap it in <code>Valkey</code> so all 5 or so HTTP servers you have don't need to recompute it.</p>
<p>However, you <em>can</em> use it as your primary database. It stores all its data in RAM, so it's pretty fast if you do that.</p>
<p>Obvious problems:</p>
<ul>
<li>You can only have so much RAM. You can have a lot more than you'd think, but its still pretty limited compared to hard drives.</li>
<li>Same as the <code>DynamoDB</code>-likes, you need to make concessions on how you model your data.</li>
</ul>
<h3 id="why-not-datomic">Why not <code>Datomic</code>?</h3>
<p>If you already knew about this one, you get a gold star.</p>
<p><code>Datomic</code> is a <code>NoSQL</code> database, but it is a relational one. The "up-front design" problems aren't there, and it does have some neat properties.</p>
<p>You don't store data in tables. It's all "entity-attribute-value-time" (EAVT) pairs. Instead of a person row with <code>id</code>, <code>name</code>, and <code>age</code> you store <code>1 :person/name "Beth"</code> and <code>1 :person/age 30</code>. Then your queries work off of "universal" indexes.</p>
<p>You don't need to coordinate with writers when making queries. You query the database "as-of" a given time. New data, even deletions (or as they call them "retractions"), don't actually delete old data.</p>
<p>But there are some significant problems</p>
<ul>
<li>It only works with JVM languages.</li>
<li>Outside of <code>Clojure</code>, a relatively niche language, its API sucks.</li>
<li>If you structure a query badly the error messages you get are terrible.</li>
<li>The whole universe of tools that exist for SQL just aren't there.</li>
</ul>
<h3 id="why-not-xtdb">Why not <code>XTDB</code>?</h3>
<p><code>Clojure</code> people make a lot of databases.</p>
<p><code>XTDB</code> is spiritually similar do <code>Datomic</code> but:</p>
<ul>
<li>There is an HTTP api, so you aren't locked to the JVM.</li>
<li>It has two axes of time you can query against. "System Time" - when records were inserted - and "Valid Time."</li>
<li>It has a SQL API.</li>
</ul>
<p>The biggest points against it are:</p>
<ul>
<li>It's new. Its SQL API is something that popped up in the last year. It recently changed its whole storage model. Will the company behind it survive the next 10 years? Who knows!</li>
</ul>
<p>Okay that's just one point. I'm sure I could think of more, but treat this as a stand-in for any recently developed database. The best predictor something will continue to exist into the future is how long it has existed. COBOL been around for decades, it will likely continue to exist for decades.</p>
<p>If you have persistent storage, you want as long a support term as you can get. You can certainly choose to pick a newer or experimental database for your app but, regardless of technical properties, that's a risky choice. It shouldn't be your default.</p>
<h3 id="why-not-kafka">Why not <code>Kafka</code>?</h3>
<p><code>Kafka</code> is an append only log. It can handle TBs of data. It is a very good append only log. It works amazingly well if you want to do event sourcing type stuff with data flowing in from multiple services maintained by multiple teams of humans.</p>
<p>But:</p>
<ul>
<li>Up to a certain scale, a table in Postgres works perfectly fine as an append only log.</li>
<li>You likely do not have hundreds of people working on your product nor TBs of events flowing in.</li>
<li>Making a Kafka consumer is a bit more error-prone than you'd expect. You need to keep track of your place in the log after all.</li>
<li>Even when maintained by a cloud provider (and there are good managed <code>Kafka</code> services) its another piece of infrastructure you need to monitor.</li>
</ul>
<h3 id="why-not-elasticsearch">Why not <code>ElasticSearch</code>?</h3>
<p>Is searching over data the primary function of your product?</p>
<p>If yes, <code>ElasticSearch</code> is going to give you some real pros. You will need to ETL your data into it and manage that whole process, but <code>ElasticSearch</code> is built for searching. It does searching good.</p>
<p>If no, <code>Postgres</code> will be fine. A sprinkling of <code>ilike</code> and the built-in <a href="https://www.postgresql.org/docs/current/textsearch.html">full text search</a> is more than enough for most applications. You can always bolt on a dedicated search thing later.</p>
<h3 id="why-not-mssql-or-oracle-db">Why not <code>MSSQL</code> or <code>Oracle DB</code>?</h3>
<p>Genuine question you should ask yourself: Are these worth the price tag?</p>
<p>I don't just mean the straight-up cost to license, but also the cost of lock-in. Once your data is in <code>Oracle DB</code> you are going to be paying Oracle forever. You are going to have to train your coders on its idiosyncrasies, forever. You are going to have to decide between enterprise features and your wallet, forever.</p>
<p>I know its super unlikely that you will contribute a patch to <code>Postgres</code>, so I won't pretend that there is some magic "power of open source" going on, but I think you should have a very specific need in mind to choose a proprietary DB. If you don't have some killer <code>MSSQL</code> feature that you simply cannot live without, don't use it.</p>
<h3 id="why-not-mysql">Why not <code>MySQL</code>?</h3>
<p>This is the one that I need some audience help with.</p>
<p><code>MySQL</code> is owned by Oracle. There are <a href="https://www.mysql.com/products/enterprise/compare/">features locked behind their enterprise editions</a>. To an extent you will have lock-in issues the same as any other DB.</p>
<p>But the free edition <code>MySQL</code> has also been used in an extremely wide range of things. It's been around for a long time. There are people who know how to work with it.</p>
<p>My problem is that I've only spent ~6 months of my professional career working with it. I genuinely don't know enough to compare it intelligently to <code>Postgres</code>.</p>
<p>I'm convinced it isn't secretly so much better that I am doing folks a disservice when telling them to use <code>Postgres</code>, and I do remember reading about how <code>Postgres</code> generally has better support for enforcing invariants in the DB itself, but I wouldn't mind being schooled a bit here.</p>
<h3 id="why-not-some-ai-vector-db">Why not some AI vector DB?</h3>
<ul>
<li>Most are new. Remember the risks of using something new.</li>
<li>AI is a bubble. A load-bearing bubble, but a bubble. Don't build a house on it if you can avoid it.</li>
<li>Even if your business is another AI grift, you probably only need to <code>import openai</code>.</li>
</ul>
<h3 id="why-not-google-sheets">Why not Google Sheets?</h3>
<p>You're right. I can't think of any downsides. Go for it.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>I Can't Run My Rust Game Either</title><link>https://mccue.dev/pages/8-1-24-i-cant-run-my-rust-game</link><description></description><pubDate>Thu, 01 Aug 0024 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>I Can't Run My Rust Game Either</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">I Can't Run My Rust Game Either</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
Yesterday I [talked about an issue I had updating a Rust project](https://mccue.dev/pages/7-31-24-rust-just-failed-its-test).
The time between when that project was working for me and when it was not was only a few months.

<p>But I have one other Rust project I haven't touched in a while. <a href="https://github.com/bowbahdoe/alien_game">This little game</a>.</p>
<p>In it, you play as a Pong paddle catching or dodging bullets from an alien. It was a fun project at the time and a good exercise with Rust.</p>
<p>It also does not compile today.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>   <span class="ex">Compiling</span> winit v0.19.5</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.19.5/src/platform/macos/view.rs:209:9</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="ex">205</span> <span class="kw">|</span> <span class="ex">extern</span> fn has_marked_text<span class="er">(</span><span class="ex">this:</span> <span class="kw">&amp;</span><span class="ex">Object,</span> _sel: Sel<span class="kw">)</span> <span class="ex">-</span><span class="op">&gt;</span> BOOL {</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                        <span class="ex">----</span> expected <span class="kw">`</span><span class="ex">bool</span><span class="kw">`</span> because of return type</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="ex">...</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="ex">209</span> <span class="kw">|</span>         <span class="kw">(</span><span class="fu">marked_text.length()</span> <span class="op">&gt;</span> 0<span class="kw">)</span> <span class="fu">as</span> i8</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>         <span class="ex">^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</span> expected <span class="kw">`</span><span class="ex">bool</span><span class="kw">`</span>, found <span class="kw">`</span><span class="ex">i8</span><span class="kw">`</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.19.5/src/platform/macos/window.rs:103:26</span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="ex">103</span> <span class="kw">|</span>             <span class="ex">is_zoomed</span> != 0</span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>             <span class="ex">---------</span>    ^ expected <span class="kw">`</span><span class="ex">bool</span><span class="kw">`</span>, found integer</span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>             <span class="kw">|</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>             <span class="ex">expected</span> because this is <span class="kw">`</span><span class="ex">bool</span><span class="kw">`</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.19.5/src/platform/macos/window.rs:175:57</span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a><span class="ex">175</span> <span class="kw">|</span>                 <span class="ex">self.window.setFrame_display_</span><span class="er">(</span><span class="ex">new_rect,</span> 0<span class="kw">);</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                             <span class="ex">-----------------</span>           ^ expected <span class="kw">`</span><span class="ex">bool</span><span class="kw">`</span>, found integer</span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                             <span class="kw">|</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                             <span class="ex">arguments</span> to this method are incorrect</span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> method defined here</span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cocoa-0.18.5/src/appkit.rs:932:15</span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a><span class="ex">932</span> <span class="kw">|</span>     <span class="ex">unsafe</span> fn setFrame_display_<span class="er">(</span><span class="ex">self,</span> windowFrame: NSRect, display: BOOL<span class="kw">);</span></span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>               <span class="ex">^^^^^^^^^^^^^^^^^</span></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a>    <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.19.5/src/platform/macos/window.rs:1301:48</span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a><span class="ex">1301</span> <span class="kw">|</span>         <span class="ex">window.setFrame_display_</span><span class="er">(</span><span class="ex">current_rect,</span> 0<span class="kw">)</span></span>
<span id="cb1-37"><a href="#cb1-37" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="ex">-----------------</span>               ^ expected <span class="kw">`</span><span class="ex">bool</span><span class="kw">`</span>, found integer</span>
<span id="cb1-38"><a href="#cb1-38" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="kw">|</span></span>
<span id="cb1-39"><a href="#cb1-39" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="ex">arguments</span> to this method are incorrect</span>
<span id="cb1-40"><a href="#cb1-40" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb1-41"><a href="#cb1-41" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> method defined here</span>
<span id="cb1-42"><a href="#cb1-42" aria-hidden="true" tabindex="-1"></a>    <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cocoa-0.18.5/src/appkit.rs:932:15</span>
<span id="cb1-43"><a href="#cb1-43" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb1-44"><a href="#cb1-44" aria-hidden="true" tabindex="-1"></a><span class="ex">932</span>  <span class="kw">|</span>     <span class="ex">unsafe</span> fn setFrame_display_<span class="er">(</span><span class="ex">self,</span> windowFrame: NSRect, display: BOOL<span class="kw">);</span></span>
<span id="cb1-45"><a href="#cb1-45" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>               <span class="ex">^^^^^^^^^^^^^^^^^</span></span>
<span id="cb1-46"><a href="#cb1-46" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-47"><a href="#cb1-47" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb1-48"><a href="#cb1-48" aria-hidden="true" tabindex="-1"></a>    <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.19.5/src/platform/macos/window.rs:1308:48</span>
<span id="cb1-49"><a href="#cb1-49" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb1-50"><a href="#cb1-50" aria-hidden="true" tabindex="-1"></a><span class="ex">1308</span> <span class="kw">|</span>         <span class="ex">window.setFrame_display_</span><span class="er">(</span><span class="ex">current_rect,</span> 0<span class="kw">)</span></span>
<span id="cb1-51"><a href="#cb1-51" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="ex">-----------------</span>               ^ expected <span class="kw">`</span><span class="ex">bool</span><span class="kw">`</span>, found integer</span>
<span id="cb1-52"><a href="#cb1-52" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="kw">|</span></span>
<span id="cb1-53"><a href="#cb1-53" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="ex">arguments</span> to this method are incorrect</span>
<span id="cb1-54"><a href="#cb1-54" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb1-55"><a href="#cb1-55" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> method defined here</span>
<span id="cb1-56"><a href="#cb1-56" aria-hidden="true" tabindex="-1"></a>    <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cocoa-0.18.5/src/appkit.rs:932:15</span>
<span id="cb1-57"><a href="#cb1-57" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb1-58"><a href="#cb1-58" aria-hidden="true" tabindex="-1"></a><span class="ex">932</span>  <span class="kw">|</span>     <span class="ex">unsafe</span> fn setFrame_display_<span class="er">(</span><span class="ex">self,</span> windowFrame: NSRect, display: BOOL<span class="kw">);</span></span>
<span id="cb1-59"><a href="#cb1-59" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>               <span class="ex">^^^^^^^^^^^^^^^^^</span></span>
<span id="cb1-60"><a href="#cb1-60" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-61"><a href="#cb1-61" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb1-62"><a href="#cb1-62" aria-hidden="true" tabindex="-1"></a>    <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.19.5/src/platform/macos/window.rs:1325:48</span>
<span id="cb1-63"><a href="#cb1-63" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb1-64"><a href="#cb1-64" aria-hidden="true" tabindex="-1"></a><span class="ex">1325</span> <span class="kw">|</span>         <span class="ex">window.setFrame_display_</span><span class="er">(</span><span class="ex">current_rect,</span> 0<span class="kw">)</span></span>
<span id="cb1-65"><a href="#cb1-65" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="ex">-----------------</span>               ^ expected <span class="kw">`</span><span class="ex">bool</span><span class="kw">`</span>, found integer</span>
<span id="cb1-66"><a href="#cb1-66" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="kw">|</span></span>
<span id="cb1-67"><a href="#cb1-67" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="ex">arguments</span> to this method are incorrect</span>
<span id="cb1-68"><a href="#cb1-68" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb1-69"><a href="#cb1-69" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> method defined here</span>
<span id="cb1-70"><a href="#cb1-70" aria-hidden="true" tabindex="-1"></a>    <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cocoa-0.18.5/src/appkit.rs:932:15</span>
<span id="cb1-71"><a href="#cb1-71" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb1-72"><a href="#cb1-72" aria-hidden="true" tabindex="-1"></a><span class="ex">932</span>  <span class="kw">|</span>     <span class="ex">unsafe</span> fn setFrame_display_<span class="er">(</span><span class="ex">self,</span> windowFrame: NSRect, display: BOOL<span class="kw">);</span></span>
<span id="cb1-73"><a href="#cb1-73" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>               <span class="ex">^^^^^^^^^^^^^^^^^</span></span>
<span id="cb1-74"><a href="#cb1-74" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-75"><a href="#cb1-75" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb1-76"><a href="#cb1-76" aria-hidden="true" tabindex="-1"></a>    <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.19.5/src/platform/macos/window.rs:1332:48</span>
<span id="cb1-77"><a href="#cb1-77" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb1-78"><a href="#cb1-78" aria-hidden="true" tabindex="-1"></a><span class="ex">1332</span> <span class="kw">|</span>         <span class="ex">window.setFrame_display_</span><span class="er">(</span><span class="ex">current_rect,</span> 0<span class="kw">)</span></span>
<span id="cb1-79"><a href="#cb1-79" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="ex">-----------------</span>               ^ expected <span class="kw">`</span><span class="ex">bool</span><span class="kw">`</span>, found integer</span>
<span id="cb1-80"><a href="#cb1-80" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="kw">|</span></span>
<span id="cb1-81"><a href="#cb1-81" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="ex">arguments</span> to this method are incorrect</span>
<span id="cb1-82"><a href="#cb1-82" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb1-83"><a href="#cb1-83" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> method defined here</span>
<span id="cb1-84"><a href="#cb1-84" aria-hidden="true" tabindex="-1"></a>    <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cocoa-0.18.5/src/appkit.rs:932:15</span>
<span id="cb1-85"><a href="#cb1-85" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb1-86"><a href="#cb1-86" aria-hidden="true" tabindex="-1"></a><span class="ex">932</span>  <span class="kw">|</span>     <span class="ex">unsafe</span> fn setFrame_display_<span class="er">(</span><span class="ex">self,</span> windowFrame: NSRect, display: BOOL<span class="kw">);</span></span>
<span id="cb1-87"><a href="#cb1-87" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>               <span class="ex">^^^^^^^^^^^^^^^^^</span></span>
<span id="cb1-88"><a href="#cb1-88" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-89"><a href="#cb1-89" aria-hidden="true" tabindex="-1"></a><span class="ex">For</span> more information about this error, try <span class="kw">`</span><span class="ex">rustc</span> <span class="at">--explain</span> E0308<span class="kw">`</span>.</span>
<span id="cb1-90"><a href="#cb1-90" aria-hidden="true" tabindex="-1"></a><span class="ex">error:</span> could not compile <span class="kw">`</span><span class="ex">winit</span><span class="kw">`</span> <span class="er">(</span><span class="ex">lib</span><span class="kw">)</span> <span class="ex">due</span> to 7 previous errors</span></code></pre></div>
<p>A lot of people suggested locking to an older version of the Rust toolchain. So I tried to set my laptop to have whatever the Rust compiler was the last time I made a commit on that project.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ex">➜</span>  alien_game git:<span class="er">(</span><span class="ex">master</span><span class="kw">)</span> <span class="ex">✗</span> rustup toolchain install stable-2020-03-25</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="ex">info:</span> syncing channel updates for <span class="st">&#39;stable-2020-03-25-aarch64-apple-darwin&#39;</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="ex">error:</span> no release found for <span class="st">&#39;stable-2020-03-25&#39;</span></span></code></pre></div>
<p>Oh, yeah. ARM Macs weren't a thing in 2020.</p>
<p>I no longer have the laptop I used to write this code.</p>
<p>I can't find a list of available toolchains online and trying every date is tiresome - maybe I'll script it if all else fails - but there are only two dependencies.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode toml"><code class="sourceCode toml"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">[</span><span class="dt">dependencies</span><span class="kw">]</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="dt">ggez</span> <span class="op">=</span> <span class="st">&quot;0.5&quot;</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="dt">rand</span> <span class="op">=</span> <span class="st">&quot;0.7.3&quot;</span></span></code></pre></div>
<p>What if I just lock newer versions of <code>winit</code> and <code>cocoa</code>?</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode toml"><code class="sourceCode toml"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">[</span><span class="dt">dependencies</span><span class="kw">]</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="dt">ggez</span> <span class="op">=</span> <span class="st">&quot;0.5&quot;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="dt">rand</span> <span class="op">=</span> <span class="st">&quot;0.7.3&quot;</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="dt">winit</span> <span class="op">=</span> <span class="st">&quot;0.30.4&quot;</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="dt">cocoa</span> <span class="op">=</span> <span class="st">&quot;0.25.0&quot;</span></span></code></pre></div>
<div class="sourceCode" id="cb5"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>   <span class="ex">Compiling</span> winit v0.19.5</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.19.5/src/platform/macos/view.rs:209:9</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="ex">205</span> <span class="kw">|</span> <span class="ex">extern</span> fn has_marked_text<span class="er">(</span><span class="ex">this:</span> <span class="kw">&amp;</span><span class="ex">Object,</span> _sel: Sel<span class="kw">)</span> <span class="ex">-</span><span class="op">&gt;</span> BOOL {</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                        <span class="ex">----</span> expected <span class="kw">`</span><span class="ex">bool</span><span class="kw">`</span> because of return type</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="ex">...</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a><span class="ex">209</span> <span class="kw">|</span>         <span class="kw">(</span><span class="fu">marked_text.length()</span> <span class="op">&gt;</span> 0<span class="kw">)</span> <span class="fu">as</span> i8</span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>         <span class="ex">^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</span> expected <span class="kw">`</span><span class="ex">bool</span><span class="kw">`</span>, found <span class="kw">`</span><span class="ex">i8</span><span class="kw">`</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.19.5/src/platform/macos/window.rs:103:26</span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a><span class="ex">103</span> <span class="kw">|</span>             <span class="ex">is_zoomed</span> != 0</span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>             <span class="ex">---------</span>    ^ expected <span class="kw">`</span><span class="ex">bool</span><span class="kw">`</span>, found integer</span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>             <span class="kw">|</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>             <span class="ex">expected</span> because this is <span class="kw">`</span><span class="ex">bool</span><span class="kw">`</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.19.5/src/platform/macos/window.rs:175:57</span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true" tabindex="-1"></a><span class="ex">175</span> <span class="kw">|</span>                 <span class="ex">self.window.setFrame_display_</span><span class="er">(</span><span class="ex">new_rect,</span> 0<span class="kw">);</span></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                             <span class="ex">-----------------</span>           ^ expected <span class="kw">`</span><span class="ex">bool</span><span class="kw">`</span>, found integer</span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                             <span class="kw">|</span></span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                             <span class="ex">arguments</span> to this method are incorrect</span>
<span id="cb5-26"><a href="#cb5-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb5-27"><a href="#cb5-27" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> method defined here</span>
<span id="cb5-28"><a href="#cb5-28" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cocoa-0.18.5/src/appkit.rs:932:15</span>
<span id="cb5-29"><a href="#cb5-29" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb5-30"><a href="#cb5-30" aria-hidden="true" tabindex="-1"></a><span class="ex">932</span> <span class="kw">|</span>     <span class="ex">unsafe</span> fn setFrame_display_<span class="er">(</span><span class="ex">self,</span> windowFrame: NSRect, display: BOOL<span class="kw">);</span></span>
<span id="cb5-31"><a href="#cb5-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>               <span class="ex">^^^^^^^^^^^^^^^^^</span></span>
<span id="cb5-32"><a href="#cb5-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-33"><a href="#cb5-33" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb5-34"><a href="#cb5-34" aria-hidden="true" tabindex="-1"></a>    <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.19.5/src/platform/macos/window.rs:1301:48</span>
<span id="cb5-35"><a href="#cb5-35" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb5-36"><a href="#cb5-36" aria-hidden="true" tabindex="-1"></a><span class="ex">1301</span> <span class="kw">|</span>         <span class="ex">window.setFrame_display_</span><span class="er">(</span><span class="ex">current_rect,</span> 0<span class="kw">)</span></span>
<span id="cb5-37"><a href="#cb5-37" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="ex">-----------------</span>               ^ expected <span class="kw">`</span><span class="ex">bool</span><span class="kw">`</span>, found integer</span>
<span id="cb5-38"><a href="#cb5-38" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="kw">|</span></span>
<span id="cb5-39"><a href="#cb5-39" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="ex">arguments</span> to this method are incorrect</span>
<span id="cb5-40"><a href="#cb5-40" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb5-41"><a href="#cb5-41" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> method defined here</span>
<span id="cb5-42"><a href="#cb5-42" aria-hidden="true" tabindex="-1"></a>    <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cocoa-0.18.5/src/appkit.rs:932:15</span>
<span id="cb5-43"><a href="#cb5-43" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb5-44"><a href="#cb5-44" aria-hidden="true" tabindex="-1"></a><span class="ex">932</span>  <span class="kw">|</span>     <span class="ex">unsafe</span> fn setFrame_display_<span class="er">(</span><span class="ex">self,</span> windowFrame: NSRect, display: BOOL<span class="kw">);</span></span>
<span id="cb5-45"><a href="#cb5-45" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>               <span class="ex">^^^^^^^^^^^^^^^^^</span></span>
<span id="cb5-46"><a href="#cb5-46" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-47"><a href="#cb5-47" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb5-48"><a href="#cb5-48" aria-hidden="true" tabindex="-1"></a>    <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.19.5/src/platform/macos/window.rs:1308:48</span>
<span id="cb5-49"><a href="#cb5-49" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb5-50"><a href="#cb5-50" aria-hidden="true" tabindex="-1"></a><span class="ex">1308</span> <span class="kw">|</span>         <span class="ex">window.setFrame_display_</span><span class="er">(</span><span class="ex">current_rect,</span> 0<span class="kw">)</span></span>
<span id="cb5-51"><a href="#cb5-51" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="ex">-----------------</span>               ^ expected <span class="kw">`</span><span class="ex">bool</span><span class="kw">`</span>, found integer</span>
<span id="cb5-52"><a href="#cb5-52" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="kw">|</span></span>
<span id="cb5-53"><a href="#cb5-53" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="ex">arguments</span> to this method are incorrect</span>
<span id="cb5-54"><a href="#cb5-54" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb5-55"><a href="#cb5-55" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> method defined here</span>
<span id="cb5-56"><a href="#cb5-56" aria-hidden="true" tabindex="-1"></a>    <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cocoa-0.18.5/src/appkit.rs:932:15</span>
<span id="cb5-57"><a href="#cb5-57" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb5-58"><a href="#cb5-58" aria-hidden="true" tabindex="-1"></a><span class="ex">932</span>  <span class="kw">|</span>     <span class="ex">unsafe</span> fn setFrame_display_<span class="er">(</span><span class="ex">self,</span> windowFrame: NSRect, display: BOOL<span class="kw">);</span></span>
<span id="cb5-59"><a href="#cb5-59" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>               <span class="ex">^^^^^^^^^^^^^^^^^</span></span>
<span id="cb5-60"><a href="#cb5-60" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-61"><a href="#cb5-61" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb5-62"><a href="#cb5-62" aria-hidden="true" tabindex="-1"></a>    <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.19.5/src/platform/macos/window.rs:1325:48</span>
<span id="cb5-63"><a href="#cb5-63" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb5-64"><a href="#cb5-64" aria-hidden="true" tabindex="-1"></a><span class="ex">1325</span> <span class="kw">|</span>         <span class="ex">window.setFrame_display_</span><span class="er">(</span><span class="ex">current_rect,</span> 0<span class="kw">)</span></span>
<span id="cb5-65"><a href="#cb5-65" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="ex">-----------------</span>               ^ expected <span class="kw">`</span><span class="ex">bool</span><span class="kw">`</span>, found integer</span>
<span id="cb5-66"><a href="#cb5-66" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="kw">|</span></span>
<span id="cb5-67"><a href="#cb5-67" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="ex">arguments</span> to this method are incorrect</span>
<span id="cb5-68"><a href="#cb5-68" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb5-69"><a href="#cb5-69" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> method defined here</span>
<span id="cb5-70"><a href="#cb5-70" aria-hidden="true" tabindex="-1"></a>    <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cocoa-0.18.5/src/appkit.rs:932:15</span>
<span id="cb5-71"><a href="#cb5-71" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb5-72"><a href="#cb5-72" aria-hidden="true" tabindex="-1"></a><span class="ex">932</span>  <span class="kw">|</span>     <span class="ex">unsafe</span> fn setFrame_display_<span class="er">(</span><span class="ex">self,</span> windowFrame: NSRect, display: BOOL<span class="kw">);</span></span>
<span id="cb5-73"><a href="#cb5-73" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>               <span class="ex">^^^^^^^^^^^^^^^^^</span></span>
<span id="cb5-74"><a href="#cb5-74" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-75"><a href="#cb5-75" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb5-76"><a href="#cb5-76" aria-hidden="true" tabindex="-1"></a>    <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.19.5/src/platform/macos/window.rs:1332:48</span>
<span id="cb5-77"><a href="#cb5-77" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb5-78"><a href="#cb5-78" aria-hidden="true" tabindex="-1"></a><span class="ex">1332</span> <span class="kw">|</span>         <span class="ex">window.setFrame_display_</span><span class="er">(</span><span class="ex">current_rect,</span> 0<span class="kw">)</span></span>
<span id="cb5-79"><a href="#cb5-79" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="ex">-----------------</span>               ^ expected <span class="kw">`</span><span class="ex">bool</span><span class="kw">`</span>, found integer</span>
<span id="cb5-80"><a href="#cb5-80" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="kw">|</span></span>
<span id="cb5-81"><a href="#cb5-81" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>                <span class="ex">arguments</span> to this method are incorrect</span>
<span id="cb5-82"><a href="#cb5-82" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb5-83"><a href="#cb5-83" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> method defined here</span>
<span id="cb5-84"><a href="#cb5-84" aria-hidden="true" tabindex="-1"></a>    <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cocoa-0.18.5/src/appkit.rs:932:15</span>
<span id="cb5-85"><a href="#cb5-85" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span></span>
<span id="cb5-86"><a href="#cb5-86" aria-hidden="true" tabindex="-1"></a><span class="ex">932</span>  <span class="kw">|</span>     <span class="ex">unsafe</span> fn setFrame_display_<span class="er">(</span><span class="ex">self,</span> windowFrame: NSRect, display: BOOL<span class="kw">);</span></span>
<span id="cb5-87"><a href="#cb5-87" aria-hidden="true" tabindex="-1"></a>     <span class="kw">|</span>               <span class="ex">^^^^^^^^^^^^^^^^^</span></span>
<span id="cb5-88"><a href="#cb5-88" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-89"><a href="#cb5-89" aria-hidden="true" tabindex="-1"></a><span class="ex">For</span> more information about this error, try <span class="kw">`</span><span class="ex">rustc</span> <span class="at">--explain</span> E0308<span class="kw">`</span>.</span>
<span id="cb5-90"><a href="#cb5-90" aria-hidden="true" tabindex="-1"></a><span class="ex">error:</span> could not compile <span class="kw">`</span><span class="ex">winit</span><span class="kw">`</span> <span class="er">(</span><span class="ex">lib</span><span class="kw">)</span> <span class="ex">due</span> to 7 previous errors</span></code></pre></div>
<p>I guess hell or high water it is bringing in that version of <code>winit</code>.</p>
<p>Well, what if I upgraded <code>ggez</code> to the latest?</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode toml"><code class="sourceCode toml"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">[</span><span class="dt">dependencies</span><span class="kw">]</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="dt">ggez</span> <span class="op">=</span> <span class="st">&quot;0.9.3&quot;</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="dt">rand</span> <span class="op">=</span> <span class="st">&quot;0.7.3&quot;</span></span></code></pre></div>
<div class="sourceCode" id="cb7"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>   <span class="ex">Compiling</span> rustisbetter v0.1.0 <span class="er">(</span><span class="ex">/Users/emccue/Development/alien_game</span><span class="kw">)</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0432<span class="op">]</span><span class="ex">:</span> unresolved import <span class="kw">`</span><span class="ex">ggez::event::quit</span><span class="kw">`</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a> <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:2:25</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">|</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="ex">2</span> <span class="kw">|</span> <span class="ex">use</span> ggez::event::{self, quit, EventHandler, KeyCode, KeyMods}<span class="kw">;</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">|</span>                         <span class="ex">^^^^</span> no <span class="kw">`</span><span class="ex">quit</span><span class="kw">`</span> in <span class="kw">`</span><span class="ex">event</span><span class="kw">`</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0432<span class="op">]</span><span class="ex">:</span> unresolved import <span class="kw">`</span><span class="ex">ggez::graphics::Font</span><span class="kw">`</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a> <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:4:5</span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">|</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a><span class="ex">4</span> <span class="kw">|</span> <span class="ex">use</span> ggez::graphics::Font<span class="kw">;</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">|</span>     <span class="ex">^^^^^^^^^^^^^^^^^^^^</span> no <span class="kw">`</span><span class="ex">Font</span><span class="kw">`</span> in <span class="kw">`</span><span class="ex">graphics</span><span class="kw">`</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0432<span class="op">]</span><span class="ex">:</span> unresolved import <span class="kw">`</span><span class="ex">ggez::nalgebra</span><span class="kw">`</span></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a> <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:6:11</span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">|</span></span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true" tabindex="-1"></a><span class="ex">6</span> <span class="kw">|</span> <span class="ex">use</span> ggez::nalgebra::Point2<span class="kw">;</span></span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">|</span>           <span class="ex">^^^^^^^^</span> could not find <span class="kw">`</span><span class="ex">nalgebra</span><span class="kw">`</span> in <span class="kw">`</span><span class="ex">ggez</span><span class="kw">`</span></span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0432<span class="op">]</span><span class="ex">:</span> unresolved import <span class="kw">`</span><span class="ex">ggez::nalgebra</span><span class="kw">`</span></span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true" tabindex="-1"></a> <span class="ex">--</span><span class="op">&gt;</span> src/alien.rs:3:11</span>
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true" tabindex="-1"></a>  <span class="kw">|</span></span>
<span id="cb7-23"><a href="#cb7-23" aria-hidden="true" tabindex="-1"></a><span class="ex">3</span> <span class="kw">|</span> <span class="ex">use</span> ggez::nalgebra::Point2<span class="kw">;</span></span>
<span id="cb7-24"><a href="#cb7-24" aria-hidden="true" tabindex="-1"></a>  <span class="kw">|</span>           <span class="ex">^^^^^^^^</span> could not find <span class="kw">`</span><span class="ex">nalgebra</span><span class="kw">`</span> in <span class="kw">`</span><span class="ex">ggez</span><span class="kw">`</span></span>
<span id="cb7-25"><a href="#cb7-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-26"><a href="#cb7-26" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0432<span class="op">]</span><span class="ex">:</span> unresolved import <span class="kw">`</span><span class="ex">ggez::nalgebra</span><span class="kw">`</span></span>
<span id="cb7-27"><a href="#cb7-27" aria-hidden="true" tabindex="-1"></a> <span class="ex">--</span><span class="op">&gt;</span> src/bullet.rs:3:11</span>
<span id="cb7-28"><a href="#cb7-28" aria-hidden="true" tabindex="-1"></a>  <span class="kw">|</span></span>
<span id="cb7-29"><a href="#cb7-29" aria-hidden="true" tabindex="-1"></a><span class="ex">3</span> <span class="kw">|</span> <span class="ex">use</span> ggez::nalgebra::Point2<span class="kw">;</span></span>
<span id="cb7-30"><a href="#cb7-30" aria-hidden="true" tabindex="-1"></a>  <span class="kw">|</span>           <span class="ex">^^^^^^^^</span> could not find <span class="kw">`</span><span class="ex">nalgebra</span><span class="kw">`</span> in <span class="kw">`</span><span class="ex">ggez</span><span class="kw">`</span></span>
<span id="cb7-31"><a href="#cb7-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-32"><a href="#cb7-32" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0425<span class="op">]</span><span class="ex">:</span> cannot find function <span class="kw">`</span><span class="ex">screen_coordinates</span><span class="kw">`</span> in module <span class="kw">`</span><span class="ex">graphics</span><span class="kw">`</span></span>
<span id="cb7-33"><a href="#cb7-33" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:177:44</span>
<span id="cb7-34"><a href="#cb7-34" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-35"><a href="#cb7-35" aria-hidden="true" tabindex="-1"></a><span class="ex">177</span> <span class="kw">|</span>         <span class="bu">let</span> <span class="va">screen_coordinates</span> <span class="op">=</span> <span class="va">graphics</span><span class="op">::</span><span class="va">screen_coordinates</span><span class="er">(</span><span class="kw">&amp;</span><span class="ex">ctx</span><span class="kw">);</span></span>
<span id="cb7-36"><a href="#cb7-36" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                            <span class="ex">^^^^^^^^^^^^^^^^^^</span> not found in <span class="kw">`</span><span class="ex">graphics</span><span class="kw">`</span></span>
<span id="cb7-37"><a href="#cb7-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-38"><a href="#cb7-38" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0425<span class="op">]</span><span class="ex">:</span> cannot find function <span class="kw">`</span><span class="fu">clear</span><span class="kw">`</span> in module <span class="kw">`</span><span class="ex">graphics</span><span class="kw">`</span></span>
<span id="cb7-39"><a href="#cb7-39" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:318:19</span>
<span id="cb7-40"><a href="#cb7-40" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-41"><a href="#cb7-41" aria-hidden="true" tabindex="-1"></a><span class="ex">318</span> <span class="kw">|</span>         <span class="ex">graphics::clear</span><span class="er">(</span><span class="ex">ctx,</span> graphics::WHITE<span class="kw">);</span></span>
<span id="cb7-42"><a href="#cb7-42" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                   <span class="ex">^^^^^</span> not found in <span class="kw">`</span><span class="ex">graphics</span><span class="kw">`</span></span>
<span id="cb7-43"><a href="#cb7-43" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-44"><a href="#cb7-44" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0425<span class="op">]</span><span class="ex">:</span> cannot find value <span class="kw">`</span><span class="ex">WHITE</span><span class="kw">`</span> in module <span class="kw">`</span><span class="ex">graphics</span><span class="kw">`</span></span>
<span id="cb7-45"><a href="#cb7-45" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:318:40</span>
<span id="cb7-46"><a href="#cb7-46" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-47"><a href="#cb7-47" aria-hidden="true" tabindex="-1"></a><span class="ex">318</span> <span class="kw">|</span>         <span class="ex">graphics::clear</span><span class="er">(</span><span class="ex">ctx,</span> graphics::WHITE<span class="kw">);</span></span>
<span id="cb7-48"><a href="#cb7-48" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                        <span class="ex">^^^^^</span> not found in <span class="kw">`</span><span class="ex">graphics</span><span class="kw">`</span></span>
<span id="cb7-49"><a href="#cb7-49" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-50"><a href="#cb7-50" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0425<span class="op">]</span><span class="ex">:</span> cannot find function <span class="kw">`</span><span class="ex">present</span><span class="kw">`</span> in module <span class="kw">`</span><span class="ex">graphics</span><span class="kw">`</span></span>
<span id="cb7-51"><a href="#cb7-51" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:324:19</span>
<span id="cb7-52"><a href="#cb7-52" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-53"><a href="#cb7-53" aria-hidden="true" tabindex="-1"></a><span class="ex">324</span> <span class="kw">|</span>         <span class="ex">graphics::present</span><span class="er">(</span><span class="ex">ctx</span><span class="kw">)</span><span class="ex">?</span><span class="kw">;</span></span>
<span id="cb7-54"><a href="#cb7-54" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                   <span class="ex">^^^^^^^</span> not found in <span class="kw">`</span><span class="ex">graphics</span><span class="kw">`</span></span>
<span id="cb7-55"><a href="#cb7-55" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-56"><a href="#cb7-56" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0603<span class="op">]</span><span class="ex">:</span> enum <span class="kw">`</span><span class="ex">KeyCode</span><span class="kw">`</span> is private</span>
<span id="cb7-57"><a href="#cb7-57" aria-hidden="true" tabindex="-1"></a>  <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:2:45</span>
<span id="cb7-58"><a href="#cb7-58" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-59"><a href="#cb7-59" aria-hidden="true" tabindex="-1"></a><span class="ex">2</span>  <span class="kw">|</span> <span class="ex">use</span> ggez::event::{self, quit, EventHandler, KeyCode, KeyMods}<span class="kw">;</span></span>
<span id="cb7-60"><a href="#cb7-60" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span>                                             <span class="ex">^^^^^^^</span> private enum</span>
<span id="cb7-61"><a href="#cb7-61" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-62"><a href="#cb7-62" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> the enum <span class="kw">`</span><span class="ex">KeyCode</span><span class="kw">`</span> is defined here</span>
<span id="cb7-63"><a href="#cb7-63" aria-hidden="true" tabindex="-1"></a>  <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/event.rs:34:30</span>
<span id="cb7-64"><a href="#cb7-64" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-65"><a href="#cb7-65" aria-hidden="true" tabindex="-1"></a><span class="ex">34</span> <span class="kw">|</span> <span class="ex">use</span> crate::input::keyboard::{KeyCode, KeyInput, KeyMods}<span class="kw">;</span></span>
<span id="cb7-66"><a href="#cb7-66" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span>                              <span class="ex">^^^^^^^</span></span>
<span id="cb7-67"><a href="#cb7-67" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> import <span class="kw">`</span><span class="ex">KeyCode</span><span class="kw">`</span> directly</span>
<span id="cb7-68"><a href="#cb7-68" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-69"><a href="#cb7-69" aria-hidden="true" tabindex="-1"></a><span class="ex">2</span>  <span class="kw">|</span> <span class="ex">use</span> ggez::event::{self, quit, EventHandler, winit::event::VirtualKeyCode, KeyMods}<span class="kw">;</span></span>
<span id="cb7-70"><a href="#cb7-70" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span>                                             <span class="ex">~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></span>
<span id="cb7-71"><a href="#cb7-71" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-72"><a href="#cb7-72" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0603<span class="op">]</span><span class="ex">:</span> struct <span class="kw">`</span><span class="ex">KeyMods</span><span class="kw">`</span> is private</span>
<span id="cb7-73"><a href="#cb7-73" aria-hidden="true" tabindex="-1"></a>  <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:2:54</span>
<span id="cb7-74"><a href="#cb7-74" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-75"><a href="#cb7-75" aria-hidden="true" tabindex="-1"></a><span class="ex">2</span>  <span class="kw">|</span> <span class="ex">use</span> ggez::event::{self, quit, EventHandler, KeyCode, KeyMods}<span class="kw">;</span></span>
<span id="cb7-76"><a href="#cb7-76" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span>                                                      <span class="ex">^^^^^^^</span> private struct</span>
<span id="cb7-77"><a href="#cb7-77" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-78"><a href="#cb7-78" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> the struct <span class="kw">`</span><span class="ex">KeyMods</span><span class="kw">`</span> is defined here</span>
<span id="cb7-79"><a href="#cb7-79" aria-hidden="true" tabindex="-1"></a>  <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/event.rs:34:49</span>
<span id="cb7-80"><a href="#cb7-80" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-81"><a href="#cb7-81" aria-hidden="true" tabindex="-1"></a><span class="ex">34</span> <span class="kw">|</span> <span class="ex">use</span> crate::input::keyboard::{KeyCode, KeyInput, KeyMods}<span class="kw">;</span></span>
<span id="cb7-82"><a href="#cb7-82" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span>                                                 <span class="ex">^^^^^^^</span></span>
<span id="cb7-83"><a href="#cb7-83" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> import <span class="kw">`</span><span class="ex">KeyMods</span><span class="kw">`</span> directly</span>
<span id="cb7-84"><a href="#cb7-84" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-85"><a href="#cb7-85" aria-hidden="true" tabindex="-1"></a><span class="ex">2</span>  <span class="kw">|</span> <span class="ex">use</span> ggez::event::{self, quit, EventHandler, KeyCode, ggez::input::keyboard::KeyMods}<span class="kw">;</span></span>
<span id="cb7-86"><a href="#cb7-86" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span>                                                      <span class="ex">~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></span>
<span id="cb7-87"><a href="#cb7-87" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-88"><a href="#cb7-88" aria-hidden="true" tabindex="-1"></a><span class="ex">warning:</span> unused imports: <span class="kw">`</span><span class="ex">BlendMode</span><span class="kw">`</span>, <span class="kw">`</span><span class="ex">Rect</span><span class="kw">`</span></span>
<span id="cb7-89"><a href="#cb7-89" aria-hidden="true" tabindex="-1"></a> <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:5:22</span>
<span id="cb7-90"><a href="#cb7-90" aria-hidden="true" tabindex="-1"></a>  <span class="kw">|</span></span>
<span id="cb7-91"><a href="#cb7-91" aria-hidden="true" tabindex="-1"></a><span class="ex">5</span> <span class="kw">|</span> <span class="ex">use</span> ggez::graphics::{BlendMode, DrawParam, Drawable, Rect, Text}<span class="kw">;</span></span>
<span id="cb7-92"><a href="#cb7-92" aria-hidden="true" tabindex="-1"></a>  <span class="kw">|</span>                      <span class="ex">^^^^^^^^^</span>                       ^^^^</span>
<span id="cb7-93"><a href="#cb7-93" aria-hidden="true" tabindex="-1"></a>  <span class="kw">|</span></span>
<span id="cb7-94"><a href="#cb7-94" aria-hidden="true" tabindex="-1"></a>  <span class="ex">=</span> note: <span class="kw">`</span><span class="co">#[warn(unused_imports)]</span><span class="kw">`</span> on by default</span>
<span id="cb7-95"><a href="#cb7-95" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-96"><a href="#cb7-96" aria-hidden="true" tabindex="-1"></a><span class="ex">warning:</span> unused import: <span class="kw">`</span><span class="ex">GameError</span><span class="kw">`</span></span>
<span id="cb7-97"><a href="#cb7-97" aria-hidden="true" tabindex="-1"></a> <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:7:19</span>
<span id="cb7-98"><a href="#cb7-98" aria-hidden="true" tabindex="-1"></a>  <span class="kw">|</span></span>
<span id="cb7-99"><a href="#cb7-99" aria-hidden="true" tabindex="-1"></a><span class="ex">7</span> <span class="kw">|</span> <span class="ex">use</span> ggez::{audio, GameError}<span class="kw">;</span></span>
<span id="cb7-100"><a href="#cb7-100" aria-hidden="true" tabindex="-1"></a>  <span class="kw">|</span>                   <span class="ex">^^^^^^^^^</span></span>
<span id="cb7-101"><a href="#cb7-101" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-102"><a href="#cb7-102" aria-hidden="true" tabindex="-1"></a><span class="ex">warning:</span> unused import: <span class="kw">`</span><span class="ex">rand::seq::SliceRandom</span><span class="kw">`</span></span>
<span id="cb7-103"><a href="#cb7-103" aria-hidden="true" tabindex="-1"></a> <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:9:5</span>
<span id="cb7-104"><a href="#cb7-104" aria-hidden="true" tabindex="-1"></a>  <span class="kw">|</span></span>
<span id="cb7-105"><a href="#cb7-105" aria-hidden="true" tabindex="-1"></a><span class="ex">9</span> <span class="kw">|</span> <span class="ex">use</span> rand::seq::SliceRandom<span class="kw">;</span></span>
<span id="cb7-106"><a href="#cb7-106" aria-hidden="true" tabindex="-1"></a>  <span class="kw">|</span>     <span class="ex">^^^^^^^^^^^^^^^^^^^^^^</span></span>
<span id="cb7-107"><a href="#cb7-107" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-108"><a href="#cb7-108" aria-hidden="true" tabindex="-1"></a><span class="ex">warning:</span> unused import: <span class="kw">`</span><span class="ex">std::error::Error</span><span class="kw">`</span></span>
<span id="cb7-109"><a href="#cb7-109" aria-hidden="true" tabindex="-1"></a>  <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:12:5</span>
<span id="cb7-110"><a href="#cb7-110" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-111"><a href="#cb7-111" aria-hidden="true" tabindex="-1"></a><span class="ex">12</span> <span class="kw">|</span> <span class="ex">use</span> std::error::Error<span class="kw">;</span></span>
<span id="cb7-112"><a href="#cb7-112" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span>     <span class="ex">^^^^^^^^^^^^^^^^^</span></span>
<span id="cb7-113"><a href="#cb7-113" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-114"><a href="#cb7-114" aria-hidden="true" tabindex="-1"></a><span class="ex">warning:</span> unused import: <span class="kw">`</span><span class="ex">std::iter::Peekable</span><span class="kw">`</span></span>
<span id="cb7-115"><a href="#cb7-115" aria-hidden="true" tabindex="-1"></a>  <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:16:5</span>
<span id="cb7-116"><a href="#cb7-116" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-117"><a href="#cb7-117" aria-hidden="true" tabindex="-1"></a><span class="ex">16</span> <span class="kw">|</span> <span class="ex">use</span> std::iter::Peekable<span class="kw">;</span></span>
<span id="cb7-118"><a href="#cb7-118" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span>     <span class="ex">^^^^^^^^^^^^^^^^^^^</span></span>
<span id="cb7-119"><a href="#cb7-119" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-120"><a href="#cb7-120" aria-hidden="true" tabindex="-1"></a><span class="ex">warning:</span> unused import: <span class="kw">`</span><span class="ex">std::iter::Peekable</span><span class="kw">`</span></span>
<span id="cb7-121"><a href="#cb7-121" aria-hidden="true" tabindex="-1"></a> <span class="ex">--</span><span class="op">&gt;</span> src/alien.rs:9:5</span>
<span id="cb7-122"><a href="#cb7-122" aria-hidden="true" tabindex="-1"></a>  <span class="kw">|</span></span>
<span id="cb7-123"><a href="#cb7-123" aria-hidden="true" tabindex="-1"></a><span class="ex">9</span> <span class="kw">|</span> <span class="ex">use</span> std::iter::Peekable<span class="kw">;</span></span>
<span id="cb7-124"><a href="#cb7-124" aria-hidden="true" tabindex="-1"></a>  <span class="kw">|</span>     <span class="ex">^^^^^^^^^^^^^^^^^^^</span></span>
<span id="cb7-125"><a href="#cb7-125" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-126"><a href="#cb7-126" aria-hidden="true" tabindex="-1"></a><span class="ex">warning:</span> unused import: <span class="kw">`</span><span class="ex">std::ops::Add</span><span class="kw">`</span></span>
<span id="cb7-127"><a href="#cb7-127" aria-hidden="true" tabindex="-1"></a>  <span class="ex">--</span><span class="op">&gt;</span> src/alien.rs:10:5</span>
<span id="cb7-128"><a href="#cb7-128" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-129"><a href="#cb7-129" aria-hidden="true" tabindex="-1"></a><span class="ex">10</span> <span class="kw">|</span> <span class="ex">use</span> std::ops::Add<span class="kw">;</span></span>
<span id="cb7-130"><a href="#cb7-130" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span>     <span class="ex">^^^^^^^^^^^^^</span></span>
<span id="cb7-131"><a href="#cb7-131" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-132"><a href="#cb7-132" aria-hidden="true" tabindex="-1"></a><span class="ex">warning:</span> unnecessary parentheses around pattern</span>
<span id="cb7-133"><a href="#cb7-133" aria-hidden="true" tabindex="-1"></a>  <span class="ex">--</span><span class="op">&gt;</span> src/alien.rs:80:13</span>
<span id="cb7-134"><a href="#cb7-134" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-135"><a href="#cb7-135" aria-hidden="true" tabindex="-1"></a><span class="ex">80</span> <span class="kw">|</span>         <span class="bu">let</span> <span class="er">(</span><span class="kw">(</span><span class="ex">min_x,</span> max_x<span class="kw">))</span> <span class="ex">=</span> self.x_movement_range<span class="kw">;</span></span>
<span id="cb7-136"><a href="#cb7-136" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span>             <span class="ex">^</span>              ^</span>
<span id="cb7-137"><a href="#cb7-137" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-138"><a href="#cb7-138" aria-hidden="true" tabindex="-1"></a>   <span class="ex">=</span> note: <span class="kw">`</span><span class="co">#[warn(unused_parens)]</span><span class="kw">`</span> on by default</span>
<span id="cb7-139"><a href="#cb7-139" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> remove these parentheses</span>
<span id="cb7-140"><a href="#cb7-140" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-141"><a href="#cb7-141" aria-hidden="true" tabindex="-1"></a><span class="ex">80</span> <span class="at">-</span>         let <span class="er">(</span><span class="kw">(</span><span class="ex">min_x,</span> max_x<span class="kw">))</span> <span class="ex">=</span> self.x_movement_range<span class="kw">;</span></span>
<span id="cb7-142"><a href="#cb7-142" aria-hidden="true" tabindex="-1"></a><span class="ex">80</span> +         let <span class="er">(</span><span class="ex">min_x,</span> max_x<span class="kw">)</span> <span class="ex">=</span> self.x_movement_range<span class="kw">;</span></span>
<span id="cb7-143"><a href="#cb7-143" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-144"><a href="#cb7-144" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-145"><a href="#cb7-145" aria-hidden="true" tabindex="-1"></a><span class="ex">warning:</span> use of deprecated function <span class="kw">`</span><span class="ex">ggez::filesystem::open</span><span class="kw">`</span>: Use <span class="kw">`</span><span class="ex">ctx.fs.open</span><span class="kw">`</span> instead</span>
<span id="cb7-146"><a href="#cb7-146" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:142:65</span>
<span id="cb7-147"><a href="#cb7-147" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-148"><a href="#cb7-148" aria-hidden="true" tabindex="-1"></a><span class="ex">142</span> <span class="kw">|</span>         <span class="bu">let</span> <span class="va">data</span> <span class="op">=</span> <span class="va">audio</span><span class="op">::</span><span class="va">SoundData</span><span class="op">::</span><span class="va">from_read</span><span class="er">(</span><span class="kw">&amp;</span><span class="ex">mut</span> filesystem::open<span class="er">(</span><span class="ex">ctx,</span> <span class="st">&quot;/Bloop.mp3&quot;</span><span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">?</span><span class="kw">;</span></span>
<span id="cb7-149"><a href="#cb7-149" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                                 <span class="ex">^^^^</span></span>
<span id="cb7-150"><a href="#cb7-150" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-151"><a href="#cb7-151" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> note: <span class="kw">`</span><span class="co">#[warn(deprecated)]</span><span class="kw">`</span> on by default</span>
<span id="cb7-152"><a href="#cb7-152" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-153"><a href="#cb7-153" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0050<span class="op">]</span><span class="ex">:</span> method <span class="kw">`</span><span class="ex">key_down_event</span><span class="kw">`</span> has 5 parameters but the declaration in trait <span class="kw">`</span><span class="ex">key_down_event</span><span class="kw">`</span> has 4</span>
<span id="cb7-154"><a href="#cb7-154" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:329:9</span>
<span id="cb7-155"><a href="#cb7-155" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-156"><a href="#cb7-156" aria-hidden="true" tabindex="-1"></a><span class="ex">329</span> <span class="kw">|</span> <span class="ex">/</span>         <span class="kw">&amp;</span><span class="ex">mut</span> self,</span>
<span id="cb7-157"><a href="#cb7-157" aria-hidden="true" tabindex="-1"></a><span class="ex">330</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">ctx:</span> <span class="kw">&amp;</span><span class="ex">mut</span> Context,</span>
<span id="cb7-158"><a href="#cb7-158" aria-hidden="true" tabindex="-1"></a><span class="ex">331</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">keycode:</span> KeyCode,</span>
<span id="cb7-159"><a href="#cb7-159" aria-hidden="true" tabindex="-1"></a><span class="ex">332</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">_keymods:</span> KeyMods,</span>
<span id="cb7-160"><a href="#cb7-160" aria-hidden="true" tabindex="-1"></a><span class="ex">333</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">_repeat:</span> bool,</span>
<span id="cb7-161"><a href="#cb7-161" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span> <span class="kw">|</span><span class="ex">_____________________^</span> expected 4 parameters, found 5</span>
<span id="cb7-162"><a href="#cb7-162" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-163"><a href="#cb7-163" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> note: <span class="kw">`</span><span class="ex">key_down_event</span><span class="kw">`</span> from trait: <span class="kw">`</span><span class="ex">fn</span><span class="er">(</span><span class="kw">&amp;</span><span class="ex">mut</span> Self, <span class="kw">&amp;</span><span class="ex">mut</span> ggez::Context, KeyInput, bool<span class="kw">)</span> <span class="ex">-</span><span class="op">&gt;</span> Result<span class="op">&lt;()</span>, E<span class="op">&gt;</span><span class="kw">`</span></span>
<span id="cb7-164"><a href="#cb7-164" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-165"><a href="#cb7-165" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0050<span class="op">]</span><span class="ex">:</span> method <span class="kw">`</span><span class="ex">key_up_event</span><span class="kw">`</span> has 4 parameters but the declaration in trait <span class="kw">`</span><span class="ex">key_up_event</span><span class="kw">`</span> has 3</span>
<span id="cb7-166"><a href="#cb7-166" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:348:21</span>
<span id="cb7-167"><a href="#cb7-167" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-168"><a href="#cb7-168" aria-hidden="true" tabindex="-1"></a><span class="ex">348</span> <span class="kw">|</span>     <span class="ex">fn</span> key_up_event<span class="er">(</span><span class="kw">&amp;</span><span class="ex">mut</span> self, _ctx: <span class="kw">&amp;</span><span class="ex">mut</span> Context, keycode: KeyCode, _keymods: KeyMods<span class="kw">)</span> <span class="kw">{</span></span>
<span id="cb7-169"><a href="#cb7-169" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                     <span class="ex">^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</span> expected 3 parameters, found 4</span>
<span id="cb7-170"><a href="#cb7-170" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-171"><a href="#cb7-171" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> note: <span class="kw">`</span><span class="ex">key_up_event</span><span class="kw">`</span> from trait: <span class="kw">`</span><span class="ex">fn</span><span class="er">(</span><span class="kw">&amp;</span><span class="ex">mut</span> Self, <span class="kw">&amp;</span><span class="ex">mut</span> ggez::Context, KeyInput<span class="kw">)</span> <span class="ex">-</span><span class="op">&gt;</span> Result<span class="op">&lt;()</span>, E<span class="op">&gt;</span><span class="kw">`</span></span>
<span id="cb7-172"><a href="#cb7-172" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-173"><a href="#cb7-173" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0053<span class="op">]</span><span class="ex">:</span> method <span class="kw">`</span><span class="ex">resize_event</span><span class="kw">`</span> has an incompatible type for trait</span>
<span id="cb7-174"><a href="#cb7-174" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:358:76</span>
<span id="cb7-175"><a href="#cb7-175" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-176"><a href="#cb7-176" aria-hidden="true" tabindex="-1"></a><span class="ex">358</span> <span class="kw">|</span>     <span class="ex">fn</span> resize_event<span class="er">(</span><span class="kw">&amp;</span><span class="ex">mut</span> self, _ctx: <span class="kw">&amp;</span><span class="ex">mut</span> Context, width: f32, height: f32<span class="kw">)</span> <span class="kw">{</span></span>
<span id="cb7-177"><a href="#cb7-177" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                                            <span class="ex">^</span> expected <span class="kw">`</span><span class="ex">Result</span><span class="op">&lt;()</span>, GameError<span class="op">&gt;</span><span class="kw">`</span>, found <span class="kw">`()`</span></span>
<span id="cb7-178"><a href="#cb7-178" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-179"><a href="#cb7-179" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> note: expected signature <span class="kw">`</span><span class="ex">fn</span><span class="er">(</span><span class="kw">&amp;</span><span class="ex">mut</span> Game, <span class="kw">&amp;</span><span class="ex">mut</span> ggez::Context, _, _<span class="kw">)</span> <span class="ex">-</span><span class="op">&gt;</span> Result<span class="op">&lt;()</span>, GameError<span class="op">&gt;</span><span class="kw">`</span></span>
<span id="cb7-180"><a href="#cb7-180" aria-hidden="true" tabindex="-1"></a>               <span class="ex">found</span> signature <span class="kw">`</span><span class="ex">fn</span><span class="er">(</span><span class="kw">&amp;</span><span class="ex">mut</span> Game, <span class="kw">&amp;</span><span class="ex">mut</span> ggez::Context, _, _<span class="kw">)`</span></span>
<span id="cb7-181"><a href="#cb7-181" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> change the output type to match the trait</span>
<span id="cb7-182"><a href="#cb7-182" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-183"><a href="#cb7-183" aria-hidden="true" tabindex="-1"></a><span class="ex">358</span> <span class="kw">|</span>     <span class="ex">fn</span> resize_event<span class="er">(</span><span class="kw">&amp;</span><span class="ex">mut</span> self, _ctx: <span class="kw">&amp;</span><span class="ex">mut</span> Context, width: f32, height: f32<span class="kw">)</span> <span class="ex">-</span><span class="op">&gt;</span> Result<span class="op">&lt;()</span>, GameError<span class="op">&gt;</span> {</span>
<span id="cb7-184"><a href="#cb7-184" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                                             <span class="ex">++++++++++++++++++++++++</span></span>
<span id="cb7-185"><a href="#cb7-185" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-186"><a href="#cb7-186" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb7-187"><a href="#cb7-187" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/alien.rs:141:13</span>
<span id="cb7-188"><a href="#cb7-188" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-189"><a href="#cb7-189" aria-hidden="true" tabindex="-1"></a><span class="ex">140</span> <span class="kw">|</span>         <span class="ex">sprite.draw</span><span class="er">(</span></span>
<span id="cb7-190"><a href="#cb7-190" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                <span class="ex">----</span> arguments to this method are incorrect</span>
<span id="cb7-191"><a href="#cb7-191" aria-hidden="true" tabindex="-1"></a><span class="ex">141</span> <span class="kw">|</span>             <span class="ex">ctx,</span></span>
<span id="cb7-192"><a href="#cb7-192" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>             <span class="ex">^^^</span> expected <span class="kw">`&amp;</span><span class="ex">mut</span> Canvas<span class="kw">`</span>, found <span class="kw">`&amp;</span><span class="ex">mut</span> Context<span class="kw">`</span></span>
<span id="cb7-193"><a href="#cb7-193" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-194"><a href="#cb7-194" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> note: expected mutable reference <span class="kw">`&amp;</span><span class="ex">mut</span> Canvas<span class="kw">`</span></span>
<span id="cb7-195"><a href="#cb7-195" aria-hidden="true" tabindex="-1"></a>               <span class="ex">found</span> mutable reference <span class="kw">`&amp;</span><span class="ex">mut</span> ggez::Context<span class="kw">`</span></span>
<span id="cb7-196"><a href="#cb7-196" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> method defined here</span>
<span id="cb7-197"><a href="#cb7-197" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/draw.rs:293:8</span>
<span id="cb7-198"><a href="#cb7-198" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-199"><a href="#cb7-199" aria-hidden="true" tabindex="-1"></a><span class="ex">293</span> <span class="kw">|</span>     <span class="ex">fn</span> draw<span class="er">(</span><span class="kw">&amp;</span><span class="ex">self,</span> canvas: <span class="kw">&amp;</span><span class="ex">mut</span> Canvas, param: impl Into<span class="op">&lt;</span>DrawParam<span class="op">&gt;</span><span class="kw">);</span></span>
<span id="cb7-200"><a href="#cb7-200" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>        <span class="ex">^^^^</span></span>
<span id="cb7-201"><a href="#cb7-201" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-202"><a href="#cb7-202" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb7-203"><a href="#cb7-203" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/alien.rs:140:9</span>
<span id="cb7-204"><a href="#cb7-204" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-205"><a href="#cb7-205" aria-hidden="true" tabindex="-1"></a><span class="ex">134</span> <span class="kw">|</span>       <span class="ex">pub</span> fn draw<span class="er">(</span><span class="kw">&amp;</span><span class="ex">self,</span> ctx: <span class="kw">&amp;</span><span class="ex">mut</span> Context<span class="kw">)</span> <span class="ex">-</span><span class="op">&gt;</span> GameResult<span class="op">&lt;()&gt;</span> {</span>
<span id="cb7-206"><a href="#cb7-206" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                <span class="ex">--------------</span> expected <span class="kw">`</span><span class="ex">Result</span><span class="op">&lt;()</span>, GameError<span class="op">&gt;</span><span class="kw">`</span> because of return type</span>
<span id="cb7-207"><a href="#cb7-207" aria-hidden="true" tabindex="-1"></a><span class="ex">...</span></span>
<span id="cb7-208"><a href="#cb7-208" aria-hidden="true" tabindex="-1"></a><span class="ex">140</span> <span class="kw">|</span> <span class="ex">/</span>         sprite.draw<span class="er">(</span></span>
<span id="cb7-209"><a href="#cb7-209" aria-hidden="true" tabindex="-1"></a><span class="ex">141</span> <span class="kw">|</span> <span class="kw">|</span>             <span class="ex">ctx,</span></span>
<span id="cb7-210"><a href="#cb7-210" aria-hidden="true" tabindex="-1"></a><span class="ex">142</span> <span class="kw">|</span> <span class="kw">|</span>             <span class="fu">DrawParam::default()</span></span>
<span id="cb7-211"><a href="#cb7-211" aria-hidden="true" tabindex="-1"></a><span class="ex">143</span> <span class="kw">|</span> <span class="kw">|</span>                 <span class="ex">.offset</span><span class="er">(</span><span class="ex">Point2::new</span><span class="er">(</span><span class="ex">0.5,</span> 0.5<span class="kw">))</span></span>
<span id="cb7-212"><a href="#cb7-212" aria-hidden="true" tabindex="-1"></a><span class="ex">144</span> <span class="kw">|</span> <span class="kw">|</span>                 <span class="ex">.dest</span><span class="er">(</span><span class="ex">Point2::new</span><span class="er">(</span><span class="ex">self.pos.0,</span> self.pos.1<span class="kw">))</span><span class="ex">,</span></span>
<span id="cb7-213"><a href="#cb7-213" aria-hidden="true" tabindex="-1"></a><span class="ex">145</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="kw">)</span></span>
<span id="cb7-214"><a href="#cb7-214" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span> <span class="kw">|</span><span class="ex">_________^</span> expected <span class="kw">`</span><span class="ex">Result</span><span class="op">&lt;()</span>, GameError<span class="op">&gt;</span><span class="kw">`</span>, found <span class="kw">`()`</span></span>
<span id="cb7-215"><a href="#cb7-215" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-216"><a href="#cb7-216" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> note:   expected enum <span class="kw">`</span><span class="ex">Result</span><span class="op">&lt;()</span>, GameError<span class="op">&gt;</span><span class="kw">`</span></span>
<span id="cb7-217"><a href="#cb7-217" aria-hidden="true" tabindex="-1"></a>            <span class="ex">found</span> unit type <span class="kw">`()`</span></span>
<span id="cb7-218"><a href="#cb7-218" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> try adding an expression at the end of the block</span>
<span id="cb7-219"><a href="#cb7-219" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-220"><a href="#cb7-220" aria-hidden="true" tabindex="-1"></a><span class="ex">145</span> ~         <span class="kw">);</span></span>
<span id="cb7-221"><a href="#cb7-221" aria-hidden="true" tabindex="-1"></a><span class="ex">146</span> +         Ok<span class="er">(</span><span class="kw">())</span></span>
<span id="cb7-222"><a href="#cb7-222" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-223"><a href="#cb7-223" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-224"><a href="#cb7-224" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb7-225"><a href="#cb7-225" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/bullet.rs:54:13</span>
<span id="cb7-226"><a href="#cb7-226" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-227"><a href="#cb7-227" aria-hidden="true" tabindex="-1"></a><span class="ex">53</span>  <span class="kw">|</span>         <span class="ex">self.sprite.draw</span><span class="er">(</span></span>
<span id="cb7-228"><a href="#cb7-228" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                     <span class="ex">----</span> arguments to this method are incorrect</span>
<span id="cb7-229"><a href="#cb7-229" aria-hidden="true" tabindex="-1"></a><span class="ex">54</span>  <span class="kw">|</span>             <span class="ex">ctx,</span></span>
<span id="cb7-230"><a href="#cb7-230" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>             <span class="ex">^^^</span> expected <span class="kw">`&amp;</span><span class="ex">mut</span> Canvas<span class="kw">`</span>, found <span class="kw">`&amp;</span><span class="ex">mut</span> Context<span class="kw">`</span></span>
<span id="cb7-231"><a href="#cb7-231" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-232"><a href="#cb7-232" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> note: expected mutable reference <span class="kw">`&amp;</span><span class="ex">mut</span> Canvas<span class="kw">`</span></span>
<span id="cb7-233"><a href="#cb7-233" aria-hidden="true" tabindex="-1"></a>               <span class="ex">found</span> mutable reference <span class="kw">`&amp;</span><span class="ex">mut</span> ggez::Context<span class="kw">`</span></span>
<span id="cb7-234"><a href="#cb7-234" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> method defined here</span>
<span id="cb7-235"><a href="#cb7-235" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/draw.rs:293:8</span>
<span id="cb7-236"><a href="#cb7-236" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-237"><a href="#cb7-237" aria-hidden="true" tabindex="-1"></a><span class="ex">293</span> <span class="kw">|</span>     <span class="ex">fn</span> draw<span class="er">(</span><span class="kw">&amp;</span><span class="ex">self,</span> canvas: <span class="kw">&amp;</span><span class="ex">mut</span> Canvas, param: impl Into<span class="op">&lt;</span>DrawParam<span class="op">&gt;</span><span class="kw">);</span></span>
<span id="cb7-238"><a href="#cb7-238" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>        <span class="ex">^^^^</span></span>
<span id="cb7-239"><a href="#cb7-239" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-240"><a href="#cb7-240" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb7-241"><a href="#cb7-241" aria-hidden="true" tabindex="-1"></a>  <span class="ex">--</span><span class="op">&gt;</span> src/bullet.rs:53:9</span>
<span id="cb7-242"><a href="#cb7-242" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-243"><a href="#cb7-243" aria-hidden="true" tabindex="-1"></a><span class="ex">52</span> <span class="kw">|</span>       <span class="ex">pub</span> fn draw<span class="er">(</span><span class="kw">&amp;</span><span class="ex">self,</span> ctx: <span class="kw">&amp;</span><span class="ex">mut</span> Context<span class="kw">)</span> <span class="ex">-</span><span class="op">&gt;</span> GameResult<span class="op">&lt;()&gt;</span> {</span>
<span id="cb7-244"><a href="#cb7-244" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span>                                                <span class="ex">--------------</span> expected <span class="kw">`</span><span class="ex">Result</span><span class="op">&lt;()</span>, GameError<span class="op">&gt;</span><span class="kw">`</span> because of return type</span>
<span id="cb7-245"><a href="#cb7-245" aria-hidden="true" tabindex="-1"></a><span class="ex">53</span> <span class="kw">|</span> <span class="ex">/</span>         self.sprite.draw<span class="er">(</span></span>
<span id="cb7-246"><a href="#cb7-246" aria-hidden="true" tabindex="-1"></a><span class="ex">54</span> <span class="kw">|</span> <span class="kw">|</span>             <span class="ex">ctx,</span></span>
<span id="cb7-247"><a href="#cb7-247" aria-hidden="true" tabindex="-1"></a><span class="ex">55</span> <span class="kw">|</span> <span class="kw">|</span>             <span class="fu">DrawParam::default()</span></span>
<span id="cb7-248"><a href="#cb7-248" aria-hidden="true" tabindex="-1"></a><span class="ex">56</span> <span class="kw">|</span> <span class="kw">|</span>                 <span class="ex">.offset</span><span class="er">(</span><span class="ex">Point2::new</span><span class="er">(</span><span class="ex">0.5,</span> 0.5<span class="kw">))</span></span>
<span id="cb7-249"><a href="#cb7-249" aria-hidden="true" tabindex="-1"></a><span class="ex">57</span> <span class="kw">|</span> <span class="kw">|</span>                 <span class="ex">.dest</span><span class="er">(</span><span class="ex">Point2::new</span><span class="er">(</span><span class="ex">self.pos.0,</span> self.pos.1<span class="kw">))</span></span>
<span id="cb7-250"><a href="#cb7-250" aria-hidden="true" tabindex="-1"></a><span class="ex">58</span> <span class="kw">|</span> <span class="kw">|</span>                 <span class="ex">.rotation</span><span class="er">(</span><span class="ex">FRAC_PI_2</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-251"><a href="#cb7-251" aria-hidden="true" tabindex="-1"></a><span class="ex">59</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="kw">)</span></span>
<span id="cb7-252"><a href="#cb7-252" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span> <span class="kw">|</span><span class="ex">_________^</span> expected <span class="kw">`</span><span class="ex">Result</span><span class="op">&lt;()</span>, GameError<span class="op">&gt;</span><span class="kw">`</span>, found <span class="kw">`()`</span></span>
<span id="cb7-253"><a href="#cb7-253" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-254"><a href="#cb7-254" aria-hidden="true" tabindex="-1"></a>   <span class="ex">=</span> note:   expected enum <span class="kw">`</span><span class="ex">Result</span><span class="op">&lt;()</span>, GameError<span class="op">&gt;</span><span class="kw">`</span></span>
<span id="cb7-255"><a href="#cb7-255" aria-hidden="true" tabindex="-1"></a>           <span class="ex">found</span> unit type <span class="kw">`()`</span></span>
<span id="cb7-256"><a href="#cb7-256" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> try adding an expression at the end of the block</span>
<span id="cb7-257"><a href="#cb7-257" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-258"><a href="#cb7-258" aria-hidden="true" tabindex="-1"></a><span class="ex">59</span> ~         <span class="kw">);</span></span>
<span id="cb7-259"><a href="#cb7-259" aria-hidden="true" tabindex="-1"></a><span class="ex">60</span> +         Ok<span class="er">(</span><span class="kw">())</span></span>
<span id="cb7-260"><a href="#cb7-260" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-261"><a href="#cb7-261" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-262"><a href="#cb7-262" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0061<span class="op">]</span><span class="ex">:</span> this method takes 1 argument but 0 arguments were supplied</span>
<span id="cb7-263"><a href="#cb7-263" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/bullet.rs:100:34</span>
<span id="cb7-264"><a href="#cb7-264" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-265"><a href="#cb7-265" aria-hidden="true" tabindex="-1"></a><span class="ex">100</span> <span class="kw">|</span>         <span class="ex">self.pos.0</span> <span class="at">-</span> self.sprite.dimensions<span class="er">(</span><span class="kw">)</span><span class="ex">.w</span> as f32 / 2.0</span>
<span id="cb7-266"><a href="#cb7-266" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                  <span class="ex">^^^^^^^^^^--</span> an argument of type <span class="kw">`&amp;</span><span class="ex">_</span><span class="kw">`</span> is missing</span>
<span id="cb7-267"><a href="#cb7-267" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-268"><a href="#cb7-268" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> method defined here</span>
<span id="cb7-269"><a href="#cb7-269" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/draw.rs:299:8</span>
<span id="cb7-270"><a href="#cb7-270" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-271"><a href="#cb7-271" aria-hidden="true" tabindex="-1"></a><span class="ex">299</span> <span class="kw">|</span>     <span class="ex">fn</span> dimensions<span class="er">(</span><span class="kw">&amp;</span><span class="ex">self,</span> gfx: <span class="kw">&amp;</span><span class="ex">impl</span> Has<span class="op">&lt;</span>GraphicsContext<span class="op">&gt;</span><span class="kw">)</span> <span class="ex">-</span><span class="op">&gt;</span> Option<span class="op">&lt;</span>Rect<span class="op">&gt;</span><span class="kw">;</span></span>
<span id="cb7-272"><a href="#cb7-272" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>        <span class="ex">^^^^^^^^^^</span></span>
<span id="cb7-273"><a href="#cb7-273" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> provide the argument</span>
<span id="cb7-274"><a href="#cb7-274" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-275"><a href="#cb7-275" aria-hidden="true" tabindex="-1"></a><span class="ex">100</span> <span class="kw">|</span>         <span class="ex">self.pos.0</span> <span class="at">-</span> self.sprite.dimensions<span class="er">(</span><span class="ex">/*</span> gfx <span class="pp">*</span>/<span class="kw">)</span><span class="ex">.w</span> as f32 / 2.0</span>
<span id="cb7-276"><a href="#cb7-276" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                            <span class="ex">~~~~~~~~~~~</span></span>
<span id="cb7-277"><a href="#cb7-277" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-278"><a href="#cb7-278" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0609<span class="op">]</span><span class="ex">:</span> no field <span class="kw">`</span><span class="fu">w</span><span class="kw">`</span> on type <span class="kw">`</span><span class="ex">Option</span><span class="op">&lt;</span>Rect<span class="op">&gt;</span><span class="kw">`</span></span>
<span id="cb7-279"><a href="#cb7-279" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/bullet.rs:100:47</span>
<span id="cb7-280"><a href="#cb7-280" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-281"><a href="#cb7-281" aria-hidden="true" tabindex="-1"></a><span class="ex">100</span> <span class="kw">|</span>         <span class="ex">self.pos.0</span> <span class="at">-</span> self.sprite.dimensions<span class="er">(</span><span class="kw">)</span><span class="ex">.w</span> as f32 / 2.0</span>
<span id="cb7-282"><a href="#cb7-282" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                               <span class="ex">^</span> unknown field</span>
<span id="cb7-283"><a href="#cb7-283" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-284"><a href="#cb7-284" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> one of the expressions<span class="st">&#39; fields has a field of the same name</span></span>
<span id="cb7-285"><a href="#cb7-285" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-286"><a href="#cb7-286" aria-hidden="true" tabindex="-1"></a><span class="st">100 |         self.pos.0 - self.sprite.dimensions().unwrap().w as f32 / 2.0</span></span>
<span id="cb7-287"><a href="#cb7-287" aria-hidden="true" tabindex="-1"></a><span class="st">    |                                               +++++++++</span></span>
<span id="cb7-288"><a href="#cb7-288" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-289"><a href="#cb7-289" aria-hidden="true" tabindex="-1"></a><span class="st">error[E0061]: this method takes 1 argument but 0 arguments were supplied</span></span>
<span id="cb7-290"><a href="#cb7-290" aria-hidden="true" tabindex="-1"></a><span class="st">   --&gt; src/bullet.rs:104:34</span></span>
<span id="cb7-291"><a href="#cb7-291" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-292"><a href="#cb7-292" aria-hidden="true" tabindex="-1"></a><span class="st">104 |         self.pos.1 - self.sprite.dimensions().h as f32 / 2.0</span></span>
<span id="cb7-293"><a href="#cb7-293" aria-hidden="true" tabindex="-1"></a><span class="st">    |                                  ^^^^^^^^^^-- an argument of type `&amp;_` is missing</span></span>
<span id="cb7-294"><a href="#cb7-294" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-295"><a href="#cb7-295" aria-hidden="true" tabindex="-1"></a><span class="st">note: method defined here</span></span>
<span id="cb7-296"><a href="#cb7-296" aria-hidden="true" tabindex="-1"></a><span class="st">   --&gt; /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/draw.rs:299:8</span></span>
<span id="cb7-297"><a href="#cb7-297" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-298"><a href="#cb7-298" aria-hidden="true" tabindex="-1"></a><span class="st">299 |     fn dimensions(&amp;self, gfx: &amp;impl Has&lt;GraphicsContext&gt;) -&gt; Option&lt;Rect&gt;;</span></span>
<span id="cb7-299"><a href="#cb7-299" aria-hidden="true" tabindex="-1"></a><span class="st">    |        ^^^^^^^^^^</span></span>
<span id="cb7-300"><a href="#cb7-300" aria-hidden="true" tabindex="-1"></a><span class="st">help: provide the argument</span></span>
<span id="cb7-301"><a href="#cb7-301" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-302"><a href="#cb7-302" aria-hidden="true" tabindex="-1"></a><span class="st">104 |         self.pos.1 - self.sprite.dimensions(/* gfx */).h as f32 / 2.0</span></span>
<span id="cb7-303"><a href="#cb7-303" aria-hidden="true" tabindex="-1"></a><span class="st">    |                                            ~~~~~~~~~~~</span></span>
<span id="cb7-304"><a href="#cb7-304" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-305"><a href="#cb7-305" aria-hidden="true" tabindex="-1"></a><span class="st">error[E0609]: no field `h` on type `Option&lt;Rect&gt;`</span></span>
<span id="cb7-306"><a href="#cb7-306" aria-hidden="true" tabindex="-1"></a><span class="st">   --&gt; src/bullet.rs:104:47</span></span>
<span id="cb7-307"><a href="#cb7-307" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-308"><a href="#cb7-308" aria-hidden="true" tabindex="-1"></a><span class="st">104 |         self.pos.1 - self.sprite.dimensions().h as f32 / 2.0</span></span>
<span id="cb7-309"><a href="#cb7-309" aria-hidden="true" tabindex="-1"></a><span class="st">    |                                               ^ unknown field</span></span>
<span id="cb7-310"><a href="#cb7-310" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-311"><a href="#cb7-311" aria-hidden="true" tabindex="-1"></a><span class="st">help: one of the expressions&#39;</span> fields has a field of the same name</span>
<span id="cb7-312"><a href="#cb7-312" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-313"><a href="#cb7-313" aria-hidden="true" tabindex="-1"></a><span class="ex">104</span> <span class="kw">|</span>         <span class="ex">self.pos.1</span> <span class="at">-</span> self.sprite.dimensions<span class="er">(</span><span class="kw">)</span><span class="fu">.unwrap()</span><span class="ex">.h</span> as f32 / 2.0</span>
<span id="cb7-314"><a href="#cb7-314" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                               <span class="ex">+++++++++</span></span>
<span id="cb7-315"><a href="#cb7-315" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-316"><a href="#cb7-316" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0061<span class="op">]</span><span class="ex">:</span> this method takes 1 argument but 0 arguments were supplied</span>
<span id="cb7-317"><a href="#cb7-317" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/bullet.rs:108:21</span>
<span id="cb7-318"><a href="#cb7-318" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-319"><a href="#cb7-319" aria-hidden="true" tabindex="-1"></a><span class="ex">108</span> <span class="kw">|</span>         <span class="fu">self.sprite.dimensions()</span><span class="ex">.w</span></span>
<span id="cb7-320"><a href="#cb7-320" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                     <span class="ex">^^^^^^^^^^--</span> an argument of type <span class="kw">`&amp;</span><span class="ex">_</span><span class="kw">`</span> is missing</span>
<span id="cb7-321"><a href="#cb7-321" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-322"><a href="#cb7-322" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> method defined here</span>
<span id="cb7-323"><a href="#cb7-323" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/draw.rs:299:8</span>
<span id="cb7-324"><a href="#cb7-324" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-325"><a href="#cb7-325" aria-hidden="true" tabindex="-1"></a><span class="ex">299</span> <span class="kw">|</span>     <span class="ex">fn</span> dimensions<span class="er">(</span><span class="kw">&amp;</span><span class="ex">self,</span> gfx: <span class="kw">&amp;</span><span class="ex">impl</span> Has<span class="op">&lt;</span>GraphicsContext<span class="op">&gt;</span><span class="kw">)</span> <span class="ex">-</span><span class="op">&gt;</span> Option<span class="op">&lt;</span>Rect<span class="op">&gt;</span><span class="kw">;</span></span>
<span id="cb7-326"><a href="#cb7-326" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>        <span class="ex">^^^^^^^^^^</span></span>
<span id="cb7-327"><a href="#cb7-327" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> provide the argument</span>
<span id="cb7-328"><a href="#cb7-328" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-329"><a href="#cb7-329" aria-hidden="true" tabindex="-1"></a><span class="ex">108</span> <span class="kw">|</span>         <span class="ex">self.sprite.dimensions</span><span class="er">(</span><span class="ex">/*</span> gfx <span class="pp">*</span>/<span class="kw">)</span><span class="ex">.w</span></span>
<span id="cb7-330"><a href="#cb7-330" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                               <span class="ex">~~~~~~~~~~~</span></span>
<span id="cb7-331"><a href="#cb7-331" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-332"><a href="#cb7-332" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0609<span class="op">]</span><span class="ex">:</span> no field <span class="kw">`</span><span class="fu">w</span><span class="kw">`</span> on type <span class="kw">`</span><span class="ex">Option</span><span class="op">&lt;</span>Rect<span class="op">&gt;</span><span class="kw">`</span></span>
<span id="cb7-333"><a href="#cb7-333" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/bullet.rs:108:34</span>
<span id="cb7-334"><a href="#cb7-334" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-335"><a href="#cb7-335" aria-hidden="true" tabindex="-1"></a><span class="ex">108</span> <span class="kw">|</span>         <span class="fu">self.sprite.dimensions()</span><span class="ex">.w</span></span>
<span id="cb7-336"><a href="#cb7-336" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                  <span class="ex">^</span> unknown field</span>
<span id="cb7-337"><a href="#cb7-337" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-338"><a href="#cb7-338" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> one of the expressions<span class="st">&#39; fields has a field of the same name</span></span>
<span id="cb7-339"><a href="#cb7-339" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-340"><a href="#cb7-340" aria-hidden="true" tabindex="-1"></a><span class="st">108 |         self.sprite.dimensions().unwrap().w</span></span>
<span id="cb7-341"><a href="#cb7-341" aria-hidden="true" tabindex="-1"></a><span class="st">    |                                  +++++++++</span></span>
<span id="cb7-342"><a href="#cb7-342" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-343"><a href="#cb7-343" aria-hidden="true" tabindex="-1"></a><span class="st">error[E0061]: this method takes 1 argument but 0 arguments were supplied</span></span>
<span id="cb7-344"><a href="#cb7-344" aria-hidden="true" tabindex="-1"></a><span class="st">   --&gt; src/bullet.rs:112:21</span></span>
<span id="cb7-345"><a href="#cb7-345" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-346"><a href="#cb7-346" aria-hidden="true" tabindex="-1"></a><span class="st">112 |         self.sprite.dimensions().h</span></span>
<span id="cb7-347"><a href="#cb7-347" aria-hidden="true" tabindex="-1"></a><span class="st">    |                     ^^^^^^^^^^-- an argument of type `&amp;_` is missing</span></span>
<span id="cb7-348"><a href="#cb7-348" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-349"><a href="#cb7-349" aria-hidden="true" tabindex="-1"></a><span class="st">note: method defined here</span></span>
<span id="cb7-350"><a href="#cb7-350" aria-hidden="true" tabindex="-1"></a><span class="st">   --&gt; /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/draw.rs:299:8</span></span>
<span id="cb7-351"><a href="#cb7-351" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-352"><a href="#cb7-352" aria-hidden="true" tabindex="-1"></a><span class="st">299 |     fn dimensions(&amp;self, gfx: &amp;impl Has&lt;GraphicsContext&gt;) -&gt; Option&lt;Rect&gt;;</span></span>
<span id="cb7-353"><a href="#cb7-353" aria-hidden="true" tabindex="-1"></a><span class="st">    |        ^^^^^^^^^^</span></span>
<span id="cb7-354"><a href="#cb7-354" aria-hidden="true" tabindex="-1"></a><span class="st">help: provide the argument</span></span>
<span id="cb7-355"><a href="#cb7-355" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-356"><a href="#cb7-356" aria-hidden="true" tabindex="-1"></a><span class="st">112 |         self.sprite.dimensions(/* gfx */).h</span></span>
<span id="cb7-357"><a href="#cb7-357" aria-hidden="true" tabindex="-1"></a><span class="st">    |                               ~~~~~~~~~~~</span></span>
<span id="cb7-358"><a href="#cb7-358" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-359"><a href="#cb7-359" aria-hidden="true" tabindex="-1"></a><span class="st">error[E0609]: no field `h` on type `Option&lt;Rect&gt;`</span></span>
<span id="cb7-360"><a href="#cb7-360" aria-hidden="true" tabindex="-1"></a><span class="st">   --&gt; src/bullet.rs:112:34</span></span>
<span id="cb7-361"><a href="#cb7-361" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-362"><a href="#cb7-362" aria-hidden="true" tabindex="-1"></a><span class="st">112 |         self.sprite.dimensions().h</span></span>
<span id="cb7-363"><a href="#cb7-363" aria-hidden="true" tabindex="-1"></a><span class="st">    |                                  ^ unknown field</span></span>
<span id="cb7-364"><a href="#cb7-364" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-365"><a href="#cb7-365" aria-hidden="true" tabindex="-1"></a><span class="st">help: one of the expressions&#39;</span> fields has a field of the same name</span>
<span id="cb7-366"><a href="#cb7-366" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-367"><a href="#cb7-367" aria-hidden="true" tabindex="-1"></a><span class="ex">112</span> <span class="kw">|</span>         <span class="fu">self.sprite.dimensions().unwrap()</span><span class="ex">.h</span></span>
<span id="cb7-368"><a href="#cb7-368" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                  <span class="ex">+++++++++</span></span>
<span id="cb7-369"><a href="#cb7-369" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-370"><a href="#cb7-370" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0061<span class="op">]</span><span class="ex">:</span> this method takes 1 argument but 0 arguments were supplied</span>
<span id="cb7-371"><a href="#cb7-371" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:53:34</span>
<span id="cb7-372"><a href="#cb7-372" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-373"><a href="#cb7-373" aria-hidden="true" tabindex="-1"></a><span class="ex">53</span>  <span class="kw">|</span>         <span class="ex">self.pos.0</span> <span class="at">-</span> self.sprite.dimensions<span class="er">(</span><span class="kw">)</span><span class="ex">.w</span> as f32 / 2.0</span>
<span id="cb7-374"><a href="#cb7-374" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                  <span class="ex">^^^^^^^^^^--</span> an argument of type <span class="kw">`&amp;</span><span class="ex">_</span><span class="kw">`</span> is missing</span>
<span id="cb7-375"><a href="#cb7-375" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-376"><a href="#cb7-376" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> method defined here</span>
<span id="cb7-377"><a href="#cb7-377" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/draw.rs:299:8</span>
<span id="cb7-378"><a href="#cb7-378" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-379"><a href="#cb7-379" aria-hidden="true" tabindex="-1"></a><span class="ex">299</span> <span class="kw">|</span>     <span class="ex">fn</span> dimensions<span class="er">(</span><span class="kw">&amp;</span><span class="ex">self,</span> gfx: <span class="kw">&amp;</span><span class="ex">impl</span> Has<span class="op">&lt;</span>GraphicsContext<span class="op">&gt;</span><span class="kw">)</span> <span class="ex">-</span><span class="op">&gt;</span> Option<span class="op">&lt;</span>Rect<span class="op">&gt;</span><span class="kw">;</span></span>
<span id="cb7-380"><a href="#cb7-380" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>        <span class="ex">^^^^^^^^^^</span></span>
<span id="cb7-381"><a href="#cb7-381" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> provide the argument</span>
<span id="cb7-382"><a href="#cb7-382" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-383"><a href="#cb7-383" aria-hidden="true" tabindex="-1"></a><span class="ex">53</span>  <span class="kw">|</span>         <span class="ex">self.pos.0</span> <span class="at">-</span> self.sprite.dimensions<span class="er">(</span><span class="ex">/*</span> gfx <span class="pp">*</span>/<span class="kw">)</span><span class="ex">.w</span> as f32 / 2.0</span>
<span id="cb7-384"><a href="#cb7-384" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                            <span class="ex">~~~~~~~~~~~</span></span>
<span id="cb7-385"><a href="#cb7-385" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-386"><a href="#cb7-386" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0609<span class="op">]</span><span class="ex">:</span> no field <span class="kw">`</span><span class="fu">w</span><span class="kw">`</span> on type <span class="kw">`</span><span class="ex">Option</span><span class="op">&lt;</span>Rect<span class="op">&gt;</span><span class="kw">`</span></span>
<span id="cb7-387"><a href="#cb7-387" aria-hidden="true" tabindex="-1"></a>  <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:53:47</span>
<span id="cb7-388"><a href="#cb7-388" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-389"><a href="#cb7-389" aria-hidden="true" tabindex="-1"></a><span class="ex">53</span> <span class="kw">|</span>         <span class="ex">self.pos.0</span> <span class="at">-</span> self.sprite.dimensions<span class="er">(</span><span class="kw">)</span><span class="ex">.w</span> as f32 / 2.0</span>
<span id="cb7-390"><a href="#cb7-390" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span>                                               <span class="ex">^</span> unknown field</span>
<span id="cb7-391"><a href="#cb7-391" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-392"><a href="#cb7-392" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> one of the expressions<span class="st">&#39; fields has a field of the same name</span></span>
<span id="cb7-393"><a href="#cb7-393" aria-hidden="true" tabindex="-1"></a><span class="st">   |</span></span>
<span id="cb7-394"><a href="#cb7-394" aria-hidden="true" tabindex="-1"></a><span class="st">53 |         self.pos.0 - self.sprite.dimensions().unwrap().w as f32 / 2.0</span></span>
<span id="cb7-395"><a href="#cb7-395" aria-hidden="true" tabindex="-1"></a><span class="st">   |                                               +++++++++</span></span>
<span id="cb7-396"><a href="#cb7-396" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-397"><a href="#cb7-397" aria-hidden="true" tabindex="-1"></a><span class="st">error[E0061]: this method takes 1 argument but 0 arguments were supplied</span></span>
<span id="cb7-398"><a href="#cb7-398" aria-hidden="true" tabindex="-1"></a><span class="st">   --&gt; src/main.rs:57:34</span></span>
<span id="cb7-399"><a href="#cb7-399" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-400"><a href="#cb7-400" aria-hidden="true" tabindex="-1"></a><span class="st">57  |         self.pos.1 - self.sprite.dimensions().h as f32 / 2.0</span></span>
<span id="cb7-401"><a href="#cb7-401" aria-hidden="true" tabindex="-1"></a><span class="st">    |                                  ^^^^^^^^^^-- an argument of type `&amp;_` is missing</span></span>
<span id="cb7-402"><a href="#cb7-402" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-403"><a href="#cb7-403" aria-hidden="true" tabindex="-1"></a><span class="st">note: method defined here</span></span>
<span id="cb7-404"><a href="#cb7-404" aria-hidden="true" tabindex="-1"></a><span class="st">   --&gt; /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/draw.rs:299:8</span></span>
<span id="cb7-405"><a href="#cb7-405" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-406"><a href="#cb7-406" aria-hidden="true" tabindex="-1"></a><span class="st">299 |     fn dimensions(&amp;self, gfx: &amp;impl Has&lt;GraphicsContext&gt;) -&gt; Option&lt;Rect&gt;;</span></span>
<span id="cb7-407"><a href="#cb7-407" aria-hidden="true" tabindex="-1"></a><span class="st">    |        ^^^^^^^^^^</span></span>
<span id="cb7-408"><a href="#cb7-408" aria-hidden="true" tabindex="-1"></a><span class="st">help: provide the argument</span></span>
<span id="cb7-409"><a href="#cb7-409" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-410"><a href="#cb7-410" aria-hidden="true" tabindex="-1"></a><span class="st">57  |         self.pos.1 - self.sprite.dimensions(/* gfx */).h as f32 / 2.0</span></span>
<span id="cb7-411"><a href="#cb7-411" aria-hidden="true" tabindex="-1"></a><span class="st">    |                                            ~~~~~~~~~~~</span></span>
<span id="cb7-412"><a href="#cb7-412" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-413"><a href="#cb7-413" aria-hidden="true" tabindex="-1"></a><span class="st">error[E0609]: no field `h` on type `Option&lt;Rect&gt;`</span></span>
<span id="cb7-414"><a href="#cb7-414" aria-hidden="true" tabindex="-1"></a><span class="st">  --&gt; src/main.rs:57:47</span></span>
<span id="cb7-415"><a href="#cb7-415" aria-hidden="true" tabindex="-1"></a><span class="st">   |</span></span>
<span id="cb7-416"><a href="#cb7-416" aria-hidden="true" tabindex="-1"></a><span class="st">57 |         self.pos.1 - self.sprite.dimensions().h as f32 / 2.0</span></span>
<span id="cb7-417"><a href="#cb7-417" aria-hidden="true" tabindex="-1"></a><span class="st">   |                                               ^ unknown field</span></span>
<span id="cb7-418"><a href="#cb7-418" aria-hidden="true" tabindex="-1"></a><span class="st">   |</span></span>
<span id="cb7-419"><a href="#cb7-419" aria-hidden="true" tabindex="-1"></a><span class="st">help: one of the expressions&#39;</span> fields has a field of the same name</span>
<span id="cb7-420"><a href="#cb7-420" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-421"><a href="#cb7-421" aria-hidden="true" tabindex="-1"></a><span class="ex">57</span> <span class="kw">|</span>         <span class="ex">self.pos.1</span> <span class="at">-</span> self.sprite.dimensions<span class="er">(</span><span class="kw">)</span><span class="fu">.unwrap()</span><span class="ex">.h</span> as f32 / 2.0</span>
<span id="cb7-422"><a href="#cb7-422" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span>                                               <span class="ex">+++++++++</span></span>
<span id="cb7-423"><a href="#cb7-423" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-424"><a href="#cb7-424" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0061<span class="op">]</span><span class="ex">:</span> this method takes 1 argument but 0 arguments were supplied</span>
<span id="cb7-425"><a href="#cb7-425" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:61:21</span>
<span id="cb7-426"><a href="#cb7-426" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-427"><a href="#cb7-427" aria-hidden="true" tabindex="-1"></a><span class="ex">61</span>  <span class="kw">|</span>         <span class="fu">self.sprite.dimensions()</span><span class="ex">.w</span></span>
<span id="cb7-428"><a href="#cb7-428" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                     <span class="ex">^^^^^^^^^^--</span> an argument of type <span class="kw">`&amp;</span><span class="ex">_</span><span class="kw">`</span> is missing</span>
<span id="cb7-429"><a href="#cb7-429" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-430"><a href="#cb7-430" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> method defined here</span>
<span id="cb7-431"><a href="#cb7-431" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/draw.rs:299:8</span>
<span id="cb7-432"><a href="#cb7-432" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-433"><a href="#cb7-433" aria-hidden="true" tabindex="-1"></a><span class="ex">299</span> <span class="kw">|</span>     <span class="ex">fn</span> dimensions<span class="er">(</span><span class="kw">&amp;</span><span class="ex">self,</span> gfx: <span class="kw">&amp;</span><span class="ex">impl</span> Has<span class="op">&lt;</span>GraphicsContext<span class="op">&gt;</span><span class="kw">)</span> <span class="ex">-</span><span class="op">&gt;</span> Option<span class="op">&lt;</span>Rect<span class="op">&gt;</span><span class="kw">;</span></span>
<span id="cb7-434"><a href="#cb7-434" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>        <span class="ex">^^^^^^^^^^</span></span>
<span id="cb7-435"><a href="#cb7-435" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> provide the argument</span>
<span id="cb7-436"><a href="#cb7-436" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-437"><a href="#cb7-437" aria-hidden="true" tabindex="-1"></a><span class="ex">61</span>  <span class="kw">|</span>         <span class="ex">self.sprite.dimensions</span><span class="er">(</span><span class="ex">/*</span> gfx <span class="pp">*</span>/<span class="kw">)</span><span class="ex">.w</span></span>
<span id="cb7-438"><a href="#cb7-438" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                               <span class="ex">~~~~~~~~~~~</span></span>
<span id="cb7-439"><a href="#cb7-439" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-440"><a href="#cb7-440" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0609<span class="op">]</span><span class="ex">:</span> no field <span class="kw">`</span><span class="fu">w</span><span class="kw">`</span> on type <span class="kw">`</span><span class="ex">Option</span><span class="op">&lt;</span>Rect<span class="op">&gt;</span><span class="kw">`</span></span>
<span id="cb7-441"><a href="#cb7-441" aria-hidden="true" tabindex="-1"></a>  <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:61:34</span>
<span id="cb7-442"><a href="#cb7-442" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-443"><a href="#cb7-443" aria-hidden="true" tabindex="-1"></a><span class="ex">61</span> <span class="kw">|</span>         <span class="fu">self.sprite.dimensions()</span><span class="ex">.w</span></span>
<span id="cb7-444"><a href="#cb7-444" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span>                                  <span class="ex">^</span> unknown field</span>
<span id="cb7-445"><a href="#cb7-445" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-446"><a href="#cb7-446" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> one of the expressions<span class="st">&#39; fields has a field of the same name</span></span>
<span id="cb7-447"><a href="#cb7-447" aria-hidden="true" tabindex="-1"></a><span class="st">   |</span></span>
<span id="cb7-448"><a href="#cb7-448" aria-hidden="true" tabindex="-1"></a><span class="st">61 |         self.sprite.dimensions().unwrap().w</span></span>
<span id="cb7-449"><a href="#cb7-449" aria-hidden="true" tabindex="-1"></a><span class="st">   |                                  +++++++++</span></span>
<span id="cb7-450"><a href="#cb7-450" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-451"><a href="#cb7-451" aria-hidden="true" tabindex="-1"></a><span class="st">error[E0061]: this method takes 1 argument but 0 arguments were supplied</span></span>
<span id="cb7-452"><a href="#cb7-452" aria-hidden="true" tabindex="-1"></a><span class="st">   --&gt; src/main.rs:65:21</span></span>
<span id="cb7-453"><a href="#cb7-453" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-454"><a href="#cb7-454" aria-hidden="true" tabindex="-1"></a><span class="st">65  |         self.sprite.dimensions().h</span></span>
<span id="cb7-455"><a href="#cb7-455" aria-hidden="true" tabindex="-1"></a><span class="st">    |                     ^^^^^^^^^^-- an argument of type `&amp;_` is missing</span></span>
<span id="cb7-456"><a href="#cb7-456" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-457"><a href="#cb7-457" aria-hidden="true" tabindex="-1"></a><span class="st">note: method defined here</span></span>
<span id="cb7-458"><a href="#cb7-458" aria-hidden="true" tabindex="-1"></a><span class="st">   --&gt; /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/draw.rs:299:8</span></span>
<span id="cb7-459"><a href="#cb7-459" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-460"><a href="#cb7-460" aria-hidden="true" tabindex="-1"></a><span class="st">299 |     fn dimensions(&amp;self, gfx: &amp;impl Has&lt;GraphicsContext&gt;) -&gt; Option&lt;Rect&gt;;</span></span>
<span id="cb7-461"><a href="#cb7-461" aria-hidden="true" tabindex="-1"></a><span class="st">    |        ^^^^^^^^^^</span></span>
<span id="cb7-462"><a href="#cb7-462" aria-hidden="true" tabindex="-1"></a><span class="st">help: provide the argument</span></span>
<span id="cb7-463"><a href="#cb7-463" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-464"><a href="#cb7-464" aria-hidden="true" tabindex="-1"></a><span class="st">65  |         self.sprite.dimensions(/* gfx */).h</span></span>
<span id="cb7-465"><a href="#cb7-465" aria-hidden="true" tabindex="-1"></a><span class="st">    |                               ~~~~~~~~~~~</span></span>
<span id="cb7-466"><a href="#cb7-466" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-467"><a href="#cb7-467" aria-hidden="true" tabindex="-1"></a><span class="st">error[E0609]: no field `h` on type `Option&lt;Rect&gt;`</span></span>
<span id="cb7-468"><a href="#cb7-468" aria-hidden="true" tabindex="-1"></a><span class="st">  --&gt; src/main.rs:65:34</span></span>
<span id="cb7-469"><a href="#cb7-469" aria-hidden="true" tabindex="-1"></a><span class="st">   |</span></span>
<span id="cb7-470"><a href="#cb7-470" aria-hidden="true" tabindex="-1"></a><span class="st">65 |         self.sprite.dimensions().h</span></span>
<span id="cb7-471"><a href="#cb7-471" aria-hidden="true" tabindex="-1"></a><span class="st">   |                                  ^ unknown field</span></span>
<span id="cb7-472"><a href="#cb7-472" aria-hidden="true" tabindex="-1"></a><span class="st">   |</span></span>
<span id="cb7-473"><a href="#cb7-473" aria-hidden="true" tabindex="-1"></a><span class="st">help: one of the expressions&#39;</span> fields has a field of the same name</span>
<span id="cb7-474"><a href="#cb7-474" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-475"><a href="#cb7-475" aria-hidden="true" tabindex="-1"></a><span class="ex">65</span> <span class="kw">|</span>         <span class="fu">self.sprite.dimensions().unwrap()</span><span class="ex">.h</span></span>
<span id="cb7-476"><a href="#cb7-476" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span>                                  <span class="ex">+++++++++</span></span>
<span id="cb7-477"><a href="#cb7-477" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-478"><a href="#cb7-478" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0624<span class="op">]</span><span class="ex">:</span> associated function <span class="kw">`</span><span class="ex">new</span><span class="kw">`</span> is private</span>
<span id="cb7-479"><a href="#cb7-479" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:120:50</span>
<span id="cb7-480"><a href="#cb7-480" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-481"><a href="#cb7-481" aria-hidden="true" tabindex="-1"></a><span class="ex">120</span> <span class="kw">|</span>               <span class="ex">alien_idle:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">ctx,</span> <span class="st">&quot;/ENEMY.png&quot;</span><span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-482"><a href="#cb7-482" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                    <span class="ex">^^^</span> private associated function</span>
<span id="cb7-483"><a href="#cb7-483" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-484"><a href="#cb7-484" aria-hidden="true" tabindex="-1"></a>   <span class="ex">:::</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/image.rs:161:5</span>
<span id="cb7-485"><a href="#cb7-485" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-486"><a href="#cb7-486" aria-hidden="true" tabindex="-1"></a><span class="ex">161</span> <span class="kw">|</span> <span class="ex">/</span>     fn new<span class="er">(</span></span>
<span id="cb7-487"><a href="#cb7-487" aria-hidden="true" tabindex="-1"></a><span class="ex">162</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">wgpu:</span> <span class="kw">&amp;</span><span class="ex">WgpuContext,</span></span>
<span id="cb7-488"><a href="#cb7-488" aria-hidden="true" tabindex="-1"></a><span class="ex">163</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">format:</span> ImageFormat,</span>
<span id="cb7-489"><a href="#cb7-489" aria-hidden="true" tabindex="-1"></a><span class="ex">164</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">width:</span> u32,</span>
<span id="cb7-490"><a href="#cb7-490" aria-hidden="true" tabindex="-1"></a><span class="ex">...</span>   <span class="kw">|</span></span>
<span id="cb7-491"><a href="#cb7-491" aria-hidden="true" tabindex="-1"></a><span class="ex">167</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">usage:</span> wgpu::TextureUsages,</span>
<span id="cb7-492"><a href="#cb7-492" aria-hidden="true" tabindex="-1"></a><span class="ex">168</span> <span class="kw">|</span> <span class="kw">|</span>     <span class="kw">)</span> <span class="ex">-</span><span class="op">&gt;</span> Self {</span>
<span id="cb7-493"><a href="#cb7-493" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span> <span class="kw">|</span><span class="ex">_____________-</span> private associated function defined here</span>
<span id="cb7-494"><a href="#cb7-494" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-495"><a href="#cb7-495" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0061<span class="op">]</span><span class="ex">:</span> this function takes 6 arguments but 2 arguments were supplied</span>
<span id="cb7-496"><a href="#cb7-496" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:120:33</span>
<span id="cb7-497"><a href="#cb7-497" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-498"><a href="#cb7-498" aria-hidden="true" tabindex="-1"></a><span class="ex">120</span> <span class="kw">|</span>             <span class="ex">alien_idle:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">ctx,</span> <span class="st">&quot;/ENEMY.png&quot;</span><span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-499"><a href="#cb7-499" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                 <span class="ex">^^^^^^^^^^^^^^^^^^^^-------------------</span></span>
<span id="cb7-500"><a href="#cb7-500" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                     <span class="kw">||</span>    <span class="kw">|</span></span>
<span id="cb7-501"><a href="#cb7-501" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                     <span class="kw">||</span>    <span class="ex">expected</span> <span class="kw">`</span><span class="ex">TextureFormat</span><span class="kw">`</span>, found <span class="kw">`&amp;</span><span class="ex">str</span><span class="kw">`</span></span>
<span id="cb7-502"><a href="#cb7-502" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                     <span class="kw">|</span><span class="ex">expected</span> <span class="kw">`&amp;</span><span class="ex">WgpuContext</span><span class="kw">`</span>, found <span class="kw">`&amp;</span><span class="ex">mut</span> Context<span class="kw">`</span></span>
<span id="cb7-503"><a href="#cb7-503" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                     <span class="ex">multiple</span> arguments are missing</span>
<span id="cb7-504"><a href="#cb7-504" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-505"><a href="#cb7-505" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> note:      expected reference <span class="kw">`&amp;</span><span class="ex">WgpuContext</span><span class="kw">`</span></span>
<span id="cb7-506"><a href="#cb7-506" aria-hidden="true" tabindex="-1"></a>            <span class="ex">found</span> mutable reference <span class="kw">`&amp;</span><span class="ex">mut</span> ggez::Context<span class="kw">`</span></span>
<span id="cb7-507"><a href="#cb7-507" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> associated function defined here</span>
<span id="cb7-508"><a href="#cb7-508" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/image.rs:161:8</span>
<span id="cb7-509"><a href="#cb7-509" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-510"><a href="#cb7-510" aria-hidden="true" tabindex="-1"></a><span class="ex">161</span> <span class="kw">|</span>     <span class="ex">fn</span> new<span class="er">(</span></span>
<span id="cb7-511"><a href="#cb7-511" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>        <span class="ex">^^^</span></span>
<span id="cb7-512"><a href="#cb7-512" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> provide the arguments</span>
<span id="cb7-513"><a href="#cb7-513" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-514"><a href="#cb7-514" aria-hidden="true" tabindex="-1"></a><span class="ex">120</span> <span class="kw">|</span>             <span class="ex">alien_idle:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">/*</span> <span class="kw">&amp;</span><span class="ex">WgpuContext</span> <span class="pp">*</span>/, /<span class="pp">*</span> wgpu_types::TextureFormat <span class="pp">*</span>/, /<span class="pp">*</span> u32 <span class="pp">*</span>/, /<span class="pp">*</span> u32 <span class="pp">*</span>/, /<span class="pp">*</span> u32 <span class="pp">*</span>/, /<span class="pp">*</span> wgpu_types::TextureUsages <span class="pp">*</span>/<span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-515"><a href="#cb7-515" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                     <span class="ex">~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></span>
<span id="cb7-516"><a href="#cb7-516" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-517"><a href="#cb7-517" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0277<span class="op">]</span><span class="ex">:</span> the <span class="kw">`</span><span class="ex">?</span><span class="kw">`</span> operator can only be applied to values that implement <span class="kw">`</span><span class="ex">Try</span><span class="kw">`</span></span>
<span id="cb7-518"><a href="#cb7-518" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:120:33</span>
<span id="cb7-519"><a href="#cb7-519" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-520"><a href="#cb7-520" aria-hidden="true" tabindex="-1"></a><span class="ex">120</span> <span class="kw">|</span>             <span class="ex">alien_idle:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">ctx,</span> <span class="st">&quot;/ENEMY.png&quot;</span><span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-521"><a href="#cb7-521" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                 <span class="ex">^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</span> the <span class="kw">`</span><span class="ex">?</span><span class="kw">`</span> operator cannot be applied to type <span class="kw">`</span><span class="ex">Image</span><span class="kw">`</span></span>
<span id="cb7-522"><a href="#cb7-522" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-523"><a href="#cb7-523" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> help: the trait <span class="kw">`</span><span class="ex">Try</span><span class="kw">`</span> is not implemented for <span class="kw">`</span><span class="ex">Image</span><span class="kw">`</span></span>
<span id="cb7-524"><a href="#cb7-524" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-525"><a href="#cb7-525" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0624<span class="op">]</span><span class="ex">:</span> associated function <span class="kw">`</span><span class="ex">new</span><span class="kw">`</span> is private</span>
<span id="cb7-526"><a href="#cb7-526" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:121:52</span>
<span id="cb7-527"><a href="#cb7-527" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-528"><a href="#cb7-528" aria-hidden="true" tabindex="-1"></a><span class="ex">121</span> <span class="kw">|</span>               <span class="ex">alien_firing:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">ctx,</span> <span class="st">&quot;/ENEMY_FIRING.png&quot;</span><span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-529"><a href="#cb7-529" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                      <span class="ex">^^^</span> private associated function</span>
<span id="cb7-530"><a href="#cb7-530" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-531"><a href="#cb7-531" aria-hidden="true" tabindex="-1"></a>   <span class="ex">:::</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/image.rs:161:5</span>
<span id="cb7-532"><a href="#cb7-532" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-533"><a href="#cb7-533" aria-hidden="true" tabindex="-1"></a><span class="ex">161</span> <span class="kw">|</span> <span class="ex">/</span>     fn new<span class="er">(</span></span>
<span id="cb7-534"><a href="#cb7-534" aria-hidden="true" tabindex="-1"></a><span class="ex">162</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">wgpu:</span> <span class="kw">&amp;</span><span class="ex">WgpuContext,</span></span>
<span id="cb7-535"><a href="#cb7-535" aria-hidden="true" tabindex="-1"></a><span class="ex">163</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">format:</span> ImageFormat,</span>
<span id="cb7-536"><a href="#cb7-536" aria-hidden="true" tabindex="-1"></a><span class="ex">164</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">width:</span> u32,</span>
<span id="cb7-537"><a href="#cb7-537" aria-hidden="true" tabindex="-1"></a><span class="ex">...</span>   <span class="kw">|</span></span>
<span id="cb7-538"><a href="#cb7-538" aria-hidden="true" tabindex="-1"></a><span class="ex">167</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">usage:</span> wgpu::TextureUsages,</span>
<span id="cb7-539"><a href="#cb7-539" aria-hidden="true" tabindex="-1"></a><span class="ex">168</span> <span class="kw">|</span> <span class="kw">|</span>     <span class="kw">)</span> <span class="ex">-</span><span class="op">&gt;</span> Self {</span>
<span id="cb7-540"><a href="#cb7-540" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span> <span class="kw">|</span><span class="ex">_____________-</span> private associated function defined here</span>
<span id="cb7-541"><a href="#cb7-541" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-542"><a href="#cb7-542" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0061<span class="op">]</span><span class="ex">:</span> this function takes 6 arguments but 2 arguments were supplied</span>
<span id="cb7-543"><a href="#cb7-543" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:121:35</span>
<span id="cb7-544"><a href="#cb7-544" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-545"><a href="#cb7-545" aria-hidden="true" tabindex="-1"></a><span class="ex">121</span> <span class="kw">|</span>             <span class="ex">alien_firing:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">ctx,</span> <span class="st">&quot;/ENEMY_FIRING.png&quot;</span><span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-546"><a href="#cb7-546" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                   <span class="ex">^^^^^^^^^^^^^^^^^^^^--------------------------</span></span>
<span id="cb7-547"><a href="#cb7-547" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                       <span class="kw">||</span>    <span class="kw">|</span></span>
<span id="cb7-548"><a href="#cb7-548" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                       <span class="kw">||</span>    <span class="ex">expected</span> <span class="kw">`</span><span class="ex">TextureFormat</span><span class="kw">`</span>, found <span class="kw">`&amp;</span><span class="ex">str</span><span class="kw">`</span></span>
<span id="cb7-549"><a href="#cb7-549" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                       <span class="kw">|</span><span class="ex">expected</span> <span class="kw">`&amp;</span><span class="ex">WgpuContext</span><span class="kw">`</span>, found <span class="kw">`&amp;</span><span class="ex">mut</span> Context<span class="kw">`</span></span>
<span id="cb7-550"><a href="#cb7-550" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                       <span class="ex">multiple</span> arguments are missing</span>
<span id="cb7-551"><a href="#cb7-551" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-552"><a href="#cb7-552" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> note:      expected reference <span class="kw">`&amp;</span><span class="ex">WgpuContext</span><span class="kw">`</span></span>
<span id="cb7-553"><a href="#cb7-553" aria-hidden="true" tabindex="-1"></a>            <span class="ex">found</span> mutable reference <span class="kw">`&amp;</span><span class="ex">mut</span> ggez::Context<span class="kw">`</span></span>
<span id="cb7-554"><a href="#cb7-554" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> associated function defined here</span>
<span id="cb7-555"><a href="#cb7-555" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/image.rs:161:8</span>
<span id="cb7-556"><a href="#cb7-556" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-557"><a href="#cb7-557" aria-hidden="true" tabindex="-1"></a><span class="ex">161</span> <span class="kw">|</span>     <span class="ex">fn</span> new<span class="er">(</span></span>
<span id="cb7-558"><a href="#cb7-558" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>        <span class="ex">^^^</span></span>
<span id="cb7-559"><a href="#cb7-559" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> provide the arguments</span>
<span id="cb7-560"><a href="#cb7-560" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-561"><a href="#cb7-561" aria-hidden="true" tabindex="-1"></a><span class="ex">121</span> <span class="kw">|</span>             <span class="ex">alien_firing:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">/*</span> <span class="kw">&amp;</span><span class="ex">WgpuContext</span> <span class="pp">*</span>/, /<span class="pp">*</span> wgpu_types::TextureFormat <span class="pp">*</span>/, /<span class="pp">*</span> u32 <span class="pp">*</span>/, /<span class="pp">*</span> u32 <span class="pp">*</span>/, /<span class="pp">*</span> u32 <span class="pp">*</span>/, /<span class="pp">*</span> wgpu_types::TextureUsages <span class="pp">*</span>/<span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-562"><a href="#cb7-562" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                       <span class="ex">~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></span>
<span id="cb7-563"><a href="#cb7-563" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-564"><a href="#cb7-564" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0277<span class="op">]</span><span class="ex">:</span> the <span class="kw">`</span><span class="ex">?</span><span class="kw">`</span> operator can only be applied to values that implement <span class="kw">`</span><span class="ex">Try</span><span class="kw">`</span></span>
<span id="cb7-565"><a href="#cb7-565" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:121:35</span>
<span id="cb7-566"><a href="#cb7-566" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-567"><a href="#cb7-567" aria-hidden="true" tabindex="-1"></a><span class="ex">121</span> <span class="kw">|</span>             <span class="ex">alien_firing:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">ctx,</span> <span class="st">&quot;/ENEMY_FIRING.png&quot;</span><span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-568"><a href="#cb7-568" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                   <span class="ex">^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</span> the <span class="kw">`</span><span class="ex">?</span><span class="kw">`</span> operator cannot be applied to type <span class="kw">`</span><span class="ex">Image</span><span class="kw">`</span></span>
<span id="cb7-569"><a href="#cb7-569" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-570"><a href="#cb7-570" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> help: the trait <span class="kw">`</span><span class="ex">Try</span><span class="kw">`</span> is not implemented for <span class="kw">`</span><span class="ex">Image</span><span class="kw">`</span></span>
<span id="cb7-571"><a href="#cb7-571" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-572"><a href="#cb7-572" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0624<span class="op">]</span><span class="ex">:</span> associated function <span class="kw">`</span><span class="ex">new</span><span class="kw">`</span> is private</span>
<span id="cb7-573"><a href="#cb7-573" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:122:46</span>
<span id="cb7-574"><a href="#cb7-574" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-575"><a href="#cb7-575" aria-hidden="true" tabindex="-1"></a><span class="ex">122</span> <span class="kw">|</span>               <span class="ex">player:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">ctx,</span> <span class="st">&quot;/PLAYER_OLD_2.png&quot;</span><span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-576"><a href="#cb7-576" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                <span class="ex">^^^</span> private associated function</span>
<span id="cb7-577"><a href="#cb7-577" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-578"><a href="#cb7-578" aria-hidden="true" tabindex="-1"></a>   <span class="ex">:::</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/image.rs:161:5</span>
<span id="cb7-579"><a href="#cb7-579" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-580"><a href="#cb7-580" aria-hidden="true" tabindex="-1"></a><span class="ex">161</span> <span class="kw">|</span> <span class="ex">/</span>     fn new<span class="er">(</span></span>
<span id="cb7-581"><a href="#cb7-581" aria-hidden="true" tabindex="-1"></a><span class="ex">162</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">wgpu:</span> <span class="kw">&amp;</span><span class="ex">WgpuContext,</span></span>
<span id="cb7-582"><a href="#cb7-582" aria-hidden="true" tabindex="-1"></a><span class="ex">163</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">format:</span> ImageFormat,</span>
<span id="cb7-583"><a href="#cb7-583" aria-hidden="true" tabindex="-1"></a><span class="ex">164</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">width:</span> u32,</span>
<span id="cb7-584"><a href="#cb7-584" aria-hidden="true" tabindex="-1"></a><span class="ex">...</span>   <span class="kw">|</span></span>
<span id="cb7-585"><a href="#cb7-585" aria-hidden="true" tabindex="-1"></a><span class="ex">167</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">usage:</span> wgpu::TextureUsages,</span>
<span id="cb7-586"><a href="#cb7-586" aria-hidden="true" tabindex="-1"></a><span class="ex">168</span> <span class="kw">|</span> <span class="kw">|</span>     <span class="kw">)</span> <span class="ex">-</span><span class="op">&gt;</span> Self {</span>
<span id="cb7-587"><a href="#cb7-587" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span> <span class="kw">|</span><span class="ex">_____________-</span> private associated function defined here</span>
<span id="cb7-588"><a href="#cb7-588" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-589"><a href="#cb7-589" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0061<span class="op">]</span><span class="ex">:</span> this function takes 6 arguments but 2 arguments were supplied</span>
<span id="cb7-590"><a href="#cb7-590" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:122:29</span>
<span id="cb7-591"><a href="#cb7-591" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-592"><a href="#cb7-592" aria-hidden="true" tabindex="-1"></a><span class="ex">122</span> <span class="kw">|</span>             <span class="ex">player:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">ctx,</span> <span class="st">&quot;/PLAYER_OLD_2.png&quot;</span><span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-593"><a href="#cb7-593" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                             <span class="ex">^^^^^^^^^^^^^^^^^^^^--------------------------</span></span>
<span id="cb7-594"><a href="#cb7-594" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                 <span class="kw">||</span>    <span class="kw">|</span></span>
<span id="cb7-595"><a href="#cb7-595" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                 <span class="kw">||</span>    <span class="ex">expected</span> <span class="kw">`</span><span class="ex">TextureFormat</span><span class="kw">`</span>, found <span class="kw">`&amp;</span><span class="ex">str</span><span class="kw">`</span></span>
<span id="cb7-596"><a href="#cb7-596" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                 <span class="kw">|</span><span class="ex">expected</span> <span class="kw">`&amp;</span><span class="ex">WgpuContext</span><span class="kw">`</span>, found <span class="kw">`&amp;</span><span class="ex">mut</span> Context<span class="kw">`</span></span>
<span id="cb7-597"><a href="#cb7-597" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                 <span class="ex">multiple</span> arguments are missing</span>
<span id="cb7-598"><a href="#cb7-598" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-599"><a href="#cb7-599" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> note:      expected reference <span class="kw">`&amp;</span><span class="ex">WgpuContext</span><span class="kw">`</span></span>
<span id="cb7-600"><a href="#cb7-600" aria-hidden="true" tabindex="-1"></a>            <span class="ex">found</span> mutable reference <span class="kw">`&amp;</span><span class="ex">mut</span> ggez::Context<span class="kw">`</span></span>
<span id="cb7-601"><a href="#cb7-601" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> associated function defined here</span>
<span id="cb7-602"><a href="#cb7-602" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/image.rs:161:8</span>
<span id="cb7-603"><a href="#cb7-603" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-604"><a href="#cb7-604" aria-hidden="true" tabindex="-1"></a><span class="ex">161</span> <span class="kw">|</span>     <span class="ex">fn</span> new<span class="er">(</span></span>
<span id="cb7-605"><a href="#cb7-605" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>        <span class="ex">^^^</span></span>
<span id="cb7-606"><a href="#cb7-606" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> provide the arguments</span>
<span id="cb7-607"><a href="#cb7-607" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-608"><a href="#cb7-608" aria-hidden="true" tabindex="-1"></a><span class="ex">122</span> <span class="kw">|</span>             <span class="ex">player:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">/*</span> <span class="kw">&amp;</span><span class="ex">WgpuContext</span> <span class="pp">*</span>/, /<span class="pp">*</span> wgpu_types::TextureFormat <span class="pp">*</span>/, /<span class="pp">*</span> u32 <span class="pp">*</span>/, /<span class="pp">*</span> u32 <span class="pp">*</span>/, /<span class="pp">*</span> u32 <span class="pp">*</span>/, /<span class="pp">*</span> wgpu_types::TextureUsages <span class="pp">*</span>/<span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-609"><a href="#cb7-609" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                 <span class="ex">~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></span>
<span id="cb7-610"><a href="#cb7-610" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-611"><a href="#cb7-611" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0277<span class="op">]</span><span class="ex">:</span> the <span class="kw">`</span><span class="ex">?</span><span class="kw">`</span> operator can only be applied to values that implement <span class="kw">`</span><span class="ex">Try</span><span class="kw">`</span></span>
<span id="cb7-612"><a href="#cb7-612" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:122:29</span>
<span id="cb7-613"><a href="#cb7-613" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-614"><a href="#cb7-614" aria-hidden="true" tabindex="-1"></a><span class="ex">122</span> <span class="kw">|</span>             <span class="ex">player:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">ctx,</span> <span class="st">&quot;/PLAYER_OLD_2.png&quot;</span><span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-615"><a href="#cb7-615" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                             <span class="ex">^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</span> the <span class="kw">`</span><span class="ex">?</span><span class="kw">`</span> operator cannot be applied to type <span class="kw">`</span><span class="ex">Image</span><span class="kw">`</span></span>
<span id="cb7-616"><a href="#cb7-616" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-617"><a href="#cb7-617" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> help: the trait <span class="kw">`</span><span class="ex">Try</span><span class="kw">`</span> is not implemented for <span class="kw">`</span><span class="ex">Image</span><span class="kw">`</span></span>
<span id="cb7-618"><a href="#cb7-618" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-619"><a href="#cb7-619" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0624<span class="op">]</span><span class="ex">:</span> associated function <span class="kw">`</span><span class="ex">new</span><span class="kw">`</span> is private</span>
<span id="cb7-620"><a href="#cb7-620" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:123:50</span>
<span id="cb7-621"><a href="#cb7-621" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-622"><a href="#cb7-622" aria-hidden="true" tabindex="-1"></a><span class="ex">123</span> <span class="kw">|</span>               <span class="ex">red_bullet:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">ctx,</span> <span class="st">&quot;/Red_Missile.png&quot;</span><span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-623"><a href="#cb7-623" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                    <span class="ex">^^^</span> private associated function</span>
<span id="cb7-624"><a href="#cb7-624" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-625"><a href="#cb7-625" aria-hidden="true" tabindex="-1"></a>   <span class="ex">:::</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/image.rs:161:5</span>
<span id="cb7-626"><a href="#cb7-626" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-627"><a href="#cb7-627" aria-hidden="true" tabindex="-1"></a><span class="ex">161</span> <span class="kw">|</span> <span class="ex">/</span>     fn new<span class="er">(</span></span>
<span id="cb7-628"><a href="#cb7-628" aria-hidden="true" tabindex="-1"></a><span class="ex">162</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">wgpu:</span> <span class="kw">&amp;</span><span class="ex">WgpuContext,</span></span>
<span id="cb7-629"><a href="#cb7-629" aria-hidden="true" tabindex="-1"></a><span class="ex">163</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">format:</span> ImageFormat,</span>
<span id="cb7-630"><a href="#cb7-630" aria-hidden="true" tabindex="-1"></a><span class="ex">164</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">width:</span> u32,</span>
<span id="cb7-631"><a href="#cb7-631" aria-hidden="true" tabindex="-1"></a><span class="ex">...</span>   <span class="kw">|</span></span>
<span id="cb7-632"><a href="#cb7-632" aria-hidden="true" tabindex="-1"></a><span class="ex">167</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">usage:</span> wgpu::TextureUsages,</span>
<span id="cb7-633"><a href="#cb7-633" aria-hidden="true" tabindex="-1"></a><span class="ex">168</span> <span class="kw">|</span> <span class="kw">|</span>     <span class="kw">)</span> <span class="ex">-</span><span class="op">&gt;</span> Self {</span>
<span id="cb7-634"><a href="#cb7-634" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span> <span class="kw">|</span><span class="ex">_____________-</span> private associated function defined here</span>
<span id="cb7-635"><a href="#cb7-635" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-636"><a href="#cb7-636" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0061<span class="op">]</span><span class="ex">:</span> this function takes 6 arguments but 2 arguments were supplied</span>
<span id="cb7-637"><a href="#cb7-637" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:123:33</span>
<span id="cb7-638"><a href="#cb7-638" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-639"><a href="#cb7-639" aria-hidden="true" tabindex="-1"></a><span class="ex">123</span> <span class="kw">|</span>             <span class="ex">red_bullet:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">ctx,</span> <span class="st">&quot;/Red_Missile.png&quot;</span><span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-640"><a href="#cb7-640" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                 <span class="ex">^^^^^^^^^^^^^^^^^^^^-------------------------</span></span>
<span id="cb7-641"><a href="#cb7-641" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                     <span class="kw">||</span>    <span class="kw">|</span></span>
<span id="cb7-642"><a href="#cb7-642" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                     <span class="kw">||</span>    <span class="ex">expected</span> <span class="kw">`</span><span class="ex">TextureFormat</span><span class="kw">`</span>, found <span class="kw">`&amp;</span><span class="ex">str</span><span class="kw">`</span></span>
<span id="cb7-643"><a href="#cb7-643" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                     <span class="kw">|</span><span class="ex">expected</span> <span class="kw">`&amp;</span><span class="ex">WgpuContext</span><span class="kw">`</span>, found <span class="kw">`&amp;</span><span class="ex">mut</span> Context<span class="kw">`</span></span>
<span id="cb7-644"><a href="#cb7-644" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                     <span class="ex">multiple</span> arguments are missing</span>
<span id="cb7-645"><a href="#cb7-645" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-646"><a href="#cb7-646" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> note:      expected reference <span class="kw">`&amp;</span><span class="ex">WgpuContext</span><span class="kw">`</span></span>
<span id="cb7-647"><a href="#cb7-647" aria-hidden="true" tabindex="-1"></a>            <span class="ex">found</span> mutable reference <span class="kw">`&amp;</span><span class="ex">mut</span> ggez::Context<span class="kw">`</span></span>
<span id="cb7-648"><a href="#cb7-648" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> associated function defined here</span>
<span id="cb7-649"><a href="#cb7-649" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/image.rs:161:8</span>
<span id="cb7-650"><a href="#cb7-650" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-651"><a href="#cb7-651" aria-hidden="true" tabindex="-1"></a><span class="ex">161</span> <span class="kw">|</span>     <span class="ex">fn</span> new<span class="er">(</span></span>
<span id="cb7-652"><a href="#cb7-652" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>        <span class="ex">^^^</span></span>
<span id="cb7-653"><a href="#cb7-653" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> provide the arguments</span>
<span id="cb7-654"><a href="#cb7-654" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-655"><a href="#cb7-655" aria-hidden="true" tabindex="-1"></a><span class="ex">123</span> <span class="kw">|</span>             <span class="ex">red_bullet:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">/*</span> <span class="kw">&amp;</span><span class="ex">WgpuContext</span> <span class="pp">*</span>/, /<span class="pp">*</span> wgpu_types::TextureFormat <span class="pp">*</span>/, /<span class="pp">*</span> u32 <span class="pp">*</span>/, /<span class="pp">*</span> u32 <span class="pp">*</span>/, /<span class="pp">*</span> u32 <span class="pp">*</span>/, /<span class="pp">*</span> wgpu_types::TextureUsages <span class="pp">*</span>/<span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-656"><a href="#cb7-656" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                     <span class="ex">~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></span>
<span id="cb7-657"><a href="#cb7-657" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-658"><a href="#cb7-658" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0277<span class="op">]</span><span class="ex">:</span> the <span class="kw">`</span><span class="ex">?</span><span class="kw">`</span> operator can only be applied to values that implement <span class="kw">`</span><span class="ex">Try</span><span class="kw">`</span></span>
<span id="cb7-659"><a href="#cb7-659" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:123:33</span>
<span id="cb7-660"><a href="#cb7-660" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-661"><a href="#cb7-661" aria-hidden="true" tabindex="-1"></a><span class="ex">123</span> <span class="kw">|</span>             <span class="ex">red_bullet:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">ctx,</span> <span class="st">&quot;/Red_Missile.png&quot;</span><span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-662"><a href="#cb7-662" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                 <span class="ex">^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</span> the <span class="kw">`</span><span class="ex">?</span><span class="kw">`</span> operator cannot be applied to type <span class="kw">`</span><span class="ex">Image</span><span class="kw">`</span></span>
<span id="cb7-663"><a href="#cb7-663" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-664"><a href="#cb7-664" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> help: the trait <span class="kw">`</span><span class="ex">Try</span><span class="kw">`</span> is not implemented for <span class="kw">`</span><span class="ex">Image</span><span class="kw">`</span></span>
<span id="cb7-665"><a href="#cb7-665" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-666"><a href="#cb7-666" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0624<span class="op">]</span><span class="ex">:</span> associated function <span class="kw">`</span><span class="ex">new</span><span class="kw">`</span> is private</span>
<span id="cb7-667"><a href="#cb7-667" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:124:52</span>
<span id="cb7-668"><a href="#cb7-668" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-669"><a href="#cb7-669" aria-hidden="true" tabindex="-1"></a><span class="ex">124</span> <span class="kw">|</span>               <span class="ex">green_bullet:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">ctx,</span> <span class="st">&quot;/MISSILE_FIRED.png&quot;</span><span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-670"><a href="#cb7-670" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                      <span class="ex">^^^</span> private associated function</span>
<span id="cb7-671"><a href="#cb7-671" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-672"><a href="#cb7-672" aria-hidden="true" tabindex="-1"></a>   <span class="ex">:::</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/image.rs:161:5</span>
<span id="cb7-673"><a href="#cb7-673" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-674"><a href="#cb7-674" aria-hidden="true" tabindex="-1"></a><span class="ex">161</span> <span class="kw">|</span> <span class="ex">/</span>     fn new<span class="er">(</span></span>
<span id="cb7-675"><a href="#cb7-675" aria-hidden="true" tabindex="-1"></a><span class="ex">162</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">wgpu:</span> <span class="kw">&amp;</span><span class="ex">WgpuContext,</span></span>
<span id="cb7-676"><a href="#cb7-676" aria-hidden="true" tabindex="-1"></a><span class="ex">163</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">format:</span> ImageFormat,</span>
<span id="cb7-677"><a href="#cb7-677" aria-hidden="true" tabindex="-1"></a><span class="ex">164</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">width:</span> u32,</span>
<span id="cb7-678"><a href="#cb7-678" aria-hidden="true" tabindex="-1"></a><span class="ex">...</span>   <span class="kw">|</span></span>
<span id="cb7-679"><a href="#cb7-679" aria-hidden="true" tabindex="-1"></a><span class="ex">167</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">usage:</span> wgpu::TextureUsages,</span>
<span id="cb7-680"><a href="#cb7-680" aria-hidden="true" tabindex="-1"></a><span class="ex">168</span> <span class="kw">|</span> <span class="kw">|</span>     <span class="kw">)</span> <span class="ex">-</span><span class="op">&gt;</span> Self {</span>
<span id="cb7-681"><a href="#cb7-681" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span> <span class="kw">|</span><span class="ex">_____________-</span> private associated function defined here</span>
<span id="cb7-682"><a href="#cb7-682" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-683"><a href="#cb7-683" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0061<span class="op">]</span><span class="ex">:</span> this function takes 6 arguments but 2 arguments were supplied</span>
<span id="cb7-684"><a href="#cb7-684" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:124:35</span>
<span id="cb7-685"><a href="#cb7-685" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-686"><a href="#cb7-686" aria-hidden="true" tabindex="-1"></a><span class="ex">124</span> <span class="kw">|</span>             <span class="ex">green_bullet:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">ctx,</span> <span class="st">&quot;/MISSILE_FIRED.png&quot;</span><span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-687"><a href="#cb7-687" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                   <span class="ex">^^^^^^^^^^^^^^^^^^^^---------------------------</span></span>
<span id="cb7-688"><a href="#cb7-688" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                       <span class="kw">||</span>    <span class="kw">|</span></span>
<span id="cb7-689"><a href="#cb7-689" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                       <span class="kw">||</span>    <span class="ex">expected</span> <span class="kw">`</span><span class="ex">TextureFormat</span><span class="kw">`</span>, found <span class="kw">`&amp;</span><span class="ex">str</span><span class="kw">`</span></span>
<span id="cb7-690"><a href="#cb7-690" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                       <span class="kw">|</span><span class="ex">expected</span> <span class="kw">`&amp;</span><span class="ex">WgpuContext</span><span class="kw">`</span>, found <span class="kw">`&amp;</span><span class="ex">mut</span> Context<span class="kw">`</span></span>
<span id="cb7-691"><a href="#cb7-691" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                       <span class="ex">multiple</span> arguments are missing</span>
<span id="cb7-692"><a href="#cb7-692" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-693"><a href="#cb7-693" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> note:      expected reference <span class="kw">`&amp;</span><span class="ex">WgpuContext</span><span class="kw">`</span></span>
<span id="cb7-694"><a href="#cb7-694" aria-hidden="true" tabindex="-1"></a>            <span class="ex">found</span> mutable reference <span class="kw">`&amp;</span><span class="ex">mut</span> ggez::Context<span class="kw">`</span></span>
<span id="cb7-695"><a href="#cb7-695" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> associated function defined here</span>
<span id="cb7-696"><a href="#cb7-696" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/image.rs:161:8</span>
<span id="cb7-697"><a href="#cb7-697" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-698"><a href="#cb7-698" aria-hidden="true" tabindex="-1"></a><span class="ex">161</span> <span class="kw">|</span>     <span class="ex">fn</span> new<span class="er">(</span></span>
<span id="cb7-699"><a href="#cb7-699" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>        <span class="ex">^^^</span></span>
<span id="cb7-700"><a href="#cb7-700" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> provide the arguments</span>
<span id="cb7-701"><a href="#cb7-701" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-702"><a href="#cb7-702" aria-hidden="true" tabindex="-1"></a><span class="ex">124</span> <span class="kw">|</span>             <span class="ex">green_bullet:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">/*</span> <span class="kw">&amp;</span><span class="ex">WgpuContext</span> <span class="pp">*</span>/, /<span class="pp">*</span> wgpu_types::TextureFormat <span class="pp">*</span>/, /<span class="pp">*</span> u32 <span class="pp">*</span>/, /<span class="pp">*</span> u32 <span class="pp">*</span>/, /<span class="pp">*</span> u32 <span class="pp">*</span>/, /<span class="pp">*</span> wgpu_types::TextureUsages <span class="pp">*</span>/<span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-703"><a href="#cb7-703" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                       <span class="ex">~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></span>
<span id="cb7-704"><a href="#cb7-704" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-705"><a href="#cb7-705" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0277<span class="op">]</span><span class="ex">:</span> the <span class="kw">`</span><span class="ex">?</span><span class="kw">`</span> operator can only be applied to values that implement <span class="kw">`</span><span class="ex">Try</span><span class="kw">`</span></span>
<span id="cb7-706"><a href="#cb7-706" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:124:35</span>
<span id="cb7-707"><a href="#cb7-707" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-708"><a href="#cb7-708" aria-hidden="true" tabindex="-1"></a><span class="ex">124</span> <span class="kw">|</span>             <span class="ex">green_bullet:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">ctx,</span> <span class="st">&quot;/MISSILE_FIRED.png&quot;</span><span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-709"><a href="#cb7-709" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                   <span class="ex">^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</span> the <span class="kw">`</span><span class="ex">?</span><span class="kw">`</span> operator cannot be applied to type <span class="kw">`</span><span class="ex">Image</span><span class="kw">`</span></span>
<span id="cb7-710"><a href="#cb7-710" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-711"><a href="#cb7-711" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> help: the trait <span class="kw">`</span><span class="ex">Try</span><span class="kw">`</span> is not implemented for <span class="kw">`</span><span class="ex">Image</span><span class="kw">`</span></span>
<span id="cb7-712"><a href="#cb7-712" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-713"><a href="#cb7-713" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0624<span class="op">]</span><span class="ex">:</span> associated function <span class="kw">`</span><span class="ex">new</span><span class="kw">`</span> is private</span>
<span id="cb7-714"><a href="#cb7-714" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:125:50</span>
<span id="cb7-715"><a href="#cb7-715" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-716"><a href="#cb7-716" aria-hidden="true" tabindex="-1"></a><span class="ex">125</span> <span class="kw">|</span>               <span class="ex">background:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">ctx,</span> <span class="st">&quot;/Space.png&quot;</span><span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-717"><a href="#cb7-717" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                    <span class="ex">^^^</span> private associated function</span>
<span id="cb7-718"><a href="#cb7-718" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-719"><a href="#cb7-719" aria-hidden="true" tabindex="-1"></a>   <span class="ex">:::</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/image.rs:161:5</span>
<span id="cb7-720"><a href="#cb7-720" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-721"><a href="#cb7-721" aria-hidden="true" tabindex="-1"></a><span class="ex">161</span> <span class="kw">|</span> <span class="ex">/</span>     fn new<span class="er">(</span></span>
<span id="cb7-722"><a href="#cb7-722" aria-hidden="true" tabindex="-1"></a><span class="ex">162</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">wgpu:</span> <span class="kw">&amp;</span><span class="ex">WgpuContext,</span></span>
<span id="cb7-723"><a href="#cb7-723" aria-hidden="true" tabindex="-1"></a><span class="ex">163</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">format:</span> ImageFormat,</span>
<span id="cb7-724"><a href="#cb7-724" aria-hidden="true" tabindex="-1"></a><span class="ex">164</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">width:</span> u32,</span>
<span id="cb7-725"><a href="#cb7-725" aria-hidden="true" tabindex="-1"></a><span class="ex">...</span>   <span class="kw">|</span></span>
<span id="cb7-726"><a href="#cb7-726" aria-hidden="true" tabindex="-1"></a><span class="ex">167</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">usage:</span> wgpu::TextureUsages,</span>
<span id="cb7-727"><a href="#cb7-727" aria-hidden="true" tabindex="-1"></a><span class="ex">168</span> <span class="kw">|</span> <span class="kw">|</span>     <span class="kw">)</span> <span class="ex">-</span><span class="op">&gt;</span> Self {</span>
<span id="cb7-728"><a href="#cb7-728" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span> <span class="kw">|</span><span class="ex">_____________-</span> private associated function defined here</span>
<span id="cb7-729"><a href="#cb7-729" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-730"><a href="#cb7-730" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0061<span class="op">]</span><span class="ex">:</span> this function takes 6 arguments but 2 arguments were supplied</span>
<span id="cb7-731"><a href="#cb7-731" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:125:33</span>
<span id="cb7-732"><a href="#cb7-732" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-733"><a href="#cb7-733" aria-hidden="true" tabindex="-1"></a><span class="ex">125</span> <span class="kw">|</span>             <span class="ex">background:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">ctx,</span> <span class="st">&quot;/Space.png&quot;</span><span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-734"><a href="#cb7-734" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                 <span class="ex">^^^^^^^^^^^^^^^^^^^^-------------------</span></span>
<span id="cb7-735"><a href="#cb7-735" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                     <span class="kw">||</span>    <span class="kw">|</span></span>
<span id="cb7-736"><a href="#cb7-736" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                     <span class="kw">||</span>    <span class="ex">expected</span> <span class="kw">`</span><span class="ex">TextureFormat</span><span class="kw">`</span>, found <span class="kw">`&amp;</span><span class="ex">str</span><span class="kw">`</span></span>
<span id="cb7-737"><a href="#cb7-737" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                     <span class="kw">|</span><span class="ex">expected</span> <span class="kw">`&amp;</span><span class="ex">WgpuContext</span><span class="kw">`</span>, found <span class="kw">`&amp;</span><span class="ex">mut</span> Context<span class="kw">`</span></span>
<span id="cb7-738"><a href="#cb7-738" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                     <span class="ex">multiple</span> arguments are missing</span>
<span id="cb7-739"><a href="#cb7-739" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-740"><a href="#cb7-740" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> note:      expected reference <span class="kw">`&amp;</span><span class="ex">WgpuContext</span><span class="kw">`</span></span>
<span id="cb7-741"><a href="#cb7-741" aria-hidden="true" tabindex="-1"></a>            <span class="ex">found</span> mutable reference <span class="kw">`&amp;</span><span class="ex">mut</span> ggez::Context<span class="kw">`</span></span>
<span id="cb7-742"><a href="#cb7-742" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> associated function defined here</span>
<span id="cb7-743"><a href="#cb7-743" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/image.rs:161:8</span>
<span id="cb7-744"><a href="#cb7-744" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-745"><a href="#cb7-745" aria-hidden="true" tabindex="-1"></a><span class="ex">161</span> <span class="kw">|</span>     <span class="ex">fn</span> new<span class="er">(</span></span>
<span id="cb7-746"><a href="#cb7-746" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>        <span class="ex">^^^</span></span>
<span id="cb7-747"><a href="#cb7-747" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> provide the arguments</span>
<span id="cb7-748"><a href="#cb7-748" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-749"><a href="#cb7-749" aria-hidden="true" tabindex="-1"></a><span class="ex">125</span> <span class="kw">|</span>             <span class="ex">background:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">/*</span> <span class="kw">&amp;</span><span class="ex">WgpuContext</span> <span class="pp">*</span>/, /<span class="pp">*</span> wgpu_types::TextureFormat <span class="pp">*</span>/, /<span class="pp">*</span> u32 <span class="pp">*</span>/, /<span class="pp">*</span> u32 <span class="pp">*</span>/, /<span class="pp">*</span> u32 <span class="pp">*</span>/, /<span class="pp">*</span> wgpu_types::TextureUsages <span class="pp">*</span>/<span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-750"><a href="#cb7-750" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                     <span class="ex">~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></span>
<span id="cb7-751"><a href="#cb7-751" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-752"><a href="#cb7-752" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0277<span class="op">]</span><span class="ex">:</span> the <span class="kw">`</span><span class="ex">?</span><span class="kw">`</span> operator can only be applied to values that implement <span class="kw">`</span><span class="ex">Try</span><span class="kw">`</span></span>
<span id="cb7-753"><a href="#cb7-753" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:125:33</span>
<span id="cb7-754"><a href="#cb7-754" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-755"><a href="#cb7-755" aria-hidden="true" tabindex="-1"></a><span class="ex">125</span> <span class="kw">|</span>             <span class="ex">background:</span> Rc::new<span class="er">(</span><span class="ex">graphics::Image::new</span><span class="er">(</span><span class="ex">ctx,</span> <span class="st">&quot;/Space.png&quot;</span><span class="kw">)</span><span class="ex">?</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-756"><a href="#cb7-756" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                 <span class="ex">^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</span> the <span class="kw">`</span><span class="ex">?</span><span class="kw">`</span> operator cannot be applied to type <span class="kw">`</span><span class="ex">Image</span><span class="kw">`</span></span>
<span id="cb7-757"><a href="#cb7-757" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-758"><a href="#cb7-758" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> help: the trait <span class="kw">`</span><span class="ex">Try</span><span class="kw">`</span> is not implemented for <span class="kw">`</span><span class="ex">Image</span><span class="kw">`</span></span>
<span id="cb7-759"><a href="#cb7-759" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-760"><a href="#cb7-760" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0061<span class="op">]</span><span class="ex">:</span> this method takes 1 argument but 0 arguments were supplied</span>
<span id="cb7-761"><a href="#cb7-761" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:257:30</span>
<span id="cb7-762"><a href="#cb7-762" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-763"><a href="#cb7-763" aria-hidden="true" tabindex="-1"></a><span class="ex">257</span> <span class="kw">|</span>             <span class="fu">game.audio.bloop.play()</span><span class="ex">?</span><span class="kw">;</span></span>
<span id="cb7-764"><a href="#cb7-764" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                              <span class="ex">^^^^--</span> an argument of type <span class="kw">`&amp;</span><span class="ex">_</span><span class="kw">`</span> is missing</span>
<span id="cb7-765"><a href="#cb7-765" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-766"><a href="#cb7-766" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> method defined here</span>
<span id="cb7-767"><a href="#cb7-767" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/audio.rs:131:8</span>
<span id="cb7-768"><a href="#cb7-768" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-769"><a href="#cb7-769" aria-hidden="true" tabindex="-1"></a><span class="ex">131</span> <span class="kw">|</span>     <span class="ex">fn</span> play<span class="er">(</span><span class="kw">&amp;</span><span class="ex">mut</span> self, audio: <span class="kw">&amp;</span><span class="ex">impl</span> Has<span class="op">&lt;</span>AudioContext<span class="op">&gt;</span><span class="kw">)</span> <span class="ex">-</span><span class="op">&gt;</span> GameResult {</span>
<span id="cb7-770"><a href="#cb7-770" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>        <span class="ex">^^^^</span></span>
<span id="cb7-771"><a href="#cb7-771" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> provide the argument</span>
<span id="cb7-772"><a href="#cb7-772" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-773"><a href="#cb7-773" aria-hidden="true" tabindex="-1"></a><span class="ex">257</span> <span class="kw">|</span>             <span class="ex">game.audio.bloop.play</span><span class="er">(</span><span class="ex">/*</span> audio <span class="pp">*</span>/<span class="kw">)</span><span class="ex">?</span><span class="kw">;</span></span>
<span id="cb7-774"><a href="#cb7-774" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                  <span class="ex">~~~~~~~~~~~~~</span></span>
<span id="cb7-775"><a href="#cb7-775" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-776"><a href="#cb7-776" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb7-777"><a href="#cb7-777" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:274:34</span>
<span id="cb7-778"><a href="#cb7-778" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-779"><a href="#cb7-779" aria-hidden="true" tabindex="-1"></a><span class="ex">274</span> <span class="kw">|</span>     <span class="ex">game.sprites.background.draw</span><span class="er">(</span><span class="ex">ctx,</span> DrawParam::default<span class="er">(</span><span class="kw">))</span></span>
<span id="cb7-780"><a href="#cb7-780" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                             <span class="ex">----</span> ^^^ expected <span class="kw">`&amp;</span><span class="ex">mut</span> Canvas<span class="kw">`</span>, found <span class="kw">`&amp;</span><span class="ex">mut</span> Context<span class="kw">`</span></span>
<span id="cb7-781"><a href="#cb7-781" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                             <span class="kw">|</span></span>
<span id="cb7-782"><a href="#cb7-782" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                             <span class="ex">arguments</span> to this method are incorrect</span>
<span id="cb7-783"><a href="#cb7-783" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-784"><a href="#cb7-784" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> note: expected mutable reference <span class="kw">`&amp;</span><span class="ex">mut</span> Canvas<span class="kw">`</span></span>
<span id="cb7-785"><a href="#cb7-785" aria-hidden="true" tabindex="-1"></a>               <span class="ex">found</span> mutable reference <span class="kw">`&amp;</span><span class="ex">mut</span> ggez::Context<span class="kw">`</span></span>
<span id="cb7-786"><a href="#cb7-786" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> method defined here</span>
<span id="cb7-787"><a href="#cb7-787" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/draw.rs:293:8</span>
<span id="cb7-788"><a href="#cb7-788" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-789"><a href="#cb7-789" aria-hidden="true" tabindex="-1"></a><span class="ex">293</span> <span class="kw">|</span>     <span class="ex">fn</span> draw<span class="er">(</span><span class="kw">&amp;</span><span class="ex">self,</span> canvas: <span class="kw">&amp;</span><span class="ex">mut</span> Canvas, param: impl Into<span class="op">&lt;</span>DrawParam<span class="op">&gt;</span><span class="kw">);</span></span>
<span id="cb7-790"><a href="#cb7-790" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>        <span class="ex">^^^^</span></span>
<span id="cb7-791"><a href="#cb7-791" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-792"><a href="#cb7-792" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb7-793"><a href="#cb7-793" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:274:5</span>
<span id="cb7-794"><a href="#cb7-794" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-795"><a href="#cb7-795" aria-hidden="true" tabindex="-1"></a><span class="ex">273</span> <span class="kw">|</span> <span class="ex">fn</span> draw_background<span class="er">(</span><span class="ex">ctx:</span> <span class="kw">&amp;</span><span class="ex">mut</span> Context, game: <span class="kw">&amp;</span><span class="ex">Game</span><span class="kw">)</span> <span class="ex">-</span><span class="op">&gt;</span> GameResult<span class="op">&lt;()&gt;</span> {</span>
<span id="cb7-796"><a href="#cb7-796" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                       <span class="ex">--------------</span> expected <span class="kw">`</span><span class="ex">Result</span><span class="op">&lt;()</span>, GameError<span class="op">&gt;</span><span class="kw">`</span> because of return type</span>
<span id="cb7-797"><a href="#cb7-797" aria-hidden="true" tabindex="-1"></a><span class="ex">274</span> <span class="kw">|</span>     <span class="ex">game.sprites.background.draw</span><span class="er">(</span><span class="ex">ctx,</span> DrawParam::default<span class="er">(</span><span class="kw">))</span></span>
<span id="cb7-798"><a href="#cb7-798" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>     <span class="ex">^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</span> expected <span class="kw">`</span><span class="ex">Result</span><span class="op">&lt;()</span>, GameError<span class="op">&gt;</span><span class="kw">`</span>, found <span class="kw">`()`</span></span>
<span id="cb7-799"><a href="#cb7-799" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-800"><a href="#cb7-800" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> note:   expected enum <span class="kw">`</span><span class="ex">Result</span><span class="op">&lt;()</span>, GameError<span class="op">&gt;</span><span class="kw">`</span></span>
<span id="cb7-801"><a href="#cb7-801" aria-hidden="true" tabindex="-1"></a>            <span class="ex">found</span> unit type <span class="kw">`()`</span></span>
<span id="cb7-802"><a href="#cb7-802" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> try adding an expression at the end of the block</span>
<span id="cb7-803"><a href="#cb7-803" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-804"><a href="#cb7-804" aria-hidden="true" tabindex="-1"></a><span class="ex">274</span> ~     game.sprites.background.draw<span class="er">(</span><span class="ex">ctx,</span> DrawParam::default<span class="er">(</span><span class="kw">));</span></span>
<span id="cb7-805"><a href="#cb7-805" aria-hidden="true" tabindex="-1"></a><span class="ex">275</span> +     Ok<span class="er">(</span><span class="kw">())</span></span>
<span id="cb7-806"><a href="#cb7-806" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-807"><a href="#cb7-807" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-808"><a href="#cb7-808" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb7-809"><a href="#cb7-809" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:290:9</span>
<span id="cb7-810"><a href="#cb7-810" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-811"><a href="#cb7-811" aria-hidden="true" tabindex="-1"></a><span class="ex">289</span> <span class="kw">|</span>     <span class="ex">game.sprites.player.draw</span><span class="er">(</span></span>
<span id="cb7-812"><a href="#cb7-812" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                         <span class="ex">----</span> arguments to this method are incorrect</span>
<span id="cb7-813"><a href="#cb7-813" aria-hidden="true" tabindex="-1"></a><span class="ex">290</span> <span class="kw">|</span>         <span class="ex">ctx,</span></span>
<span id="cb7-814"><a href="#cb7-814" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>         <span class="ex">^^^</span> expected <span class="kw">`&amp;</span><span class="ex">mut</span> Canvas<span class="kw">`</span>, found <span class="kw">`&amp;</span><span class="ex">mut</span> Context<span class="kw">`</span></span>
<span id="cb7-815"><a href="#cb7-815" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-816"><a href="#cb7-816" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> note: expected mutable reference <span class="kw">`&amp;</span><span class="ex">mut</span> Canvas<span class="kw">`</span></span>
<span id="cb7-817"><a href="#cb7-817" aria-hidden="true" tabindex="-1"></a>               <span class="ex">found</span> mutable reference <span class="kw">`&amp;</span><span class="ex">mut</span> ggez::Context<span class="kw">`</span></span>
<span id="cb7-818"><a href="#cb7-818" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> method defined here</span>
<span id="cb7-819"><a href="#cb7-819" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/draw.rs:293:8</span>
<span id="cb7-820"><a href="#cb7-820" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-821"><a href="#cb7-821" aria-hidden="true" tabindex="-1"></a><span class="ex">293</span> <span class="kw">|</span>     <span class="ex">fn</span> draw<span class="er">(</span><span class="kw">&amp;</span><span class="ex">self,</span> canvas: <span class="kw">&amp;</span><span class="ex">mut</span> Canvas, param: impl Into<span class="op">&lt;</span>DrawParam<span class="op">&gt;</span><span class="kw">);</span></span>
<span id="cb7-822"><a href="#cb7-822" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>        <span class="ex">^^^^</span></span>
<span id="cb7-823"><a href="#cb7-823" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-824"><a href="#cb7-824" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb7-825"><a href="#cb7-825" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:289:5</span>
<span id="cb7-826"><a href="#cb7-826" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-827"><a href="#cb7-827" aria-hidden="true" tabindex="-1"></a><span class="ex">288</span> <span class="kw">|</span>   <span class="ex">fn</span> draw_player<span class="er">(</span><span class="ex">ctx:</span> <span class="kw">&amp;</span><span class="ex">mut</span> Context, game: <span class="kw">&amp;</span><span class="ex">Game</span><span class="kw">)</span> <span class="ex">-</span><span class="op">&gt;</span> GameResult<span class="op">&lt;()&gt;</span> {</span>
<span id="cb7-828"><a href="#cb7-828" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>                                                     <span class="ex">--------------</span> expected <span class="kw">`</span><span class="ex">Result</span><span class="op">&lt;()</span>, GameError<span class="op">&gt;</span><span class="kw">`</span> because of return type</span>
<span id="cb7-829"><a href="#cb7-829" aria-hidden="true" tabindex="-1"></a><span class="ex">289</span> <span class="kw">|</span> <span class="ex">/</span>     game.sprites.player.draw<span class="er">(</span></span>
<span id="cb7-830"><a href="#cb7-830" aria-hidden="true" tabindex="-1"></a><span class="ex">290</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">ctx,</span></span>
<span id="cb7-831"><a href="#cb7-831" aria-hidden="true" tabindex="-1"></a><span class="ex">291</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="fu">DrawParam::default()</span></span>
<span id="cb7-832"><a href="#cb7-832" aria-hidden="true" tabindex="-1"></a><span class="ex">292</span> <span class="kw">|</span> <span class="kw">|</span>             <span class="ex">.offset</span><span class="er">(</span><span class="ex">Point2::new</span><span class="er">(</span><span class="ex">0.5,</span> 0.5<span class="kw">))</span></span>
<span id="cb7-833"><a href="#cb7-833" aria-hidden="true" tabindex="-1"></a><span class="ex">293</span> <span class="kw">|</span> <span class="kw">|</span>             <span class="ex">.dest</span><span class="er">(</span><span class="ex">Point2::new</span><span class="er">(</span><span class="ex">game.player.pos.0,</span> game.player.pos.1<span class="kw">))</span></span>
<span id="cb7-834"><a href="#cb7-834" aria-hidden="true" tabindex="-1"></a><span class="ex">294</span> <span class="kw">|</span> <span class="kw">|</span>             <span class="ex">.rotation</span><span class="er">(</span><span class="ex">FRAC_PI_2</span><span class="kw">)</span><span class="ex">,</span></span>
<span id="cb7-835"><a href="#cb7-835" aria-hidden="true" tabindex="-1"></a><span class="ex">295</span> <span class="kw">|</span> <span class="kw">|</span>     <span class="kw">)</span></span>
<span id="cb7-836"><a href="#cb7-836" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span> <span class="kw">|</span><span class="ex">_____^</span> expected <span class="kw">`</span><span class="ex">Result</span><span class="op">&lt;()</span>, GameError<span class="op">&gt;</span><span class="kw">`</span>, found <span class="kw">`()`</span></span>
<span id="cb7-837"><a href="#cb7-837" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-838"><a href="#cb7-838" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> note:   expected enum <span class="kw">`</span><span class="ex">Result</span><span class="op">&lt;()</span>, GameError<span class="op">&gt;</span><span class="kw">`</span></span>
<span id="cb7-839"><a href="#cb7-839" aria-hidden="true" tabindex="-1"></a>            <span class="ex">found</span> unit type <span class="kw">`()`</span></span>
<span id="cb7-840"><a href="#cb7-840" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> try adding an expression at the end of the block</span>
<span id="cb7-841"><a href="#cb7-841" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-842"><a href="#cb7-842" aria-hidden="true" tabindex="-1"></a><span class="ex">295</span> ~     <span class="kw">);</span></span>
<span id="cb7-843"><a href="#cb7-843" aria-hidden="true" tabindex="-1"></a><span class="ex">296</span> +     Ok<span class="er">(</span><span class="kw">())</span></span>
<span id="cb7-844"><a href="#cb7-844" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-845"><a href="#cb7-845" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-846"><a href="#cb7-846" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0308<span class="op">]</span><span class="ex">:</span> mismatched types</span>
<span id="cb7-847"><a href="#cb7-847" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:301:9</span>
<span id="cb7-848"><a href="#cb7-848" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-849"><a href="#cb7-849" aria-hidden="true" tabindex="-1"></a><span class="ex">300</span> <span class="kw">|</span>     <span class="ex">text.draw</span><span class="er">(</span></span>
<span id="cb7-850"><a href="#cb7-850" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>          <span class="ex">----</span> arguments to this method are incorrect</span>
<span id="cb7-851"><a href="#cb7-851" aria-hidden="true" tabindex="-1"></a><span class="ex">301</span> <span class="kw">|</span>         <span class="ex">ctx,</span></span>
<span id="cb7-852"><a href="#cb7-852" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>         <span class="ex">^^^</span> expected <span class="kw">`&amp;</span><span class="ex">mut</span> Canvas<span class="kw">`</span>, found <span class="kw">`&amp;</span><span class="ex">mut</span> Context<span class="kw">`</span></span>
<span id="cb7-853"><a href="#cb7-853" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-854"><a href="#cb7-854" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> note: expected mutable reference <span class="kw">`&amp;</span><span class="ex">mut</span> Canvas<span class="kw">`</span></span>
<span id="cb7-855"><a href="#cb7-855" aria-hidden="true" tabindex="-1"></a>               <span class="ex">found</span> mutable reference <span class="kw">`&amp;</span><span class="ex">mut</span> ggez::Context<span class="kw">`</span></span>
<span id="cb7-856"><a href="#cb7-856" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> method defined here</span>
<span id="cb7-857"><a href="#cb7-857" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/graphics/draw.rs:293:8</span>
<span id="cb7-858"><a href="#cb7-858" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-859"><a href="#cb7-859" aria-hidden="true" tabindex="-1"></a><span class="ex">293</span> <span class="kw">|</span>     <span class="ex">fn</span> draw<span class="er">(</span><span class="kw">&amp;</span><span class="ex">self,</span> canvas: <span class="kw">&amp;</span><span class="ex">mut</span> Canvas, param: impl Into<span class="op">&lt;</span>DrawParam<span class="op">&gt;</span><span class="kw">);</span></span>
<span id="cb7-860"><a href="#cb7-860" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>        <span class="ex">^^^^</span></span>
<span id="cb7-861"><a href="#cb7-861" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-862"><a href="#cb7-862" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0277<span class="op">]</span><span class="ex">:</span> the <span class="kw">`</span><span class="ex">?</span><span class="kw">`</span> operator can only be applied to values that implement <span class="kw">`</span><span class="ex">Try</span><span class="kw">`</span></span>
<span id="cb7-863"><a href="#cb7-863" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:300:5</span>
<span id="cb7-864"><a href="#cb7-864" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-865"><a href="#cb7-865" aria-hidden="true" tabindex="-1"></a><span class="ex">300</span> <span class="kw">|</span> <span class="ex">/</span>     text.draw<span class="er">(</span></span>
<span id="cb7-866"><a href="#cb7-866" aria-hidden="true" tabindex="-1"></a><span class="ex">301</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="ex">ctx,</span></span>
<span id="cb7-867"><a href="#cb7-867" aria-hidden="true" tabindex="-1"></a><span class="ex">302</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="fu">DrawParam::default()</span><span class="ex">.dest</span><span class="er">(</span><span class="ex">Point2::new</span><span class="er">(</span></span>
<span id="cb7-868"><a href="#cb7-868" aria-hidden="true" tabindex="-1"></a><span class="ex">303</span> <span class="kw">|</span> <span class="kw">|</span>             <span class="ex">game.screen_size.0</span> as f32 / 2.0,</span>
<span id="cb7-869"><a href="#cb7-869" aria-hidden="true" tabindex="-1"></a><span class="ex">304</span> <span class="kw">|</span> <span class="kw">|</span>             <span class="ex">game.screen_size.1</span> as f32 / 2.0,</span>
<span id="cb7-870"><a href="#cb7-870" aria-hidden="true" tabindex="-1"></a><span class="ex">305</span> <span class="kw">|</span> <span class="kw">|</span>         <span class="kw">))</span><span class="ex">,</span></span>
<span id="cb7-871"><a href="#cb7-871" aria-hidden="true" tabindex="-1"></a><span class="ex">306</span> <span class="kw">|</span> <span class="kw">|</span>     <span class="kw">)</span><span class="ex">?</span><span class="kw">;</span></span>
<span id="cb7-872"><a href="#cb7-872" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span> <span class="kw">|</span><span class="ex">______^</span> the <span class="kw">`</span><span class="ex">?</span><span class="kw">`</span> operator cannot be applied to type <span class="kw">`()`</span></span>
<span id="cb7-873"><a href="#cb7-873" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-874"><a href="#cb7-874" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> help: the trait <span class="kw">`</span><span class="ex">Try</span><span class="kw">`</span> is not implemented for <span class="kw">`()`</span></span>
<span id="cb7-875"><a href="#cb7-875" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-876"><a href="#cb7-876" aria-hidden="true" tabindex="-1"></a><span class="va">error</span><span class="op">[</span>E0277<span class="op">]</span><span class="ex">:</span> the trait bound <span class="kw">`&amp;</span><span class="ex">mut</span> Game: EventHandler<span class="op">&lt;</span>_<span class="op">&gt;</span><span class="kw">`</span> is not satisfied</span>
<span id="cb7-877"><a href="#cb7-877" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:375:43</span>
<span id="cb7-878"><a href="#cb7-878" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-879"><a href="#cb7-879" aria-hidden="true" tabindex="-1"></a><span class="ex">375</span> <span class="kw">|</span>     <span class="ex">event::run</span><span class="er">(</span><span class="kw">&amp;</span><span class="ex">mut</span> ctx, <span class="kw">&amp;</span><span class="ex">mut</span> event_loop, <span class="kw">&amp;</span><span class="ex">mut</span> my_game<span class="kw">)</span><span class="ex">?</span><span class="kw">;</span></span>
<span id="cb7-880"><a href="#cb7-880" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>     <span class="ex">----------</span>                            ^^^^^^^^^^^^ the trait <span class="kw">`</span><span class="ex">EventHandler</span><span class="op">&lt;</span>_<span class="op">&gt;</span><span class="kw">`</span> is not implemented for <span class="kw">`&amp;</span><span class="ex">mut</span> Game<span class="kw">`</span></span>
<span id="cb7-881"><a href="#cb7-881" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>     <span class="kw">|</span></span>
<span id="cb7-882"><a href="#cb7-882" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>     <span class="ex">required</span> by a bound introduced by this call</span>
<span id="cb7-883"><a href="#cb7-883" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-884"><a href="#cb7-884" aria-hidden="true" tabindex="-1"></a><span class="ex">note:</span> required by a bound in <span class="kw">`</span><span class="ex">run</span><span class="kw">`</span></span>
<span id="cb7-885"><a href="#cb7-885" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/event.rs:283:8</span>
<span id="cb7-886"><a href="#cb7-886" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-887"><a href="#cb7-887" aria-hidden="true" tabindex="-1"></a><span class="ex">281</span> <span class="kw">|</span> <span class="ex">pub</span> fn run<span class="op">&lt;</span>S: <span class="st">&#39;static, E&gt;(mut ctx: Context, event_loop: EventLoop&lt;()&gt;, mut state: S) -&gt; !</span></span>
<span id="cb7-888"><a href="#cb7-888" aria-hidden="true" tabindex="-1"></a><span class="st">    |        --- required by a bound in this function</span></span>
<span id="cb7-889"><a href="#cb7-889" aria-hidden="true" tabindex="-1"></a><span class="st">282 | where</span></span>
<span id="cb7-890"><a href="#cb7-890" aria-hidden="true" tabindex="-1"></a><span class="st">283 |     S: EventHandler&lt;E&gt;,</span></span>
<span id="cb7-891"><a href="#cb7-891" aria-hidden="true" tabindex="-1"></a><span class="st">    |        ^^^^^^^^^^^^^^^ required by this bound in `run`</span></span>
<span id="cb7-892"><a href="#cb7-892" aria-hidden="true" tabindex="-1"></a><span class="st">help: consider removing the leading `&amp;`-reference</span></span>
<span id="cb7-893"><a href="#cb7-893" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-894"><a href="#cb7-894" aria-hidden="true" tabindex="-1"></a><span class="st">375 -     event::run(&amp;mut ctx, &amp;mut event_loop, &amp;mut my_game)?;</span></span>
<span id="cb7-895"><a href="#cb7-895" aria-hidden="true" tabindex="-1"></a><span class="st">375 +     event::run(&amp;mut ctx, &amp;mut event_loop, my_game)?;</span></span>
<span id="cb7-896"><a href="#cb7-896" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-897"><a href="#cb7-897" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-898"><a href="#cb7-898" aria-hidden="true" tabindex="-1"></a><span class="st">error[E0308]: arguments to this function are incorrect</span></span>
<span id="cb7-899"><a href="#cb7-899" aria-hidden="true" tabindex="-1"></a><span class="st">   --&gt; src/main.rs:375:5</span></span>
<span id="cb7-900"><a href="#cb7-900" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-901"><a href="#cb7-901" aria-hidden="true" tabindex="-1"></a><span class="st">375 |     event::run(&amp;mut ctx, &amp;mut event_loop, &amp;mut my_game)?;</span></span>
<span id="cb7-902"><a href="#cb7-902" aria-hidden="true" tabindex="-1"></a><span class="st">    |     ^^^^^^^^^^ -------- expected `Context`, found `&amp;mut Context`</span></span>
<span id="cb7-903"><a href="#cb7-903" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-904"><a href="#cb7-904" aria-hidden="true" tabindex="-1"></a><span class="st">note: expected `EventLoop&lt;()&gt;`, found `&amp;mut EventLoop&lt;()&gt;`</span></span>
<span id="cb7-905"><a href="#cb7-905" aria-hidden="true" tabindex="-1"></a><span class="st">   --&gt; src/main.rs:375:26</span></span>
<span id="cb7-906"><a href="#cb7-906" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-907"><a href="#cb7-907" aria-hidden="true" tabindex="-1"></a><span class="st">375 |     event::run(&amp;mut ctx, &amp;mut event_loop, &amp;mut my_game)?;</span></span>
<span id="cb7-908"><a href="#cb7-908" aria-hidden="true" tabindex="-1"></a><span class="st">    |                          ^^^^^^^^^^^^^^^</span></span>
<span id="cb7-909"><a href="#cb7-909" aria-hidden="true" tabindex="-1"></a><span class="st">    = note:         expected struct `EventLoop&lt;_&gt;`</span></span>
<span id="cb7-910"><a href="#cb7-910" aria-hidden="true" tabindex="-1"></a><span class="st">            found mutable reference `&amp;mut EventLoop&lt;_&gt;`</span></span>
<span id="cb7-911"><a href="#cb7-911" aria-hidden="true" tabindex="-1"></a><span class="st">note: function defined here</span></span>
<span id="cb7-912"><a href="#cb7-912" aria-hidden="true" tabindex="-1"></a><span class="st">   --&gt; /Users/emccue/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ggez-0.9.3/src/event.rs:281:8</span></span>
<span id="cb7-913"><a href="#cb7-913" aria-hidden="true" tabindex="-1"></a><span class="st">    |</span></span>
<span id="cb7-914"><a href="#cb7-914" aria-hidden="true" tabindex="-1"></a><span class="st">281 | pub fn run&lt;S: &#39;</span>static, E<span class="op">&gt;(</span><span class="ex">mut</span> ctx: Context, event_loop: EventLoop<span class="op">&lt;()&gt;</span>, mut state: S<span class="op">)</span> <span class="at">-</span><span class="op">&gt;</span> !</span>
<span id="cb7-915"><a href="#cb7-915" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>        <span class="ex">^^^</span></span>
<span id="cb7-916"><a href="#cb7-916" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> consider removing the borrow</span>
<span id="cb7-917"><a href="#cb7-917" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-918"><a href="#cb7-918" aria-hidden="true" tabindex="-1"></a><span class="ex">375</span> <span class="at">-</span>     event::run<span class="er">(</span><span class="kw">&amp;</span><span class="ex">mut</span> ctx, <span class="kw">&amp;</span><span class="ex">mut</span> event_loop, <span class="kw">&amp;</span><span class="ex">mut</span> my_game<span class="kw">)</span><span class="ex">?</span><span class="kw">;</span></span>
<span id="cb7-919"><a href="#cb7-919" aria-hidden="true" tabindex="-1"></a><span class="ex">375</span> +     event::run<span class="er">(</span><span class="ex">ctx,</span> <span class="kw">&amp;</span><span class="ex">mut</span> event_loop, <span class="kw">&amp;</span><span class="ex">mut</span> my_game<span class="kw">)</span><span class="ex">?</span><span class="kw">;</span></span>
<span id="cb7-920"><a href="#cb7-920" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-921"><a href="#cb7-921" aria-hidden="true" tabindex="-1"></a><span class="ex">help:</span> consider removing the borrow</span>
<span id="cb7-922"><a href="#cb7-922" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-923"><a href="#cb7-923" aria-hidden="true" tabindex="-1"></a><span class="ex">375</span> <span class="at">-</span>     event::run<span class="er">(</span><span class="kw">&amp;</span><span class="ex">mut</span> ctx, <span class="kw">&amp;</span><span class="ex">mut</span> event_loop, <span class="kw">&amp;</span><span class="ex">mut</span> my_game<span class="kw">)</span><span class="ex">?</span><span class="kw">;</span></span>
<span id="cb7-924"><a href="#cb7-924" aria-hidden="true" tabindex="-1"></a><span class="ex">375</span> +     event::run<span class="er">(</span><span class="kw">&amp;</span><span class="ex">mut</span> ctx, event_loop, <span class="kw">&amp;</span><span class="ex">mut</span> my_game<span class="kw">)</span><span class="ex">?</span><span class="kw">;</span></span>
<span id="cb7-925"><a href="#cb7-925" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-926"><a href="#cb7-926" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-927"><a href="#cb7-927" aria-hidden="true" tabindex="-1"></a><span class="ex">warning:</span> unreachable call</span>
<span id="cb7-928"><a href="#cb7-928" aria-hidden="true" tabindex="-1"></a>   <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:375:5</span>
<span id="cb7-929"><a href="#cb7-929" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-930"><a href="#cb7-930" aria-hidden="true" tabindex="-1"></a><span class="ex">375</span> <span class="kw">|</span>     <span class="ex">event::run</span><span class="er">(</span><span class="kw">&amp;</span><span class="ex">mut</span> ctx, <span class="kw">&amp;</span><span class="ex">mut</span> event_loop, <span class="kw">&amp;</span><span class="ex">mut</span> my_game<span class="kw">)</span><span class="ex">?</span><span class="kw">;</span></span>
<span id="cb7-931"><a href="#cb7-931" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>     <span class="ex">---------------------------------------------------^</span></span>
<span id="cb7-932"><a href="#cb7-932" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>     <span class="kw">|</span></span>
<span id="cb7-933"><a href="#cb7-933" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>     <span class="ex">unreachable</span> call</span>
<span id="cb7-934"><a href="#cb7-934" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span>     <span class="ex">any</span> code following this expression is unreachable</span>
<span id="cb7-935"><a href="#cb7-935" aria-hidden="true" tabindex="-1"></a>    <span class="kw">|</span></span>
<span id="cb7-936"><a href="#cb7-936" aria-hidden="true" tabindex="-1"></a>    <span class="ex">=</span> note: <span class="kw">`</span><span class="co">#[warn(unreachable_code)]</span><span class="kw">`</span> on by default</span>
<span id="cb7-937"><a href="#cb7-937" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-938"><a href="#cb7-938" aria-hidden="true" tabindex="-1"></a><span class="ex">warning:</span> unused import: <span class="kw">`</span><span class="ex">BulletFactory</span><span class="kw">`</span></span>
<span id="cb7-939"><a href="#cb7-939" aria-hidden="true" tabindex="-1"></a>  <span class="ex">--</span><span class="op">&gt;</span> src/main.rs:26:29</span>
<span id="cb7-940"><a href="#cb7-940" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span></span>
<span id="cb7-941"><a href="#cb7-941" aria-hidden="true" tabindex="-1"></a><span class="ex">26</span> <span class="kw">|</span> <span class="ex">use</span> crate::bullet::{Bullet, BulletFactory, BulletFactoryImpl}<span class="kw">;</span></span>
<span id="cb7-942"><a href="#cb7-942" aria-hidden="true" tabindex="-1"></a>   <span class="kw">|</span>                             <span class="ex">^^^^^^^^^^^^^</span></span>
<span id="cb7-943"><a href="#cb7-943" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-944"><a href="#cb7-944" aria-hidden="true" tabindex="-1"></a><span class="ex">Some</span> errors have detailed explanations: E0050, E0053, E0061, E0277, E0308, E0425, E0432, E0603, E0609...</span>
<span id="cb7-945"><a href="#cb7-945" aria-hidden="true" tabindex="-1"></a><span class="ex">For</span> more information about an error, try <span class="kw">`</span><span class="ex">rustc</span> <span class="at">--explain</span> E0050<span class="kw">`</span>.</span>
<span id="cb7-946"><a href="#cb7-946" aria-hidden="true" tabindex="-1"></a><span class="ex">warning:</span> <span class="kw">`</span><span class="ex">rustisbetter</span><span class="kw">`</span> <span class="er">(</span><span class="ex">bin</span> <span class="st">&quot;rustisbetter&quot;</span><span class="kw">)</span> <span class="ex">generated</span> 11 warnings</span>
<span id="cb7-947"><a href="#cb7-947" aria-hidden="true" tabindex="-1"></a><span class="ex">error:</span> could not compile <span class="kw">`</span><span class="ex">rustisbetter</span><span class="kw">`</span> <span class="er">(</span><span class="ex">bin</span> <span class="st">&quot;rustisbetter&quot;</span><span class="kw">)</span> <span class="ex">due</span> to 61 previous errors<span class="kw">;</span> <span class="ex">11</span> warnings emitted</span></code></pre></div>
<p>Guess they really took <a href="https://0ver.org/">ZeroVer</a> to heart, huh?</p>
<p>So as it stands I have no clue how to run this Rust project on my Laptop.</p>
<ol type="1">
<li>If you have a clue, let me know.</li>
<li>Why did this Rust project bit-rot? Actually curious.</li>
<li>Is this representative of what will happen to any Rust project I make?</li>
</ol>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Rust Just Failed an Important Test</title><link>https://mccue.dev/pages/7-31-24-rust-just-failed-its-test</link><description></description><pubDate>Wed, 31 Jul 0024 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Rust Just Failed an Important Test</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Rust Just Failed an Important Test</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
I have two Rust projects I maintain.

<p>The first is a parser for the <a href="https://github.com/bowbahdoe/edn-format">EDN Data Format</a>. I haven't had to touch that one in a while. Best I can tell it's all still working.</p>
<p>The second is a fork of the Rust Playground for <a href="https://run.mccue.dev/">running Java code</a>. I also haven't had to touch that one in a while, but I did today to update the versions of Java available and include updated early access builds.</p>
<p>When I did that, despite having not changed any dependencies, I got a build error in CI/CD. Build log is <a href="https://github.com/bowbahdoe/run-java-code/actions/runs/10181544029/job/28161965425">here</a> if anyone wants to see.</p>
<pre><code>   Compiling io-lifetimes v1.0.11
   Compiling doc-comment v0.3.3
   Compiling smallvec v1.10.0
   Compiling pin-project v1.1.0
   Compiling miniz_oxide v0.6.2
   Compiling time v0.3.22
error[E0282]: type annotations needed for `Box&lt;_&gt;`
  --&gt; /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/time-0.3.22/src/format_description/parse/mod.rs:83:9
   |
83 |     let items = format_items
   |         ^^^^^
...
86 |     Ok(items.into())
   |              ---- type must be known at this point
   |
help: consider giving `items` an explicit type, where the placeholders `_` are specified
   |
83 |     let items: Box&lt;_&gt; = format_items
   |              ++++++++

For more information about this error, try `rustc --explain E0282`.</code></pre>
<p>And just like that, I've lost trust in Rust's resiliency to bit-rot.</p>
<p>It's not that deep an error and I resolved it by pinning a higher version of the time library, but it still sucks.</p>
<p>To me, whether code will "just work" into the future is an important property of a language and ecosystem. Maybe I had inflated expectations because of Rust editions, and maybe I'm being too harsh, but I now have this feeling of unease that I didn't before.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>You can run Java like Python now</title><link>https://mccue.dev/pages/7-27-24-you-can-run-java-like-python-or-ruby</link><description></description><pubDate>Sat, 27 Jul 0024 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>You can run Java like Python now</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">You can run Java like Python now</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
This is meant to be a brief PSA for the programming general public.
All this is known to the people following Java closely, but I figure most are not.

<p>As of Java 22, you can run Java code like you would an interpreted language such as Python, Ruby, JavaScript, etc. This means that ahead-of-time compilation is no longer strictly required.</p>
<p>Say you have the following files.</p>
<p><code>src/Main.java</code></p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>Example<span class="op">.</span><span class="fu">text</span><span class="op">());</span>    </span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><code>src/Example.java</code></p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Example <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="bu">String</span> <span class="fu">text</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="st">&quot;example&quot;</span><span class="op">;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>You can directly run this project with <code>java src/Main.java</code>.</p>
<p>This is very new. The Java ecosystem doesn't yet have an accepted equivalent of <code>pip</code> or <code>npm</code> that isn't also tied to a build tool. Now that a build tool isn't required I figure that will come around soon enough.<sup><a href="#1">1</a></sup></p>
<p>As a sidenote, <code>public static void main(String[] args)</code> and <code>System.out.println</code> are also no longer going to be needed. Stay tuned.</p>
<p id="1" style="font-size: 14px">1: There are two tools that most closely fit the mould today. The first is
<a href="https://get-coursier.io/">Coursier</a>, a tool that has been around in the Scala community for a while.
The second is <a href="https://github.com/bowbahdoe/jresolve-cli">jresolve</a>, 
a tool I produced that has a few bugs and missing features, but that I think could be a better fit 
with more time and polish.</p>

<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>After CrowdStrike, Programmers Deserve Consequences.</title><link>https://mccue.dev/pages/7-20-24-programmers-deserve-consequences</link><description></description><pubDate>Sat, 20 Jul 0024 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>After CrowdStrike, Programmers Deserve Consequences.</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">After CrowdStrike, Programmers Deserve Consequences.</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
An Anesthesiologist can expect a salary of over $300k. This is because putting you to sleep
for surgery is actually kinda risky. If they do their job wrong you die. Their salary reflects
the fact that they take on much of the liability for that.

<p>When a Structural Engineer finishes a design, they sign off on it. If something goes wrong with that structure due to their negligence, and it kills someone, that engineer might be on the hook for manslaughter.</p>
<p>Yesterday a friend of mine was stuck in the Hospital all day. Their computer system went down and that led to a delay of care. Delays in care <a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC1955366/">kill people</a>.</p>
<p>All over the world Hospitals, Airlines, Banks, etc. - critical infrastructure - was taken down by a bad patch in some random bit of software. This time it was CrowdStrike but let's be a hundred percent fucking real with ourselves it could have been anything.</p>
<p>It's an open secret that the entire software development field is a bit of a clusterfuck. Attempts to impose standards and restrictions largely fail. It is diminishingly rare to finish a project on budget, on time, and without defects. The education software developers receive is often woefully inadequate. The space is flooded with grifters, conpersons, imbeciles, and fanatics. We idolize and pray to emulate success stories like Facebook (a grand machine which reminds me of birthdays and drives teenagers to suicide.) It's just bad, man.</p>
<p>Software "Engineers" are never held personally accountable for the effects their actions have on the world. That poor bastard or bastard(s) at CrowdStrike weren't paid anesthesiologist rates and yet their mistake is going to kill a lot of people. I doubt they would have signed off on anything they'd done in the last decade as being "defect-free" and yet that is the standard we rightfully hold other fields to.</p>
<p>Something needs to change and I doubt anything other than real, uniformly applied, consequences will make a difference.</p>
<p>For a more intelligently spoken, less emotionally driven, take on this watch <a href="https://www.youtube.com/watch?v=r_U9YFPWxEE">the David Sankel talk I embedded below</a>.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/r_U9YFPWxEE?si=taTljOaqpZxYk-wy" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

<h2 id="edit">EDIT</h2>
<p>To clarify, I am not saying that an individual at the bottom of the chain of decision-making is materially responsible for this outage.</p>
<p>Based on the degree to which what was in my head was received as almost the opposite message by so many, I am pretty sure I wrote this poorly.</p>
<p>I think <a href="https://www.reddit.com/r/programming/comments/1e8ipxf/comment/le7mz8w/">this reddit comment</a> did a good job distilling something I wish I got across.</p>
<blockquote>
<p>The reason why anethesiologists and structural engineers can take responsibility for their work is because they are legally responsible for the consequences of their actions, specifically of things within their individual control. They are members of regulated, professional credentialing organisations (i.e., only a licensed 'professional engineer' can sign off certain things; only a board-certified anethesiologist can perform on patients.) It has nothing to do with 'respect'.</p>
<p>Software developers as individuals should not be scapegoated in this Crowdstrike situation specifically because they are not licensed, there are no legal standards to be met for the title or the role, and therefore they are the 'peasants' (as the author calls them) who must do as they are told by the business.</p>
</blockquote>
<p>And also <a href="https://www.reddit.com/r/programming/comments/1e8ipxf/comment/le8ef4c/?context=3">this post I wrote</a> and <a href="https://www.reddit.com/r/programming/comments/1e8ipxf/comment/le8ef4c/?context=3">this one a reply down</a> are at least a little clearer on where I think the <em>blame</em> lies for this particular outage.</p>
<blockquote>
<p>I am not and wish I never came so close to implying that in this exact instance we should blame a coder for what was clearly a process issue.</p>
<p>It's just that even though we all know that not unit testing or performing QA is negligent behavior our field doesn't actually have any codes that are enforced by law.</p>
<p>The reason I implied that programmers should see consequences isn't because I misunderstood how development works or that CrowdStrike was largely caused by chains of terrible management. It's because without any codes similar to those fields we will never be taken seriously. My thought process was "if it matters, we will make codes. If we make codes then maybe we edge closer to being an actual engineering discipline."</p>
<p>And seriously watch the video I linked. It did a way less shitty job than I did.</p>
</blockquote>
<hr />
<blockquote>
<p>Yeah I'm a demonstrably bad communicator.</p>
<p>I agree with everything you are saying and i think we agree on what they shape of things should be.</p>
<p>But I think without actual codes that you can hold someone to there is no basis upon which to punish a company for not following them.</p>
<p>Skipping past how we get from here to there, in a world where development of critical systems is regulated and folks are licensed as engineers there should be consequences if one of those licensed engineers is negligent.</p>
<p>But I fucked up hard by just saying programmers deserve consequences. People assumed I meant "yeah let's get the guy who did this!" I really mean "programmers deserve to live in the world where their actions are given weight and recognized as an engineering discipline with consequences for negligence all the way up the chain."</p>
</blockquote>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>A Dramatic Reading: I Will Fucking Piledrive You If You Mention AI Again</title><link>https://mccue.dev/pages/7-5-24-a-reading-i-will-fucking-piledrive-you-if-you-mention-ai-again</link><description></description><pubDate>Fri, 05 Jul 0024 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>A Dramatic Reading: I Will Fucking Piledrive You If You Mention AI Again</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">A Dramatic Reading: I Will Fucking Piledrive You If You Mention AI Again</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 

<p>I thoroughly enjoyed reading <a href="https://ludic.mataroa.blog/blog/i-will-fucking-piledrive-you-if-you-mention-ai-again/">this blog post entitled "I Will Fucking Piledrive You If You Mention AI Again"</a> on the <a href="https://ludic.mataroa.blog/">Lucidity blog.</a></p>
<p>I choose to hope that it is a sign that professional developers, as a group, have a developed at least a few anti-BS antibodies following the crypto bubble popping.</p>
<p>I also think that the approach it takes is probably one of the most socially effective ones. More effective than the "well, maybe there is <em>some</em> application of the technology" tepidness that allowed for crypto scams to flourish unfettered and lure in impressionable new coders.</p>
<p>So in the spirit of keeping the "you're not welcome here" message alive in the news cycle, I commissioned a professional voice actor to give a full dramatic reading of that blog post.<sup><a href="#1">1</a></sup></p>
<p>Enjoy.</p>
<p><audio controls src="/pages/7-5-24-I-Will-Fucking-Piledrive-You-If-You Mention-AI-Again.mp3"></audio></p>
<p>If you have a project in need of a voice actor, you can find their portfolio <a href="https://ryangaiservo.com/">here</a>.</p>
<p id="1" style="font-size: 14px">1: I obviously do not have any rights to the original blog post
so I can't say "you can use the recording for anything," but I need to make clear that you 
are not allowed to use any aspect of the recording to train a generative AI. Anything else I am able to grant permission
for, I do.</p>

<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Extension methods make code harder to read, actually</title><link>https://mccue.dev/pages/6-22-24-extension-methods-are-harder-to-read</link><description></description><pubDate>Mon, 24 Jun 0024 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Extension methods make code harder to read, actually</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Extension methods make code harder to read, actually</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
I apologize in advance for whatever comment sections form around this.

<h2 id="what-are-instance-methods">What are instance methods?</h2>
<p>In many languages you can associate functions with a type.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Dog <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">bark</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Bark!&quot;</span><span class="op">);</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The name these are given differs on the language you are talking about and who you are talking to, but we'll go forward calling these "instance methods."</p>
<p>Instance methods are defined at the same time as the type is declared.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Dog <span class="op">{</span> <span class="co">// Type declared here</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">bark</span><span class="op">()</span> <span class="op">{</span> <span class="co">// Method declared within it</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Bark!&quot;</span><span class="op">);</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Instance methods can have access to fields or properties of the type they are associated with that might not be accessible to other code.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Dog <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="bu">String</span> name<span class="op">;</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    <span class="fu">Dog</span><span class="op">(</span><span class="bu">String</span> name<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">name</span> <span class="op">=</span> name<span class="op">;</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">bark</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>        <span class="co">// name is accessible to this method, but not to outsiders</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>name<span class="op">.</span><span class="fu">equals</span><span class="op">(</span><span class="st">&quot;Scooby&quot;</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>            <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Scooby-Dooby-Doo!&quot;</span><span class="op">);</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>            <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Bark!&quot;</span><span class="op">);</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And, in languages with the ability to "extend" types, instance methods might be overloaded by a subtype.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Pomeranian <span class="kw">extends</span> Dog <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">bark</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;bork.&quot;</span><span class="op">);</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Importantly instance methods are also "convenient" to call.</p>
<p>Most code editors can catch you after you've written the <code>.</code> after <code>dog</code> and offer an autocomplete list of "methods you might want to call."</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    var dog <span class="op">=</span> <span class="kw">new</span> <span class="fu">Dog</span><span class="op">(</span><span class="st">&quot;Scooby&quot;</span><span class="op">);</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// After &quot;dog.b&quot; you should be able to hit enter and</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">// have &quot;dog.bark()&quot; filled in for you.</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    dog<span class="op">.</span><span class="fu">bark</span><span class="op">();</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>In addition to discovery, this is convenient for a practice known as "chaining." If one method returns an object which can itself have methods called on it you can "chain" another method call on the end.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">String</span> name <span class="op">=</span> <span class="st">&quot;  Scrappy   &quot;</span><span class="op">;</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>    name <span class="op">=</span> name</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">toLowerCase</span><span class="op">()</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">strip</span><span class="op">()</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">concat</span><span class="op">(</span><span class="st">&quot; dappy doo&quot;</span><span class="op">);</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>name<span class="op">);</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This is widely considered to be aesthetically pleasing and will be the surprise villain of today's story.</p>
<h2 id="what-are-extension-methods">What are extension methods?</h2>
<p>If you are not the author of a type, but want to write functionality that builds upon the exposed methods and fields of one, you can write code of your own.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> DogUtils <span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">DogUtils</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">void</span> <span class="fu">playFetch</span><span class="op">(</span>Dog dog<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Throwing stick...&quot;</span><span class="op">);</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>        dog<span class="op">.</span><span class="fu">bark</span><span class="op">();</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Stick retrieved.&quot;</span><span class="op">);</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Calling such a method will generally look different from calling an instance method.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>    var dog <span class="op">=</span> <span class="kw">new</span> <span class="fu">Dog</span><span class="op">(</span><span class="st">&quot;Scooby&quot;</span><span class="op">);</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>    DogUtils<span class="op">.</span><span class="fu">playFetch</span><span class="op">(</span>dog<span class="op">);</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Importantly you need to know where to look for it (in this case that there is <code>playFetch</code> in <code>DogUtils</code>) and won't get that helpful autocomplete from writing <code>dog.</code></p>
<p>Externally defined methods also don't play nicely with method chaining. Whenever you need to call them you probably need to "break the chain."</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">String</span> name <span class="op">=</span> <span class="st">&quot;  SCRAPPY   &quot;</span><span class="op">;</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>    name <span class="op">=</span> name<span class="op">.</span><span class="fu">toLowerCase</span><span class="op">();</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>    name <span class="op">=</span> StringUtils<span class="op">.</span><span class="fu">capitalizeFirstLetter</span><span class="op">(</span>name<span class="op">);</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>    name <span class="op">=</span> name</span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">strip</span><span class="op">()</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">concat</span><span class="op">(</span><span class="st">&quot; Dappy doo&quot;</span><span class="op">);</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>name<span class="op">);</span></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This is considered aesthetically displeasing.</p>
<p>Extension methods are a language feature that allow someone to make calling these externally defined methods look like calling an instance method.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="co">// This is the &quot;manifold&quot; Java superset</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="co">// http://manifold.systems/docs.html</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="at">@Extension</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> DogUtils <span class="op">{</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">DogUtils</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">void</span> <span class="fu">playFetch</span><span class="op">(</span>Dog dog<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Throwing stick...&quot;</span><span class="op">);</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>        dog<span class="op">.</span><span class="fu">bark</span><span class="op">();</span></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Stick retrieved.&quot;</span><span class="op">);</span></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb11"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>    var dog <span class="op">=</span> <span class="kw">new</span> <span class="fu">Dog</span><span class="op">(</span><span class="st">&quot;Scooby&quot;</span><span class="op">);</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>    dog<span class="op">.</span><span class="fu">playFetch</span><span class="op">();</span> <span class="co">// This turns into a call to DogUtils.playFetch</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="upsides-of-extension-methods">Upsides of extension methods</h2>
<p>Because calling an extension method looks the same as calling an instance method, downstream users of a library can make a suboptimal API more tolerable by adding their own methods.</p>
<p>As an example, the Kotlin language uses its extension mechanism to <a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/replace-first-char.html">"add methods" to <code>java.lang.String</code></a> that the Kotlin team would prefer existed.</p>
<p>This can make code more aesthetically pleasing and enables method chains to go unbroken, which in turn can make code easier to write.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">String</span> name <span class="op">=</span> <span class="st">&quot;  SCRAPPY   &quot;</span><span class="op">;</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>    name <span class="op">=</span> name</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">toLowerCase</span><span class="op">()</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">capitalizeFirstLetter</span><span class="op">()</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">strip</span><span class="op">()</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">concat</span><span class="op">(</span><span class="st">&quot; Dappy doo&quot;</span><span class="op">);</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>name<span class="op">);</span></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This is often confused with making code easier to read.</p>
<h2 id="downsides-of-extension-methods">Downsides of extension methods</h2>
<h3 id="1-they-make-life-harder-for-library-maintainers">1. They make life harder for library maintainers</h3>
<p>Java added the <code>.strip()</code> method to <code>String</code> in Java 11. <code>.trim()</code> already existed but it isn't "unicode aware" and won't trim off everything we would consider to be whitespace.</p>
<p>As such, it would have been an ideal target for an extension method.</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="at">@Extension</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="dt">final</span> <span class="kw">class</span> StringUtils <span class="op">{</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">StringUtils</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="bu">String</span> <span class="fu">strip</span><span class="op">(</span><span class="bu">String</span> s<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>So if Java had extension methods there would have certainly been code that looks like this out in the world.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">String</span> catchphrase <span class="op">=</span> <span class="st">&quot;  zoinks  &quot;</span><span class="op">;</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>    catchphrase <span class="op">=</span> catchphrase<span class="op">.</span><span class="fu">strip</span><span class="op">();</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>catchphrase<span class="op">);</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Where every call to <code>.strip()</code> was translated to a call to <code>StringUtils.strip</code>.</p>
<p>Now consider what happens when you go forward in time and the person writing <code>String</code> decides to add their own <code>.strip()</code> method.</p>
<p>If you recompile code that looks like the above does it</p>
<ul>
<li>A: Fail to compile. The compiler can't decide which one to use, you need to disambiguate somehow.</li>
<li>B: Continue to use the extension method.</li>
<li>C: Switch to using the instance method.</li>
</ul>
<p>All of these options suck.</p>
<p>If it fails to compile now library authors need to consider how likely it is that adding a brand-new method is going to break downstream code. This is something that, in the absence of extension methods, is one of the few things that is basically a free action.</p>
<p>If it continues to use the extension method that can quickly become a code readability hazard. People form their own internal roladexes of what methods are available on certain types and what they do. If someone sees <code>.strip()</code> called on a <code>String</code> its not unreasonable for them to expect exactly the behavior of <code>String#strip</code>. If the semantics of the <code>strip</code> extension method differ from the semantics of the instance method...shit. Library maintainers need to care about this because any method they add that is likely to conflict with an existing extension method can trigger exactly this hazard.</p>
<p>If it switches to using the instance method now both library authors and library consumers need to be a lot more cautious when upgrading libraries. Code, as written, could change behavior from something as simple as adding a method. This is worse than failing to compile since at least if the compiler yells at you there is a sign that something is wrong.</p>
<h3 id="2-they-make-code-harder-to-read">2. They make code harder to read</h3>
<p>Welcome to the part that was click-bait.</p>
<p>If the invocation of an instance method looks identical to invoking an extension method it is impossible to tell at a glance which is happening.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Is this an extension method call or an instance method one?</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>    <span class="bu">String</span> name <span class="op">=</span> <span class="st">&quot;  Velma&quot;</span><span class="op">.</span><span class="fu">stripLeading</span><span class="op">();</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>If the language automatically brings all extension methods "into scope" this problem is global to the entire codebase. If someone in some corner of the world adds an extension method that can alter the behavior of code or affect whether a particular line compiles.</p>
<p>If the language doesn't, that means you need some sort of import to make the extension methods available.</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="co">// If I hadn&#39;t been using this example the whole time, would</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="co">// you catch that &quot;captializeFirstLetter&quot; was the extension method?</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="at">@Extension</span><span class="op">(</span>StringUtils<span class="op">.</span><span class="fu">class</span><span class="op">)</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>        <span class="bu">String</span> name <span class="op">=</span> <span class="st">&quot;  SCRAPPY   &quot;</span><span class="op">;</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>        name <span class="op">=</span> name</span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">toLowerCase</span><span class="op">()</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">capitalizeFirstLetter</span><span class="op">()</span></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">strip</span><span class="op">()</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">concat</span><span class="op">(</span><span class="st">&quot; Dappy doo&quot;</span><span class="op">);</span></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>name<span class="op">);</span></span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This is both a worse and similar situation to <code>*</code> imports. One line of code at the top of the file is needed for many other lines to be valid code, but there is no way to visually tie the two together.</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.*;</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>    var l <span class="op">=</span> <span class="kw">new</span> <span class="bu">ArrayList</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;();</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The problem is that readability is about the ease of extracting information from text. Both <code>*</code> imports and any hypothetical design of extension methods make it harder to read code because they take information that could be written down and accessible and make it implicit.</p>
<p>That can be fine, sometimes. We're not in an anti-golf competition or anything. It is valid to trade readability for ease of writing. But we are lying to ourselves and/or others if we say that extension methods make code more readable.</p>
<p>What they do is make some code more aesthetically pleasing. Method chains are considered nice to look at. Beauty is just simply a different thing from comprehensibility.</p>
<h3 id="3-they-arent-that-powerful-actually">3. They aren't that powerful, actually</h3>
<p>There are more ways than extension methods to magically attach methods to types.</p>
<p>One of the ways that is popular in Scala is to use "implicits." Whenever you use a type in a context that it wouldn't otherwise work, Scala can implicitly wrap your type in another one that will make it work.</p>
<p>What does that mean? Well, if you had a line of code like this.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode scala"><code class="sourceCode scala"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="kw">val</span> name <span class="op">=</span> <span class="st">&quot;fred&quot;</span><span class="op">.</span><span class="fu">capitalizeFirstLetter</span><span class="op">()</span></span></code></pre></div>
<p>Then the Scala compiler will look for implicit conversions to a class that does have that method.</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode scala"><code class="sourceCode scala"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="fu">EnrichedString</span><span class="op">(</span>s<span class="op">:</span> String<span class="op">)</span> <span class="op">{</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">def</span> capitalizeFirstLetter<span class="op">:</span> String <span class="op">=</span> <span class="op">{</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>    Character<span class="op">.</span><span class="fu">toUpperCase</span><span class="op">(</span>s<span class="op">.</span><span class="fu">charAt</span><span class="op">(</span><span class="dv">0</span><span class="op">))</span> <span class="op">+</span> s<span class="op">.</span><span class="fu">substring</span><span class="op">(</span><span class="dv">1</span><span class="op">,</span> s<span class="op">.</span><span class="fu">length</span><span class="op">())</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a>given Conversion<span class="op">[</span>String<span class="op">,</span> EnrichedString<span class="op">]</span> <span class="kw">with</span></span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">def</span> <span class="fu">apply</span><span class="op">(</span>s<span class="op">:</span> String<span class="op">):</span> EnrichedString <span class="op">=</span> <span class="fu">EnrichedString</span><span class="op">(</span>s<span class="op">)</span></span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a><span class="kw">val</span> name <span class="op">=</span> <span class="st">&quot;fred&quot;</span><span class="op">.</span>capitalizeFirstLetter</span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-12"><a href="#cb19-12" aria-hidden="true" tabindex="-1"></a><span class="fu">println</span><span class="op">(</span>name<span class="op">)</span></span></code></pre></div>
<p>This is more powerful since you aren't just able to magically add a method, you can magically implement an interface.</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode scala"><code class="sourceCode scala"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">trait</span> ThingDoer <span class="op">{</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">def</span> doThing<span class="op">:</span> <span class="bu">Unit</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="fu">EnrichedString</span><span class="op">(</span>s<span class="op">:</span> String<span class="op">)</span> <span class="kw">extends</span> ThingDoer <span class="op">{</span></span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">def</span> doThing<span class="op">:</span> <span class="bu">Unit</span> <span class="op">=</span> <span class="op">{</span></span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a>    <span class="fu">println</span><span class="op">(</span><span class="ss">s&quot;</span><span class="st">Hello: </span><span class="ss">${</span>s<span class="ss">}&quot;</span><span class="op">)</span></span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-11"><a href="#cb20-11" aria-hidden="true" tabindex="-1"></a>given Conversion<span class="op">[</span>String<span class="op">,</span> ThingDoer<span class="op">]</span> <span class="kw">with</span></span>
<span id="cb20-12"><a href="#cb20-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">def</span> <span class="fu">apply</span><span class="op">(</span>s<span class="op">:</span> String<span class="op">):</span> ThingDoer <span class="op">=</span> <span class="fu">EnrichedString</span><span class="op">(</span>s<span class="op">)</span></span>
<span id="cb20-13"><a href="#cb20-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-14"><a href="#cb20-14" aria-hidden="true" tabindex="-1"></a><span class="kw">val</span> thingDoer<span class="op">:</span> ThingDoer <span class="op">=</span> <span class="st">&quot;fred&quot;</span></span>
<span id="cb20-15"><a href="#cb20-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-16"><a href="#cb20-16" aria-hidden="true" tabindex="-1"></a>thingDoer<span class="op">.</span>doThing</span></code></pre></div>
<p>Are the rules for this confusing? Extremely.</p>
<blockquote>
<p>Implicit conversions are applied in two situations:</p>
<ol type="1">
<li>If an expression e is of type S, and S does not conform to the expression’s expected type T.</li>
<li>In a selection e.m with e of type S, if the selector m does not denote a member of S (to support Scala-2-style extension methods).</li>
</ol>
<p>In the first case, a conversion c is searched for, which is applicable to e and whose result type conforms to T.</p>
</blockquote>
<p>Preach, sister.</p>
<p>Which is all to say that extension methods are the Weenie Hut Jr. version of implicits. You get all the downsides of context dependent code and pain for library maintainers, but in place of the really cool features (like being external code being able to implement an interface on a type they didn't define) we only get the most vapid benefit.</p>
<p>Method chaining.</p>
<h2 id="alternatives">Alternatives</h2>
<h3 id="1-use-a-box">1. Use a box</h3>
<p>If you are working in a language which doesn't have extension methods, but you feel in your bones a strong desire to chain methods, try making a box.</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">function</span><span class="op">.</span><span class="im">Function</span><span class="op">;</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>record <span class="bu">Box</span><span class="op">&lt;</span>T<span class="op">&gt;(</span>T value<span class="op">)</span> <span class="op">{</span></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">&lt;</span>R<span class="op">&gt;</span> <span class="bu">Box</span><span class="op">&lt;</span>R<span class="op">&gt;</span> <span class="fu">map</span><span class="op">(</span>Function<span class="op">&lt;?</span> <span class="kw">super</span> T<span class="op">,</span> <span class="op">?</span> <span class="kw">extends</span> R<span class="op">&gt;</span> f<span class="op">)</span> <span class="op">{</span></span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="bu">Box</span><span class="op">&lt;&gt;(</span>f<span class="op">.</span><span class="fu">apply</span><span class="op">(</span>value<span class="op">));</span></span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>If you box up the value you want to chain methods on then calling instance methods will actually look the same as externally defined ones.</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">String</span> name <span class="op">=</span> <span class="st">&quot;  SCRAPPY   &quot;</span><span class="op">;</span></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>    name <span class="op">=</span> <span class="kw">new</span> <span class="bu">Box</span><span class="op">&lt;&gt;(</span>name<span class="op">)</span></span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">map</span><span class="op">(</span><span class="bu">String</span><span class="op">::</span>toLowerCase<span class="op">)</span></span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">map</span><span class="op">(</span>StringUtils<span class="op">::</span>capitalizeFirstLetter<span class="op">)</span></span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">map</span><span class="op">(</span><span class="bu">String</span><span class="op">::</span>strip<span class="op">)</span></span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">map</span><span class="op">(</span>s <span class="op">-&gt;</span> s<span class="op">.</span><span class="fu">concat</span><span class="op">(</span><span class="st">&quot; Dappy doo&quot;</span><span class="op">))</span></span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">value</span><span class="op">();</span></span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>name<span class="op">);</span></span>
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Is this better than the code without chaining? Debatable. I lean towards no, but if "fluent chaining" is the goal, this achieves the goal. And, unlike a full-blown language feature, it doesn't affect the lives of those for whom method chaining is not an emotional priority.</p>
<h3 id="extend-the-type">Extend the type</h3>
<p>If the author of a type is okay with you extending it and is ready to consider whatever extensions might exist in the wild when they make new versions of a library, they can make their class open to extension.</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Dog <span class="op">{</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">bark</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Bark!&quot;</span><span class="op">);</span></span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb24"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Dalmatian <span class="kw">extends</span> Dog <span class="op">{</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">playFetch</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Throwing stick...&quot;</span><span class="op">);</span></span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>        dog<span class="op">.</span><span class="fu">bark</span><span class="op">();</span></span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Stick retrieved.&quot;</span><span class="op">);</span></span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Does this have downsides? Yes, most definitely. You cannot subclass <code>String</code> and that's maybe 50-60% of why people want extension methods as a feature.</p>
<p>But its at least a mechanism that a library maintainer has control on whether they opt into.</p>
<h3 id="add-a-uniform-calling-syntax">Add a uniform calling syntax</h3>
<p>Some languages don't have a special syntax for calling methods defined alongside a type. Accordingly, such languages often do not have an equivalent to extension methods.</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode elm"><code class="sourceCode elm"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">String</span><span class="op">.</span><span class="dt">Extra</span></span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a><span class="fu">name</span>: <span class="dt">String</span> </span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a><span class="fu">name</span> <span class="st">&quot;   shaggy  rodgers &quot;</span></span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">|&gt;</span> <span class="dt">String</span><span class="op">.</span><span class="fu">trim</span> <span class="co">-- Defined alongside String</span></span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">|&gt;</span> <span class="dt">String</span><span class="op">.</span><span class="dt">Extra</span><span class="op">.</span><span class="fu">toSentenceCase</span> <span class="co">-- Defined by third party</span></span></code></pre></div>
<p>So one possible path for a language to take would be to appease the method chaining junkies and add a new way to invoke methods that chains with instance methods.</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">String</span> name <span class="op">=</span> <span class="st">&quot;  SCRAPPY   &quot;</span><span class="op">;</span></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a>    name <span class="op">=</span> name</span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">toLowerCase</span><span class="op">()</span></span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a>            <span class="op">|[</span>StringUtils<span class="op">::</span>capitalizeFirstLetter<span class="op">]</span></span>
<span id="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">strip</span><span class="op">()</span></span>
<span id="cb26-8"><a href="#cb26-8" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">concat</span><span class="op">(</span><span class="st">&quot; Dappy doo&quot;</span><span class="op">);</span></span>
<span id="cb26-9"><a href="#cb26-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-10"><a href="#cb26-10" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>name<span class="op">);</span></span>
<span id="cb26-11"><a href="#cb26-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This is <a href="https://github.com/tc39/proposal-pipeline-operator">one of the proposed directions that JavaScript might take</a>. It has its downsides as well, but they are different downsides.</p>
<h3 id="use-default-interface-methods-or-an-equivalent">Use default interface methods (or an equivalent)</h3>
<p>While this doesn't help you add methods to arbitrary types you did not make, you can use interfaces to add methods to things in most languages that have them.</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">function</span><span class="op">.</span><span class="im">Consumer</span><span class="op">;</span></span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a><span class="kw">interface</span> IterableExtended<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="kw">extends</span> <span class="bu">Iterable</span><span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="dt">void</span> <span class="fu">forEachTwice</span><span class="op">(</span>Consumer<span class="op">&lt;?</span> <span class="kw">super</span> T<span class="op">&gt;</span> consumer<span class="op">)</span> <span class="op">{</span></span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">forEach</span><span class="op">(</span>t <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb27-6"><a href="#cb27-6" aria-hidden="true" tabindex="-1"></a>            consumer<span class="op">.</span><span class="fu">accept</span><span class="op">(</span>t<span class="op">);</span></span>
<span id="cb27-7"><a href="#cb27-7" aria-hidden="true" tabindex="-1"></a>            consumer<span class="op">.</span><span class="fu">accept</span><span class="op">(</span>t<span class="op">);</span></span>
<span id="cb27-8"><a href="#cb27-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">});</span></span>
<span id="cb27-9"><a href="#cb27-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb27-10"><a href="#cb27-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb28"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Eight <span class="kw">implements</span> IterableExtended<span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">boolean</span> gotEight <span class="op">=</span> <span class="kw">false</span><span class="op">;</span></span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">boolean</span> <span class="fu">hasNext</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">!</span>gotEight<span class="op">;</span></span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">Integer</span> <span class="fu">next</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a>        gotEight <span class="op">=</span> <span class="kw">true</span><span class="op">;</span></span>
<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="dv">8</span><span class="op">;</span></span>
<span id="cb28-11"><a href="#cb28-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-12"><a href="#cb28-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb29"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>    var eight <span class="op">=</span> <span class="kw">new</span> <span class="fu">Eight</span><span class="op">();</span></span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a>    eight<span class="op">.</span><span class="fu">forEachTwice</span><span class="op">(</span><span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">::</span>println<span class="op">);</span></span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This is <a href="https://stackoverflow.com/questions/29466427/what-was-the-design-consideration-of-not-allowing-use-site-injection-of-extensio">a sort of extension method</a>, it just is a technique that only works at the declaration site, not for arbitrary consumers to add.</p>
<h3 id="deal-with-it">Deal with it.</h3>
<div class="sourceCode" id="cb30"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">String</span> name <span class="op">=</span> <span class="st">&quot;  SCRAPPY   &quot;</span><span class="op">;</span></span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a>    name <span class="op">=</span> name<span class="op">.</span><span class="fu">toLowerCase</span><span class="op">();</span></span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a>    name <span class="op">=</span> StringUtils<span class="op">.</span><span class="fu">capitalizeFirstLetter</span><span class="op">(</span>name<span class="op">);</span></span>
<span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-8"><a href="#cb30-8" aria-hidden="true" tabindex="-1"></a>    name <span class="op">=</span> name</span>
<span id="cb30-9"><a href="#cb30-9" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">strip</span><span class="op">()</span></span>
<span id="cb30-10"><a href="#cb30-10" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">concat</span><span class="op">(</span><span class="st">&quot; Dappy doo&quot;</span><span class="op">);</span></span>
<span id="cb30-11"><a href="#cb30-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-12"><a href="#cb30-12" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>name<span class="op">);</span></span>
<span id="cb30-13"><a href="#cb30-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="conclusion">Conclusion</h2>
<p>It is fine to like extension methods. It is also fine to think they are worth the tradeoffs.</p>
<p>What stinks is that people act like there aren't tradeoffs and that they are purely positive. The sort of vapid "why don't they just add extension methods? Idiots." infects discourse and, while I have no illusions anything I write can stop it, I hope that at least some people now understand why a language might choose to not have them.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Modules Make javac Easy: Part. 2, Dependencies and Tests</title><link>https://mccue.dev/pages/5-30-24-module-libs-and-tests</link><description></description><pubDate>Thu, 30 May 0024 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Modules Make javac Easy: Part. 2, Dependencies and Tests</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Modules Make javac Easy: Part. 2, Dependencies and Tests</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
This is a follow-up to [this post](https://mccue.dev/pages/5-29-24-module-compilation).

<p>The biggest things I left out in the workflow I was describing are how to handle external dependencies and how to run tests.</p>
<p>On the one hand, I feel like I understand how those would work today with the tools that exist. On the other, I'm pretty sure it can be done a little better.</p>
<p>Try to focus on whether the "shape" of the process feels alright to you and less on the specifics of any particular command.</p>
<h2 id="dependencies">Dependencies</h2>
<p>I wrote <a href="https://mccue.dev/pages/1-11-24-cli-flow">a post on this before</a>, but I made a tool called <code>jresolve</code>. It resolves transitive dependencies.<sup><a href="#1">1</a></sup></p>
<p>If you want to get it to follow along you can use this script.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">bash</span> <span class="op">&lt;</span> <span class="op">&lt;(</span><span class="ex">curl</span> <span class="at">-s</span>  https://raw.githubusercontent.com/bowbahdoe/jresolve-cli/main/install<span class="op">)</span></span></code></pre></div>
<p>Or download a <code>.jar</code> from <a href="https://github.com/bowbahdoe/jresolve-cli/releases/tag/v2024.05.26">GitHub Releases</a>.</p>
<p>You can use <code>jresolve</code> to download libraries you want to have into a folder.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ex">jresolve</span> <span class="at">--output-directory</span> libs <span class="dt">\</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    pkg:maven/org.springframework.boot/spring-boot-starter-web@3.3.0</span></code></pre></div>
<p>This will include any transitive dependencies of those libraries.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">jresolve</span> <span class="at">--print-tree</span> <span class="dt">\ </span>            </span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    <span class="ex">pkg:maven/org.springframework.boot/spring-boot-starter-web@3.3.0</span></span></code></pre></div>
<pre><code>org.springframework.boot/spring-boot-starter-web 3.3.0
  . org.springframework.boot/spring-boot-starter 3.3.0
    . org.springframework.boot/spring-boot 3.3.0
      . org.springframework/spring-core 6.1.8
...</code></pre>
<p>The <code>pkg:maven</code> string is available at the top of the page for any artifact on <a href="https://central.sonatype.com/artifact/com.google.guava/guava">Maven Central's Search</a>.</p>
<p>If the list of dependencies gets too long you can put the dependencies you want in a file, say <code>libs.txt</code>.</p>
<pre><code>pkg:maven/com.google.guava/guava@33.2.0-jre
pkg:maven/commons-codec/commons-codec@1.17.0</code></pre>
<p>Then include that file with an <code>@</code> at the end of the command.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ex">jresolve</span> <span class="at">--output-directory</span> libs @libs.txt</span></code></pre></div>
<p>Which puts all your dependencies in one place, easily addable to the module path.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ex">javac</span> <span class="dt">\</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>    <span class="at">-d</span> build/javac <span class="dt">\</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>    <span class="at">--module-path</span> libs <span class="dt">\</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>    <span class="at">--module-source-path</span> <span class="st">&quot;./*/src&quot;</span> <span class="dt">\</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>    <span class="at">--module</span> web.hello</span></code></pre></div>
<div class="sourceCode" id="cb8"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ex">java</span> <span class="at">--module-path</span> libs:build/jar <span class="at">--module</span> web.hello</span></code></pre></div>
<h2 id="running-tests">Running Tests</h2>
<p>JUnit has a command line launcher. It's not <a href="https://github.com/junit-team/junit5/issues/3836">perfect</a> yet and it's not on anything like <a href="https://sdkman.io/">SdkMan</a>, but it is good enough for our purposes.</p>
<p>Add the dependencies you need for the command line launcher and for writing tests to your <code>libs.txt</code>.<sup><a href="#2">2</a></sup></p>
<pre><code>pkg:maven/org.junit.jupiter/junit-jupiter-api@5.10.2
pkg:maven/org.junit.platform/junit-platform-console@1.10.2
pkg:maven/org.junit.jupiter/junit-jupiter-engine@5.10.2</code></pre>
<p>Make a module for your tests. And make it an <code>open</code> module so the test runner can do its magic.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>open module web<span class="op">.</span><span class="fu">hello</span><span class="op">.</span><span class="fu">test</span> <span class="op">{</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>    requires web<span class="op">.</span><span class="fu">hello</span><span class="op">;</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>    requires org<span class="op">.</span><span class="fu">junit</span><span class="op">.</span><span class="fu">jupiter</span><span class="op">.</span><span class="fu">api</span><span class="op">;</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Write a test in this module.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">junit</span><span class="op">.</span><span class="im">jupiter</span><span class="op">.</span><span class="im">api</span><span class="op">.</span><span class="im">Test</span><span class="op">;</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">web</span><span class="op">.</span><span class="im">hello</span><span class="op">.</span><span class="im">HelloController</span><span class="op">;</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">static</span><span class="im"> org</span><span class="op">.</span><span class="im">junit</span><span class="op">.</span><span class="im">jupiter</span><span class="op">.</span><span class="im">api</span><span class="op">.</span><span class="im">Assertions</span><span class="op">.</span><span class="im">assertEquals</span><span class="op">;</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> HelloControllerTest <span class="op">{</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Test</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">getHello</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a>        <span class="fu">assertEquals</span><span class="op">(</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>                <span class="kw">new</span> <span class="fu">HelloController</span><span class="op">().</span><span class="fu">index</span><span class="op">(),</span></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;Greetings from Spring Boot!&quot;</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Then you can launch the test runner like any other code.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ex">java</span> <span class="dt">\</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>    <span class="at">--module-path</span> libs:build/jar <span class="dt">\</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>    <span class="at">--add-modules</span> web.hello.test,web.util.test <span class="dt">\</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>    <span class="at">--module</span> org.junit.platform.console <span class="dt">\</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>    execute <span class="dt">\</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>    <span class="at">--select-module</span> web.hello.test</span></code></pre></div>
<p>Which is a little long - I have hopes in the future I can write something like the following.</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ex">junit</span> <span class="dt">\</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>    execute <span class="dt">\</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>    <span class="at">--module-path</span> libs:build/jar <span class="dt">\</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>    <span class="at">--select-module</span> web.hello.test</span></code></pre></div>
<p>But the basics are that you launch junit, point it at your code, and run tests.</p>
<h2 id="wrap-up">Wrap Up</h2>
<p>While all this is more <em>work</em> than adding a dependency to a <code>pom.xml</code> and running <code>mvn test</code>, I'm not convinced its more complicated or any less powerful.</p>
<p>If anything the fact that doing things this way lets us interact more directly with tools like <code>javac</code> makes it feel more flexible.</p>
<p>I made a repo with this setup using Spring Boot that you can find <a href="https://github.com/bowbahdoe/spring-javac-setup">here</a>. All the commands you would run are in the <code>Justfile</code>. I included all the libraries needed in the repo in case you don't want to install my CLI tool for whatever reason.</p>
<p id="1" style="font-size: 14px">1: Its gauche to pitch your own tool. Especially that one which is admittedly incomplete.
One alternative is <a href="https://get-coursier.io/">Coursier</a>.</p>
<p id="2" style="font-size: 14px">2: I know, I know - dependency scopes. This is a relatively large conversation to have,
but with the module path things that aren't also "in the graph" aren't included. Having test dependencies
in the same `libs` folder as other dependencies isn't as important as with the class path. Yes, making
a docker image with just the dependencies needed for runtime needs scopes / a practice emulating it. I'm working
my way around.</p>

<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Modules Make javac Easy</title><link>https://mccue.dev/pages/5-29-24-module-compilation</link><description></description><pubDate>Wed, 29 May 0024 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Modules Make javac Easy</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Modules Make javac Easy</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
If you use Java modules, using `javac` to compile your code is easy.

<p>I figure this wouldn't be known widely - its not that popular for people to use <code>javac</code> directly these days - but its interesting.</p>
<h2 id="without-modules">Without Modules</h2>
<p><code>javac</code> compiles any files you list in its invocation.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ex">javac</span> <span class="at">-d</span> build src/Main.java src/Other.java</span></code></pre></div>
<p>If the other source files are referenced from the ones you listed, you can use <code>--source-path</code> and <code>javac</code> will find the others.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a> <span class="co"># Will find src/Other.java so long as Main uses it</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="ex">javac</span> <span class="at">-d</span> build <span class="dt">\</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    <span class="at">--source-path</span> src <span class="dt">\</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    src/Main.java</span></code></pre></div>
<p>But, if your source files might not directly reference each other, you need to list every file in your project. That turns into something like this.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">javac</span> <span class="at">-d</span> build <span class="dt">\</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    <span class="va">$(</span><span class="fu">find</span> . <span class="at">-name</span> <span class="st">&quot;*.java&quot;</span> <span class="at">-type</span> f<span class="va">)</span></span></code></pre></div>
<p>Which, while functional, doesn't inspire joy.</p>
<h2 id="with-modules">With Modules</h2>
<p>All of the above methods work, even if you have a <code>module-info.java</code>.</p>
<p>But, if you lay out your code like this</p>
<pre><code>example.mod/
  module-info.java
  example/
    mod/
      A.java
      B.java
      C.java</code></pre>
<p>I.E. with a directory that has the same name as the module within it - then <code>javac</code> can automatically find and compile your code.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ex">javac</span> <span class="dt">\</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="at">-d</span> build <span class="dt">\</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    <span class="at">--module-source-path</span> . <span class="dt">\</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    <span class="at">--module</span> example.mod</span></code></pre></div>
<p>So <code>--module-source-path</code> tells it where to find all the code for a module and <code>--module</code> tells it what module you want to compile.</p>
<p>If you wanted all your code in a <code>src/</code> folder you can do that as well. You just need to tweak the <code>--module-source-path</code> argument.</p>
<pre><code>example.mod/
  src/
    module-info.java
    example/
      mod/
        A.java
        B.java
        C.java</code></pre>
<div class="sourceCode" id="cb7"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ex">javac</span> <span class="dt">\</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>    <span class="at">-d</span> build <span class="dt">\</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>    <span class="at">--module-source-path</span> <span class="st">&quot;./*/src&quot;</span> <span class="dt">\</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>    <span class="at">--module</span> example.mod</span></code></pre></div>
<p>Where this becomes actually pretty cool is if you have more than one module.</p>
<p>Just put all your project's modules on the same level.</p>
<pre><code>example.mod/
  src/
    module-info.java
    example/
      mod/
        A.java
 
other.mod/
  src/
    module-info.java
    other/
      mod/
        B.java</code></pre>
<p>Now <code>javac</code> can compile more than one module at the same time.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="ex">javac</span> <span class="dt">\</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>    <span class="at">-d</span> build <span class="dt">\</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>    <span class="at">--module-source-path</span> <span class="st">&quot;./*/src&quot;</span> <span class="dt">\</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>    <span class="at">--module</span> example.mod,other.mod</span></code></pre></div>
<p>If modules require each other - like if <code>example.mod</code> requires <code>other.mod</code> - then all modules will be compiled automatically.</p>
<h2 id="other-tools">Other Tools</h2>
<p>Once you've laid out your code like this other tools, like <code>javadoc</code>, will also be able to automatically discover code for your modules</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ex">javadoc</span> <span class="dt">\</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>    <span class="at">-d</span> docs <span class="dt">\</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>    <span class="at">--module-source-path</span> <span class="st">&quot;./*/src&quot;</span> <span class="dt">\</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>    <span class="at">--module</span> example.mod,other.mod</span></code></pre></div>
<p>Isn't that neat?</p>
<h2 id="wrap-up">Wrap Up</h2>
<p>This leaves off some crucial bits - like how you would get dependencies or run unit tests - but compare it holistically to setting up a multi-module build in Maven. Or Gradle. Or <a href="https://github.com/rife2/bld">bld</a>. Or whatever.</p>
<p>At least to me this feels way less painful. Worthy of a closer look.</p>
<p>I made a repo with a basic version of this setup <a href="https://github.com/bowbahdoe/javac-modules-demo">here</a>. All the commands you would run are in the <code>Justfile</code>. I also threw in making jars + including resources.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Getting Started with java.sql</title><link>https://mccue.dev/pages/1-17-24-java-sql</link><description></description><pubDate>Wed, 17 Jan 0024 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Getting Started with java.sql</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Getting Started with java.sql</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
I get a lot of questions based on a very common school assignment. 

<p>A student is asked to make a desktop GUI app and, as part of that, connect to and work with a locally hosted MySQL database.</p>
<p>In this setup, presumably due to the same set of circumstances that leads to someone showing MySQL as an option for a locally hosted database (W.T.H. right?), people are shown some downright dangerously wrong ways of working with SQL.</p>
<p>This bit of writing is for me to send as a first message next time this comes up.</p>
<h2 id="what-is-javasql">What is <code>java.sql</code></h2>
<p><code>java.sql</code> is the module that contains the classes needed to connect to SQL databases in Java. We also call this API "JDBC", which stands for Java Database Connectivity.</p>
<p>You don't need to do anything special to get access to this, but if you have a <code>module-info.java</code> file in your program you will need to add a <code>requires java.sql;</code> line to it.</p>
<h2 id="install-your-database-drivers">Install your database drivers.</h2>
<p>Though the mechanisms you use to work with databases come with Java, the code to connect to the specific database you are using will not. This means <a href="https://mccue.dev/pages/1-11-24-cli-flow">you need to include a dependency</a>.</p>
<p>For MySQL, you need to have <a href="https://central.sonatype.com/artifact/com.mysql/mysql-connector-j">the mysql-connector-j library</a>. You should have been shown how to do this by now, but if not reach out.</p>
<p>Other DBs:</p>
<ul>
<li><a href="https://central.sonatype.com/artifact/org.postgresql/postgresql">Postgresql</a></li>
<li><a href="https://central.sonatype.com/artifact/org.xerial/sqlite-jdbc">Sqlite</a></li>
</ul>
<h2 id="get-a-datasource">Get a <code>DataSource</code></h2>
<p>The first thing you want to do is get an object which implements the <a href="https://docs.oracle.com/en/java/javase//21/docs/api/java.sql/javax/sql/DataSource.html"><code>DataSource</code></a> interface.</p>
<p>A <a href="https://docs.oracle.com/en/java/javase//21/docs/api/java.sql/javax/sql/DataSource.html"><code>DataSource</code></a> is an object that can give you a connection to a database.</p>
<p>The exact way to do this varies from database to database, but for MySQL you need to create a <code>new MysqlDataSource()</code>. This is also the step where you should fill in any authentication info like username and password.</p>
<p>Also, only create one of these at the top of your program and pass it to everything else. Do not create a <a href="https://docs.oracle.com/en/java/javase//21/docs/api/java.sql/javax/sql/DataSource.html"><code>DataSource</code></a> every time you want to run a query.</p>
<p>For MySQL this is going to be a <code>MysqlDataSource</code>. For Postgres start with <code>PGSimpleDataSource</code>. For SQLite, <code>SQLiteDataSource</code>.</p>
<p>The exact <code>.set*</code> methods you need to call will be different depending on your db and maybe your deployment situation.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">javax</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">DataSource</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">mysql</span><span class="op">.</span><span class="im">cj</span><span class="op">.</span><span class="im">jdbc</span><span class="op">.</span><span class="im">MysqlDataSource</span><span class="op">;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>        MysqlDataSource db <span class="op">=</span> <span class="kw">new</span> <span class="fu">MysqlDataSource</span><span class="op">();</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setPort</span><span class="op">(</span><span class="dv">3306</span><span class="op">);</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setUser</span><span class="op">(</span><span class="st">&quot;username&quot;</span><span class="op">);</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setPassword</span><span class="op">(</span><span class="st">&quot;password&quot;</span><span class="op">);</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="get-a-connection">Get a <code>Connection</code></h2>
<p>Once you have a <a href="https://docs.oracle.com/en/java/javase//21/docs/api/java.sql/javax/sql/DataSource.html"><code>DataSource</code></a> you can call the <a href="https://docs.oracle.com/en/java/javase//21/docs/api/java.sql/javax/sql/DataSource.html#getConnection()"><code>getConnection</code></a> method to get an active connection to the database.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">mysql</span><span class="op">.</span><span class="im">cj</span><span class="op">.</span><span class="im">jdbc</span><span class="op">.</span><span class="im">MysqlDataSource</span><span class="op">;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">Connection</span><span class="op">;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">javax</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">DataSource</span><span class="op">;</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>        MysqlDataSource db <span class="op">=</span> <span class="kw">new</span> <span class="fu">MysqlDataSource</span><span class="op">();</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setPort</span><span class="op">(</span><span class="dv">3306</span><span class="op">);</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setUser</span><span class="op">(</span><span class="st">&quot;username&quot;</span><span class="op">);</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setPassword</span><span class="op">(</span><span class="st">&quot;password&quot;</span><span class="op">);</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span><span class="bu">Connection</span> conn <span class="op">=</span> db<span class="op">.</span><span class="fu">getConnection</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>            </span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>You will notice that I put the connection inside a <code>try( ... ) {}</code> thing. This is called a <code>try-with-resources</code> and all it does is make sure to call <code>conn.close()</code> after the block is exited, even if an exception happens. Since you want to generally close a connection when you are done with it, this is the way to go.</p>
<p>The alternative is this, which you might have seen on your teacher's slides and the example code you were given. This hasn't been needed since <strong>2011</strong>.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="bu">Connection</span> conn <span class="op">=</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="cf">try</span> <span class="op">{</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    conn <span class="op">=</span> db<span class="op">.</span><span class="fu">getConnection</span><span class="op">();</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Code that might crash</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="cf">finally</span> <span class="op">{</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>conn <span class="op">!=</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>        conn<span class="op">.</span><span class="fu">close</span><span class="op">();</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>While you <em>can</em> re-use connections, I have to ask that you do not store any <a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.sql/java/sql/Connection.html"><code>Connection</code></a> objects in fields. Whenever you need a connection object, get a fresh one from the <a href="https://docs.oracle.com/en/java/javase//21/docs/api/java.sql/javax/sql/DataSource.html"><code>DataSource</code></a>. This might sound inefficient, but trust me its better than the alternatives.</p>
<h2 id="create-a-preparedstatement">Create a <code>PreparedStatement</code></h2>
<p>There are other ways to run queries on your database, but this is the most consistent one.</p>
<p>On a connection object you can call a method named <code>prepareStatement</code> and give it a <code>String</code> containing a SQL Query. This <a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.sql/java/sql/PreparedStatement.html"><code>PreparedStatement</code></a> object also should be set up to automatically close like a <a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.sql/java/sql/Connection.html"><code>Connection</code></a>.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">mysql</span><span class="op">.</span><span class="im">cj</span><span class="op">.</span><span class="im">jdbc</span><span class="op">.</span><span class="im">MysqlDataSource</span><span class="op">;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">Connection</span><span class="op">;</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">PreparedStatement</span><span class="op">;</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">javax</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">DataSource</span><span class="op">;</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>        MysqlDataSource db <span class="op">=</span> <span class="kw">new</span> <span class="fu">MysqlDataSource</span><span class="op">();</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setPort</span><span class="op">(</span><span class="dv">3306</span><span class="op">);</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setUser</span><span class="op">(</span><span class="st">&quot;username&quot;</span><span class="op">);</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setPassword</span><span class="op">(</span><span class="st">&quot;password&quot;</span><span class="op">);</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span><span class="bu">Connection</span> conn <span class="op">=</span> db<span class="op">.</span><span class="fu">getConnection</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>            <span class="cf">try</span> <span class="op">(</span><span class="bu">PreparedStatement</span> stmt <span class="op">=</span> conn<span class="op">.</span><span class="fu">prepareStatement</span><span class="op">(</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;SELECT 1 as number;&quot;</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>            <span class="op">))</span> <span class="op">{</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>                </span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="get-a-resultset">Get a <code>ResultSet</code></h2>
<p>To execute a SQL query that will give you results, you call <a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.sql/java/sql/PreparedStatement.html#executeQuery()"><code>executeQuery</code></a> on a <a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.sql/java/sql/PreparedStatement.html"><code>PreparedStatement</code></a>.</p>
<p>This gives you an object called a <a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.sql/java/sql/ResultSet.html"><code>ResultSet</code></a>. A <a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.sql/java/sql/ResultSet.html"><code>ResultSet</code></a> represents a "cursor" over all the rows that came as results from your queries.</p>
<p>It starts before any rows in the query and each time you call <a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.sql/java/sql/ResultSet.html#next()"><code>next</code></a> it moves to the next row. Once you are at a particular row, you call various <code>.get*</code> methods to access the data in that row.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">mysql</span><span class="op">.</span><span class="im">cj</span><span class="op">.</span><span class="im">jdbc</span><span class="op">.</span><span class="im">MysqlDataSource</span><span class="op">;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">Connection</span><span class="op">;</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">PreparedStatement</span><span class="op">;</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">ResultSet</span><span class="op">;</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">javax</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">DataSource</span><span class="op">;</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>        MysqlDataSource db <span class="op">=</span> <span class="kw">new</span> <span class="fu">MysqlDataSource</span><span class="op">();</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setPort</span><span class="op">(</span><span class="dv">3306</span><span class="op">);</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setUser</span><span class="op">(</span><span class="st">&quot;username&quot;</span><span class="op">);</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setPassword</span><span class="op">(</span><span class="st">&quot;password&quot;</span><span class="op">);</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span><span class="bu">Connection</span> conn <span class="op">=</span> db<span class="op">.</span><span class="fu">getConnection</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a>            <span class="cf">try</span> <span class="op">(</span><span class="bu">PreparedStatement</span> stmt <span class="op">=</span> conn<span class="op">.</span><span class="fu">prepareStatement</span><span class="op">(</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;SELECT 1 as number;&quot;</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a>            <span class="op">))</span> <span class="op">{</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a>                <span class="bu">ResultSet</span> rs <span class="op">=</span> stmt<span class="op">.</span><span class="fu">executeQuery</span><span class="op">();</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a>                rs<span class="op">.</span><span class="fu">next</span><span class="op">();</span></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true" tabindex="-1"></a>                <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>rs<span class="op">.</span><span class="fu">getInt</span><span class="op">(</span><span class="st">&quot;number&quot;</span><span class="op">));</span></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>If you select more than one row, you can use the fact that <code>rs.next()</code> returns <code>false</code> when there are no more rows to loop through them all.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">mysql</span><span class="op">.</span><span class="im">cj</span><span class="op">.</span><span class="im">jdbc</span><span class="op">.</span><span class="im">MysqlDataSource</span><span class="op">;</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">Connection</span><span class="op">;</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">PreparedStatement</span><span class="op">;</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">ResultSet</span><span class="op">;</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">javax</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">DataSource</span><span class="op">;</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>        MysqlDataSource db <span class="op">=</span> <span class="kw">new</span> <span class="fu">MysqlDataSource</span><span class="op">();</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setPort</span><span class="op">(</span><span class="dv">3306</span><span class="op">);</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setUser</span><span class="op">(</span><span class="st">&quot;username&quot;</span><span class="op">);</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setPassword</span><span class="op">(</span><span class="st">&quot;password&quot;</span><span class="op">);</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span><span class="bu">Connection</span> conn <span class="op">=</span> db<span class="op">.</span><span class="fu">getConnection</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a>            <span class="cf">try</span> <span class="op">(</span><span class="bu">PreparedStatement</span> stmt <span class="op">=</span> conn<span class="op">.</span><span class="fu">prepareStatement</span><span class="op">(</span></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;SELECT name FROM person;&quot;</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a>            <span class="op">))</span> <span class="op">{</span></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a>                <span class="bu">ResultSet</span> rs <span class="op">=</span> stmt<span class="op">.</span><span class="fu">executeQuery</span><span class="op">();</span></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a>                <span class="cf">while</span> <span class="op">(</span>rs<span class="op">.</span><span class="fu">next</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>rs<span class="op">.</span><span class="fu">getString</span><span class="op">(</span><span class="st">&quot;name&quot;</span><span class="op">));</span></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb6-26"><a href="#cb6-26" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And if you are unsure if you will even get one row, you can use that fact in a similar way.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">mysql</span><span class="op">.</span><span class="im">cj</span><span class="op">.</span><span class="im">jdbc</span><span class="op">.</span><span class="im">MysqlDataSource</span><span class="op">;</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">Connection</span><span class="op">;</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">PreparedStatement</span><span class="op">;</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">ResultSet</span><span class="op">;</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">javax</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">DataSource</span><span class="op">;</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>        MysqlDataSource db <span class="op">=</span> <span class="kw">new</span> <span class="fu">MysqlDataSource</span><span class="op">();</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setPort</span><span class="op">(</span><span class="dv">3306</span><span class="op">);</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setUser</span><span class="op">(</span><span class="st">&quot;username&quot;</span><span class="op">);</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setPassword</span><span class="op">(</span><span class="st">&quot;password&quot;</span><span class="op">);</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span><span class="bu">Connection</span> conn <span class="op">=</span> db<span class="op">.</span><span class="fu">getConnection</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a>            <span class="cf">try</span> <span class="op">(</span><span class="bu">PreparedStatement</span> stmt <span class="op">=</span> conn<span class="op">.</span><span class="fu">prepareStatement</span><span class="op">(</span></span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;SELECT name FROM person WHERE ssn=&#39;111111111&#39;;&quot;</span></span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true" tabindex="-1"></a>            <span class="op">))</span> <span class="op">{</span></span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true" tabindex="-1"></a>                <span class="bu">ResultSet</span> rs <span class="op">=</span> stmt<span class="op">.</span><span class="fu">executeQuery</span><span class="op">();</span></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true" tabindex="-1"></a>                <span class="cf">if</span> <span class="op">(</span>rs<span class="op">.</span><span class="fu">next</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>rs<span class="op">.</span><span class="fu">getString</span><span class="op">(</span><span class="st">&quot;name&quot;</span><span class="op">));</span></span>
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb7-23"><a href="#cb7-23" aria-hidden="true" tabindex="-1"></a>                <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb7-24"><a href="#cb7-24" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;No matching person&quot;</span><span class="op">);</span></span>
<span id="cb7-25"><a href="#cb7-25" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb7-26"><a href="#cb7-26" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb7-27"><a href="#cb7-27" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb7-28"><a href="#cb7-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-29"><a href="#cb7-29" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="set-parameters">Set parameters</h2>
<p>The queries you want to run will involve data that comes from a user typing stuff into a box. The way to deal with this is not. I repeat not, under any circumstances the following.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;SELECT name FROM person WHERE birthday=&#39;&quot;</span> <span class="op">+</span> birthday <span class="op">+</span> <span class="st">&quot;&#39;&quot;</span><span class="op">;</span></span></code></pre></div>
<p>This is the root cause of <a href="https://owasp.org/www-community/attacks/SQL_Injection">SQL Injection</a> and is generally not something you want to ever do.</p>
<p>The way to include data in a query is to put a <code>?</code> in the places that data should go, then call various <code>.set*</code> methods to set the data. You pass them the data and then the <code>?</code> you are replacing. These start counting from <code>1</code>, which is unique.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">mysql</span><span class="op">.</span><span class="im">cj</span><span class="op">.</span><span class="im">jdbc</span><span class="op">.</span><span class="im">MysqlDataSource</span><span class="op">;</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">Connection</span><span class="op">;</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">PreparedStatement</span><span class="op">;</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">ResultSet</span><span class="op">;</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">javax</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">DataSource</span><span class="op">;</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>        MysqlDataSource db <span class="op">=</span> <span class="kw">new</span> <span class="fu">MysqlDataSource</span><span class="op">();</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setPort</span><span class="op">(</span><span class="dv">3306</span><span class="op">);</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setUser</span><span class="op">(</span><span class="st">&quot;username&quot;</span><span class="op">);</span></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setPassword</span><span class="op">(</span><span class="st">&quot;password&quot;</span><span class="op">);</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span><span class="bu">Connection</span> conn <span class="op">=</span> db<span class="op">.</span><span class="fu">getConnection</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true" tabindex="-1"></a>            <span class="cf">try</span> <span class="op">(</span><span class="bu">PreparedStatement</span> stmt <span class="op">=</span> conn<span class="op">.</span><span class="fu">prepareStatement</span><span class="op">(</span></span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;SELECT name FROM person WHERE birthday=?&quot;</span></span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true" tabindex="-1"></a>            <span class="op">))</span> <span class="op">{</span></span>
<span id="cb9-19"><a href="#cb9-19" aria-hidden="true" tabindex="-1"></a>                stmt<span class="op">.</span><span class="fu">setString</span><span class="op">(</span><span class="dv">1</span><span class="op">,</span> <span class="st">&quot;9/9/1999&quot;</span><span class="op">);</span></span>
<span id="cb9-20"><a href="#cb9-20" aria-hidden="true" tabindex="-1"></a>                <span class="bu">ResultSet</span> rs <span class="op">=</span> stmt<span class="op">.</span><span class="fu">executeQuery</span><span class="op">();</span></span>
<span id="cb9-21"><a href="#cb9-21" aria-hidden="true" tabindex="-1"></a>                <span class="cf">while</span> <span class="op">(</span>rs<span class="op">.</span><span class="fu">next</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb9-22"><a href="#cb9-22" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>rs<span class="op">.</span><span class="fu">getString</span><span class="op">(</span><span class="st">&quot;name&quot;</span><span class="op">));</span></span>
<span id="cb9-23"><a href="#cb9-23" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb9-24"><a href="#cb9-24" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb9-25"><a href="#cb9-25" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb9-26"><a href="#cb9-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-27"><a href="#cb9-27" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="use-multi-line-strings">Use Multi-Line Strings</h2>
<p>As your queries get bigger, they will probably be going on multiple lines. To do this use three double quotes on either side.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;&quot;&quot;</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>SELECT name FROM person</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>WHERE birthday<span class="op">=?</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;&quot;&quot;</span></span></code></pre></div>
<p>It's important to know this because your maybe very old curriculum will still have examples like</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;SELECT name FROM person </span><span class="sc">\n</span><span class="st">&quot;</span> <span class="op">+</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;WHERE birthday=?&quot;</span></span></code></pre></div>
<p>Which can get tedious.</p>
<h2 id="execute-non-queries">Execute non-queries</h2>
<p>To do something that isn't a query, like inserting rows, you use the <code>.execute()</code> method instead of <code>.executeQuery()</code>. This will not give you a <a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.sql/java/sql/ResultSet.html"><code>ResultSet</code></a> object.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">mysql</span><span class="op">.</span><span class="im">cj</span><span class="op">.</span><span class="im">jdbc</span><span class="op">.</span><span class="im">MysqlDataSource</span><span class="op">;</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">Connection</span><span class="op">;</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">PreparedStatement</span><span class="op">;</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">ResultSet</span><span class="op">;</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">javax</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">DataSource</span><span class="op">;</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>        MysqlDataSource db <span class="op">=</span> <span class="kw">new</span> <span class="fu">MysqlDataSource</span><span class="op">();</span></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setPort</span><span class="op">(</span><span class="dv">3306</span><span class="op">);</span></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setUser</span><span class="op">(</span><span class="st">&quot;username&quot;</span><span class="op">);</span></span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a>        db<span class="op">.</span><span class="fu">setPassword</span><span class="op">(</span><span class="st">&quot;password&quot;</span><span class="op">);</span></span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span><span class="bu">Connection</span> conn <span class="op">=</span> db<span class="op">.</span><span class="fu">getConnection</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true" tabindex="-1"></a>            <span class="cf">try</span> <span class="op">(</span><span class="bu">PreparedStatement</span> stmt <span class="op">=</span> conn<span class="op">.</span><span class="fu">prepareStatement</span><span class="op">(</span></span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;&quot;&quot;</span></span>
<span id="cb12-18"><a href="#cb12-18" aria-hidden="true" tabindex="-1"></a>                    INSERT INTO <span class="fu">person</span><span class="op">(</span>name<span class="op">,</span> status<span class="op">)</span></span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true" tabindex="-1"></a>                    <span class="fu">VALUES</span> <span class="op">(?,</span> <span class="op">?)</span></span>
<span id="cb12-20"><a href="#cb12-20" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;&quot;&quot;</span></span>
<span id="cb12-21"><a href="#cb12-21" aria-hidden="true" tabindex="-1"></a>            <span class="op">))</span> <span class="op">{</span></span>
<span id="cb12-22"><a href="#cb12-22" aria-hidden="true" tabindex="-1"></a>                stmt<span class="op">.</span><span class="fu">setString</span><span class="op">(</span><span class="dv">1</span><span class="op">,</span> <span class="st">&quot;tiny tim&quot;</span><span class="op">);</span></span>
<span id="cb12-23"><a href="#cb12-23" aria-hidden="true" tabindex="-1"></a>                stmt<span class="op">.</span><span class="fu">setString</span><span class="op">(</span><span class="dv">2</span><span class="op">,</span> <span class="st">&quot;not dead&quot;</span><span class="op">);</span></span>
<span id="cb12-24"><a href="#cb12-24" aria-hidden="true" tabindex="-1"></a>                stmt<span class="op">.</span><span class="fu">execute</span><span class="op">();</span></span>
<span id="cb12-25"><a href="#cb12-25" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb12-26"><a href="#cb12-26" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb12-27"><a href="#cb12-27" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb12-28"><a href="#cb12-28" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="pool-your-connections">Pool your connections</h2>
<p>Getting a fresh connection to the database every time you want to make a query is ultimately inefficient.</p>
<p>Think of getting a connection like making a phone call. You need to dial, it needs to ring, and the other end needs to pick up. That all takes time.</p>
<p>To resolve this we use "Connection Pools." These are <code>DataSource</code> implementations which keep some number of connections always active and re-use them between calls to <code>.getConnection</code>,</p>
<p><em>The</em> library to use for this is called <a href="https://central.sonatype.com/artifact/com.zaxxer/HikariCP"><code>HikariCP</code></a>.</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">mysql</span><span class="op">.</span><span class="im">cj</span><span class="op">.</span><span class="im">jdbc</span><span class="op">.</span><span class="im">MysqlDataSource</span><span class="op">;</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">zaxxer</span><span class="op">.</span><span class="im">hikari</span><span class="op">.</span><span class="im">HikariConfig</span><span class="op">;</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">zaxxer</span><span class="op">.</span><span class="im">hikari</span><span class="op">.</span><span class="im">HikariDataSource</span><span class="op">;</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>        MysqlDataSource mysql <span class="op">=</span> <span class="kw">new</span> <span class="fu">MysqlDataSource</span><span class="op">();</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>        mysql<span class="op">.</span><span class="fu">setPort</span><span class="op">(</span><span class="dv">3306</span><span class="op">);</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>        mysql<span class="op">.</span><span class="fu">setUser</span><span class="op">(</span><span class="st">&quot;username&quot;</span><span class="op">);</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>        mysql<span class="op">.</span><span class="fu">setPassword</span><span class="op">(</span><span class="st">&quot;password&quot;</span><span class="op">);</span></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a>        HikariConfig config <span class="op">=</span> <span class="kw">new</span> <span class="fu">HikariConfig</span><span class="op">();</span></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>        config<span class="op">.</span><span class="fu">setDataSource</span><span class="op">(</span>mysql<span class="op">);</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a>        HikariDataSource db <span class="op">=</span> <span class="kw">new</span> <span class="fu">HikariDataSource</span><span class="op">(</span>config<span class="op">);</span></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span>var conn <span class="op">=</span> db<span class="op">.</span><span class="fu">getConnection</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a>            <span class="co">// ...</span></span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Note that you do not need to pool connections with a database like SQLite. There making a connection isn't like making a phone call, it's like shouting at your cousin in the other room. There's only one cousin and he can hear you.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>The Java Command Line Workflow</title><link>https://mccue.dev/pages/1-11-24-cli-flow</link><description></description><pubDate>Thu, 11 Jan 0024 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>The Java Command Line Workflow</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">The Java Command Line Workflow</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
A while ago, I released a draft of the [jresolve](https://github.com/bowbahdoe/jresolve-cli) command line tool.
Its function is to take a set of root dependency declarations and resolve the full set of transitive dependencies.

<p>I'm happy with the API, but there are some things to fix up.</p>
<p>But I think <code>jresolve</code>'s existence, and why I bothered to make it, only makes sense as a part of a larger story. This is an attempt to tell it.</p>
<h2 id="the-problem">The Problem</h2>
<p>We all use Maven or Gradle. There are other up-and-coming build tools like <a href="https://rife2.com/bld">bld</a> and some <a href="https://ant.apache.org/">Ant</a> holdovers from the 2000s, but if you threw darts at Java codebases that is what you would hit.</p>
<p>This is a good state of affairs in many ways, but there are downsides.</p>
<p>The specific downside I want to focus on is how it affects the way people learn Java. What follows are my own opinions and perception.</p>
<h2 id="step-1">Step 1.</h2>
<p>When people learn how to code, typically they start with a "Hello, world" program.</p>
<p>In the past, this part involved hand-waving away <code>public static void main(String[] args)</code>. In some future release of Java <a href="https://openjdk.org/jeps/445">it will be simpler</a>. That's great. I'll talk about how can affect curriculums at some point.</p>
<p>But from a tooling perspective, this step is a choice between having them run <code>java Main.java</code> on the command line and having them click the "Big Green Run Button" in whatever text editor they installed or online platform they signed up for.</p>
<h2 id="step-2">Step 2.</h2>
<p>You can actually go pretty far into the language without leaving a single file, but at some point a student needs to have more than one file in their projects.</p>
<p>To do this, you again have a (non-exclusive) choice of how to approach it. Either the command line or the Big Green Run Button.</p>
<p>If you take the command line route, it <a href="https://openjdk.org/jeps/458">will be</a> still <code>java Main.java</code>, followed by <code>java src/Main.java</code> after you guide them to keep their code in a folder.</p>
<p>Green button is the green button.</p>
<h2 id="step-3">Step 3.</h2>
<p>Because it will be relevant to things to come, you at some point want to explain that Java code can be compiled ahead of time to <code>.class</code> files. You could point to the directory where the B.G.R.B. put the class files, or you could explain what <code>javac</code> is and how to use it. For that you would land on something like this.</p>
<pre><code>javac --source-path ./src -d classes src/Main.java
java --class-path classes Main</code></pre>
<p>So you would have been able to introduce <code>javac</code>, the concept of ahead of time compilation, <code>.class</code> files, and the <code>--class-path</code>.</p>
<h2 id="step-4">Step 4.</h2>
<p>Once they've made an app <a href="https://www.youtube.com/watch?v=WszAwrlS5GM">the next thing they'll want</a> is to package it up into a jar.</p>
<p>In the 🟢 world, you show them a menu in their editor and what buttons to click.</p>
<p>In the CLI, it's a chance to show them how to use the <code>jar</code> tool.</p>
<pre><code>jar --create --file app.jar --main-class Main -C classes .</code></pre>
<h2 id="step-5">Step 5.</h2>
<p>This is where things get tricky, because once they know how to build an app it won't be long before they want to make something that requires a dependency.</p>
<p>And it is this step where things fall apart.</p>
<p>If you are lucky, the dependency they need has no transitive dependencies. You show them how to download a <code>.jar</code> file, how to add it to the IDE or where to put it on the <code>--class-path</code>, and warn them that they won't be able to get way with that forever.</p>
<p>If you aren't, you need Maven or Gradle. That is by far the easiest way to make sure they get their dependencies.</p>
<p>It is also easy to justify. Chances are any Java job would use one of those.</p>
<p>One problem is that because Maven and Gradle also take over compiling the code, you invalidate their investment in learning how to use <code>javac</code> and <code>jar</code>. They won't be using either of those from now on.</p>
<p>Another is that both are going to throw a lot in their face. Either an entirely new programming language with Gradle or a relatively beefy <code>pom.xml</code> with Maven.</p>
<p>This is what a "blank" Maven gives you in IntelliJ. It's not <em>horrible</em>, but it does have some <code>public static void main(String[] args)</code>-like properties.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode xml"><code class="sourceCode xml"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="fu">&lt;?xml</span><span class="ot"> version=</span><span class="st">&quot;1.0&quot;</span><span class="ot"> encoding=</span><span class="st">&quot;UTF-8&quot;</span><span class="fu">?&gt;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>&lt;<span class="ot">project</span> <span class="er">xmlns</span><span class="ot">=</span><span class="st">&quot;http://maven.apache.org/POM/4.0.0&quot;</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="ot">         xmlns:xsi=</span><span class="st">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="ot">         xsi:schemaLocation=</span><span class="st">&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;</span>&gt;</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    &lt;<span class="ot">modelVersion</span><span class="er">&gt;4.0.0&lt;/modelVersion&gt;</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;groupId&gt;org.example&lt;/groupId&gt;</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;artifactId&gt;untitled92&lt;/artifactId&gt;</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;properties&gt;</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;maven.compiler.source&gt;21&lt;/maven.compiler.source&gt;</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;maven.compiler.target&gt;21&lt;/maven.compiler.target&gt;</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;/properties&gt;</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a><span class="er">&lt;/project&gt;</span></span></code></pre></div>
<p>You could also use something like <a href="https://www.jbang.dev/"><code>jbang</code></a>, which automatically downloads dependencies declared as comments in the code. But this stops being viable if you want those dependencies for things other than running the code as a script, unfortunately.</p>
<p>So the point of <code>jresolve</code> specifically is to let you stick with the command-line flow and avoid pivoting to build tools until later.</p>
<p>You show them how to use it to get dependencies from the internet as well as how to use those dependencies.</p>
<pre><code>jresolve \
    --output-directory libraries \
    pkg:maven/de.gurkenlabs/litiengine@0.8.0

javac \
    --module-path libraries \
    --add-modules ALL-MODULE-PATH \
    --source-path ./src \
    -d classes \
    src/Main.java

java \
    --module-path libraries \
    --add-modules ALL-MODULE-PATH \
    --class-path classes \
    Main</code></pre>
<p>As an aside, while it requires the unpleasant appearance of <code>ALL-MODULE-PATH</code> I would argue that showing early that you should put your external dependencies on the <code>--module-path</code> is a good thing.</p>
<h2 id="step-6">Step 6.</h2>
<p>If you took the path enabled by a tool like <code>jresolve</code>, the commands you are asking folks to run likely are getting pretty hard to remember.</p>
<p>It is a good time to introduce some "command runner" mechanism. Some way so they only have to say <code>compile</code> instead of a long <code>javac</code> incantation.</p>
<p>For this purpose, I have a liking for <a href="https://github.com/casey/just">just</a>, but shell scripts, makefiles, etc. are all valid.</p>
<pre class="just"><code>help:
    just --list
    
clean:
    rm -rf classes
    rm -rf libraries

install:
    rm -rf libraries
    jresolve \
        --output-directory libraries \
        pkg:maven/de.gurkenlabs/litiengine@0.8.0
   
compile:
    rm -rf classes
    javac \
        --module-path libraries \
        --add-modules ALL-MODULE-PATH \
        --source-path ./src \
        -d classes \
        src/Main.java

run:
    java \
        --module-path libraries \
        --add-modules ALL-MODULE-PATH \
        --class-path classes \
        Main  </code></pre>
<p>Now that they can do something spiritually like <code>just compile</code>, commands no longer need to be produced from memory every time they want to do things with their code.</p>
<p>It also instills the notion that software projects are generally built by a set of named and repeatable processes.</p>
<p>And if you haven't or its just time for a refresher, you can use this as an opportunity to go a little deeper into the command line and explain tools like <code>cd</code> and <code>rm</code>.</p>
<h2 id="step-7">Step 7.</h2>
<p>Now that they know how to use dependencies and can run somewhat involved processes in the CLI, you can show them how to package their code to share with someone who doesn't have Java.</p>
<p>If they've made games and other such gui things, then you can show them <code>jpackage</code>. Have them make a <code>jar</code> with their classes and show them the flags to include their dependencies and make an installer.</p>
<p>If you've kept more of a server-y focus, maybe you'd just show them how to copy files to a remote machine, maybe you'd go through something like docker and show them the commands to build images.</p>
<p>But at this point they have some idea of how to "ship" their code.</p>
<h2 id="step-8">Step 8.</h2>
<p>Now that they have all the mechanisms to deliver code from concept to product, they are going to start making big projects.</p>
<p>At least some students will have an idea for a game or a website or similar they're going to invest a lot of time in, but also the assignments you are giving will probably require more structure. A thing I've seen in a lot of curriculums is to have everyone do the <code>M</code> part of an <code>MVC</code> type assignment and swap <code>M</code>s with another group and write the <code>V</code> and <code>C</code> using that.</p>
<p>As such, it is as good a time as any to introduce modules.</p>
<p>The path of least resistance would be to introduce the multi-module format that <code>javac</code> understands. I.E you have a top level directory for each module that has the module's name.</p>
<pre><code>some.mod/
    src/
        module-info.java
        some/
            mod/
                ...
other.mod/
    src/
        module-info.java
        other/
            mod/
                ...</code></pre>
<pre><code>javac \
    -d compiled \
    --module-path libraries \
    --module-source-path  &quot;./*/src&quot; \
    --module some.mod,other.mod</code></pre>
<p>That will require talking about visibility and packages, so it's a good point to also start talking about higher level concepts like encapsulation and library contracts.</p>
<h2 id="step-9">Step 9.</h2>
<p>Maybe this can be done a bit sooner, but you definitely need to show those goobers how to write unit tests now.</p>
<p>The best way to do this is to show them how to use <code>junit</code>.</p>
<pre><code>java --module-path libraries:compiled \
     --add-modules ALL-MODULE-PATH \
     org.junit.platform.console.ConsoleLauncher execute --scan-modules</code></pre>
<p>Maybe there can be a <code>junit</code> executable ready via some mechanism, but either way all the mechanics of even this relatively verbose incantation have been shown.</p>
<p>And this is a great point to introduce the practice of having a separate <code>test</code> folder. Also potentially <code>resources</code> since tests can use those as a source of test data.</p>
<h2 id="step-10">Step 10.</h2>
<p>At some point now that they know how to write code, write tests, design modules, etc. It would be a good point to get into library writing. Not everyone will, but some will try their hand.</p>
<p>It's at this point that learning Maven or Gradle probably becomes needed, though I think with a smidgen more tooling that can be delayed. Maybe just something to generate a POM + <code>jreleaser</code> would be enough.</p>
<h2 id="step-n">Step N.</h2>
<p>Then, at some point, they have need for a real build tool. I won't opine on this, but I think some people wouldn't ever reach this step.</p>
<p>They will have already gotten a relatively deep understanding of the underlying tools, naturally come across the concept of a build task, know what a library is and what Maven coordinates are and do, and they will have enough context to know why Maven would choose <code>src/main/java</code> as the place to put code.</p>
<p>I think this is a healthier level to engage with build-tools at. Understanding what tasks they automate because you've done those tasks manually.</p>
<p>It also gives a firmer foundation for the more exotic parts of tooling like agents, AppCDS, annotation processors, etc. Build tools aren't always the most intuitive with those.</p>
<h2 id="conclusion">Conclusion</h2>
<p>This might not be appropriate for all curriculums. Sometimes you are in a boot-camp and you just gotta be employable with Spring in 6 months.</p>
<p>But when the goal of an education isn't optimizing time to employment, I think teaching with the command-line first has value. I just think that in order for it to be actually practical, a few more pieces need to be in place.</p>
<p>So that aspiration is what <code>jresolve</code> is for. It is what whatever CLI tool I make next will probably be for. That's the vision. Have the JDK be enough, by itself, to get bootstrapped into modern software development. Lower the barrier of entry to be around that of JavaScript and Python.</p>
<hr />
<p>Tell me what I got wrong in the comments below.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>org.xerial.sqlitejdbc</title><link>https://mccue.dev/pages/12-24-23-java-library-of-the-day-24</link><description></description><pubDate>Sun, 24 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>org.xerial.sqlitejdbc</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">org.xerial.sqlitejdbc</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/org.xerial/sqlite-jdbc"><code>org.xerial/sqlite-jdbc</code></a></li>
<li>Module Name: <code>org.xerial.sqlitejdbc</code></li>
<li>GitHub: <a href="https://github.com/xerial/sqlite-jdbc"><code>xerial/sqlite-jdbc</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogNDgwLjM3NXB4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii04IC04IDQ4MC4zNzUgMzAyIiByb2xlPSJncmFwaGljcy1kb2N1bWVudCBkb2N1bWVudCIgYXJpYS1yb2xlZGVzY3JpcHRpb249ImZsb3djaGFydC12MiI+PHN0eWxlPiNteS1zdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O2ZpbGw6IzMzMzt9I215LXN2ZyAuZXJyb3ItaWNvbntmaWxsOiM1NTIyMjI7fSNteS1zdmcgLmVycm9yLXRleHR7ZmlsbDojNTUyMjIyO3N0cm9rZTojNTUyMjIyO30jbXktc3ZnIC5lZGdlLXRoaWNrbmVzcy1ub3JtYWx7c3Ryb2tlLXdpZHRoOjJweDt9I215LXN2ZyAuZWRnZS10aGlja25lc3MtdGhpY2t7c3Ryb2tlLXdpZHRoOjMuNXB4O30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tc29saWR7c3Ryb2tlLWRhc2hhcnJheTowO30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tZGFzaGVke3N0cm9rZS1kYXNoYXJyYXk6Mzt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLWRvdHRlZHtzdHJva2UtZGFzaGFycmF5OjI7fSNteS1zdmcgLm1hcmtlcntmaWxsOiMzMzMzMzM7c3Ryb2tlOiMzMzMzMzM7fSNteS1zdmcgLm1hcmtlci5jcm9zc3tzdHJva2U6IzMzMzMzMzt9I215LXN2ZyBzdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O30jbXktc3ZnIC5sYWJlbHtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Y29sb3I6IzMzMzt9I215LXN2ZyAuY2x1c3Rlci1sYWJlbCB0ZXh0e2ZpbGw6IzMzMzt9I215LXN2ZyAuY2x1c3Rlci1sYWJlbCBzcGFuLCNteS1zdmcgcHtjb2xvcjojMzMzO30jbXktc3ZnIC5sYWJlbCB0ZXh0LCNteS1zdmcgc3BhbiwjbXktc3ZnIHB7ZmlsbDojMzMzO2NvbG9yOiMzMzM7fSNteS1zdmcgLm5vZGUgcmVjdCwjbXktc3ZnIC5ub2RlIGNpcmNsZSwjbXktc3ZnIC5ub2RlIGVsbGlwc2UsI215LXN2ZyAubm9kZSBwb2x5Z29uLCNteS1zdmcgLm5vZGUgcGF0aHtmaWxsOiNFQ0VDRkY7c3Ryb2tlOiM5MzcwREI7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAuZmxvd2NoYXJ0LWxhYmVsIHRleHR7dGV4dC1hbmNob3I6bWlkZGxlO30jbXktc3ZnIC5ub2RlIC5rYXRleCBwYXRoe2ZpbGw6IzAwMDtzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5ub2RlIC5sYWJlbHt0ZXh0LWFsaWduOmNlbnRlcjt9I215LXN2ZyAubm9kZS5jbGlja2FibGV7Y3Vyc29yOnBvaW50ZXI7fSNteS1zdmcgLmFycm93aGVhZFBhdGh7ZmlsbDojMzMzMzMzO30jbXktc3ZnIC5lZGdlUGF0aCAucGF0aHtzdHJva2U6IzMzMzMzMztzdHJva2Utd2lkdGg6Mi4wcHg7fSNteS1zdmcgLmZsb3djaGFydC1saW5re3N0cm9rZTojMzMzMzMzO2ZpbGw6bm9uZTt9I215LXN2ZyAuZWRnZUxhYmVse2JhY2tncm91bmQtY29sb3I6I2U4ZThlODt0ZXh0LWFsaWduOmNlbnRlcjt9I215LXN2ZyAuZWRnZUxhYmVsIHJlY3R7b3BhY2l0eTowLjU7YmFja2dyb3VuZC1jb2xvcjojZThlOGU4O2ZpbGw6I2U4ZThlODt9I215LXN2ZyAubGFiZWxCa2d7YmFja2dyb3VuZC1jb2xvcjpyZ2JhKDIzMiwgMjMyLCAyMzIsIDAuNSk7fSNteS1zdmcgLmNsdXN0ZXIgcmVjdHtmaWxsOiNmZmZmZGU7c3Ryb2tlOiNhYWFhMzM7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAuY2x1c3RlciB0ZXh0e2ZpbGw6IzMzMzt9I215LXN2ZyAuY2x1c3RlciBzcGFuLCNteS1zdmcgcHtjb2xvcjojMzMzO30jbXktc3ZnIGRpdi5tZXJtYWlkVG9vbHRpcHtwb3NpdGlvbjphYnNvbHV0ZTt0ZXh0LWFsaWduOmNlbnRlcjttYXgtd2lkdGg6MjAwcHg7cGFkZGluZzoycHg7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxMnB4O2JhY2tncm91bmQ6aHNsKDgwLCAxMDAlLCA5Ni4yNzQ1MDk4MDM5JSk7Ym9yZGVyOjFweCBzb2xpZCAjYWFhYTMzO2JvcmRlci1yYWRpdXM6MnB4O3BvaW50ZXItZXZlbnRzOm5vbmU7ei1pbmRleDoxMDA7fSNteS1zdmcgLmZsb3djaGFydFRpdGxlVGV4dHt0ZXh0LWFuY2hvcjptaWRkbGU7Zm9udC1zaXplOjE4cHg7ZmlsbDojMzMzO30jbXktc3ZnIDpyb290ey0tbWVybWFpZC1mb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7fSNteS1zdmcgLmdyZWVuJmd0Oyp7c3Ryb2tlOnJnYigyNTUsIDAsIDApIWltcG9ydGFudDt9I215LXN2ZyAuZ3JlZW4gc3BhbntzdHJva2U6cmdiKDI1NSwgMCwgMCkhaW1wb3J0YW50O308L3N0eWxlPjxnPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtcG9pbnRFbmQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjYiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjEyIiBtYXJrZXJIZWlnaHQ9IjEyIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMCAwIEwgMTAgNSBMIDAgMTAgeiIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LXBvaW50U3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjQuNSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTIiIG1hcmtlckhlaWdodD0iMTIiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAwIDUgTCAxMCAxMCBMIDEwIDAgeiIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNpcmNsZUVuZCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iMTEiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxjaXJjbGUgY3g9IjUiIGN5PSI1IiByPSI1IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY2lyY2xlU3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9Ii0xIiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48Y2lyY2xlIGN4PSI1IiBjeT0iNSIgcj0iNSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNyb3NzRW5kIiBjbGFzcz0ibWFya2VyIGNyb3NzIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDExIDExIiByZWZYPSIxMiIgcmVmWT0iNS4yIiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDEsMSBsIDksOSBNIDEwLDEgbCAtOSw5IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAyOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY3Jvc3NTdGFydCIgY2xhc3M9Im1hcmtlciBjcm9zcyBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMSAxMSIgcmVmWD0iLTEiIHJlZlk9IjUuMiIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAxLDEgbCA5LDkgTSAxMCwxIGwgLTksOSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMjsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48ZyBjbGFzcz0icm9vdCI+PGcgY2xhc3M9ImNsdXN0ZXJzIi8+PGcgY2xhc3M9ImVkZ2VQYXRocyI+PHBhdGggZD0iTTU2LjQ1MywzNEw1Ni40NTMsMzguMTY3QzU2LjQ1Myw0Mi4zMzMsNTYuNDUzLDUwLjY2Nyw3My44OTIsNTkuNzgyQzkxLjMzMiw2OC44OTcsMTI2LjIxLDc4Ljc5NSwxNDMuNjUsODMuNzQ0TDE2MS4wODksODguNjkyIiBpZD0iTC1sb2dnaW5nLXNxbC0wIiBjbGFzcz0iZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1sb2dnaW5nIExFLXNxbCIgc3R5bGU9ImZpbGw6bm9uZTsiIG1hcmtlci1lbmQ9InVybCgjbXktc3ZnX2Zsb3djaGFydC1wb2ludEVuZCkiLz48cGF0aCBkPSJNMjA0LjQ2MSwzNEwyMDQuNDYxLDM4LjE2N0MyMDQuNDYxLDQyLjMzMywyMDQuNDYxLDUwLjY2NywyMDQuNDYxLDU4LjExN0MyMDQuNDYxLDY1LjU2NywyMDQuNDYxLDcyLjEzMywyMDQuNDYxLDc1LjQxN0wyMDQuNDYxLDc4LjciIGlkPSJMLXhtbC1zcWwtMCIgY2xhc3M9ImVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMteG1sIExFLXNxbCIgc3R5bGU9ImZpbGw6bm9uZTsiIG1hcmtlci1lbmQ9InVybCgjbXktc3ZnX2Zsb3djaGFydC1wb2ludEVuZCkiLz48cGF0aCBkPSJNMzgwLjE5NSwzNEwzODAuMTk1LDM4LjE2N0MzODAuMTk1LDQyLjMzMywzODAuMTk1LDUwLjY2NywzNTguMTQ0LDYwLjEwM0MzMzYuMDkzLDY5LjU0LDI5MS45OTEsODAuMDgxLDI2OS45NCw4NS4zNTFMMjQ3Ljg4OSw5MC42MjEiIGlkPSJMLXRyYW5zYWN0aW9uLXNxbC0wIiBjbGFzcz0iZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy10cmFuc2FjdGlvbiBMRS1zcWwiIHN0eWxlPSJmaWxsOm5vbmU7IiBtYXJrZXItZW5kPSJ1cmwoI215LXN2Z19mbG93Y2hhcnQtcG9pbnRFbmQpIi8+PHBhdGggZD0iTTIyMS4xNCwxMThMMjI1LjIyOCwxMjIuMTY3QzIyOS4zMTYsMTI2LjMzMywyMzcuNDkyLDEzNC42NjcsMjUwLjEsMTQyLjY0QzI2Mi43MDgsMTUwLjYxMywyNzkuNzQ4LDE1OC4yMjUsMjg4LjI2OCwxNjIuMDMyTDI5Ni43ODgsMTY1LjgzOCIgaWQ9Ikwtc3FsLXNxbHJvd3NldC0wIiBjbGFzcz0iZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1zcWwgTEUtc3Fscm93c2V0IiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLWVuZD0idXJsKCNteS1zdmdfZmxvd2NoYXJ0LXBvaW50RW5kKSIvPjxwYXRoIGQ9Ik0zNDkuNjgsMTE4TDM0OS42OCwxMjIuMTY3QzM0OS42OCwxMjYuMzMzLDM0OS42OCwxMzQuNjY3LDM0OC44OTIsMTQyLjE0MUMzNDguMTA1LDE0OS42MTUsMzQ2LjUzLDE1Ni4yMjksMzQ1Ljc0MiwxNTkuNTM3TDM0NC45NTUsMTYyLjg0NCIgaWQ9IkwtbmFtaW5nLXNxbHJvd3NldC0wIiBjbGFzcz0iZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1uYW1pbmcgTEUtc3Fscm93c2V0IiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLWVuZD0idXJsKCNteS1zdmdfZmxvd2NoYXJ0LXBvaW50RW5kKSIvPjxwYXRoIGQ9Ik0xMTkuNzczLDIwMkwxMTkuNzczLDIwNi4xNjdDMTE5Ljc3MywyMTAuMzMzLDExOS43NzMsMjE4LjY2NywxMjYuNDEzLDIyNi41NjdDMTMzLjA1MiwyMzQuNDY3LDE0Ni4zMzIsMjQxLjkzNSwxNTIuOTcxLDI0NS42NjhMMTU5LjYxMSwyNDkuNDAyIiBpZD0iTC1zbGY0ai1zcWxpdGUtMCIgY2xhc3M9ImVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtc2xmNGogTEUtc3FsaXRlIiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLWVuZD0idXJsKCNteS1zdmdfZmxvd2NoYXJ0LXBvaW50RW5kKSIvPjxwYXRoIGQ9Ik0yMDAuNDEzLDExOEwxOTkuNDIxLDEyMi4xNjdDMTk4LjQyOSwxMjYuMzMzLDE5Ni40NDUsMTM0LjY2NywxOTUuNDUzLDE0NS44MzNDMTk0LjQ2MSwxNTcsMTk0LjQ2MSwxNzEsMTk0LjQ2MSwxODVDMTk0LjQ2MSwxOTksMTk0LjQ2MSwyMTMsMTk0LjQ2MSwyMjMuMjgzQzE5NC40NjEsMjMzLjU2NywxOTQuNDYxLDI0MC4xMzMsMTk0LjQ2MSwyNDMuNDE3TDE5NC40NjEsMjQ2LjciIGlkPSJMLXNxbC1zcWxpdGUtMCIgY2xhc3M9ImVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtc3FsIExFLXNxbGl0ZSIgc3R5bGU9ImZpbGw6bm9uZTsiIG1hcmtlci1lbmQ9InVybCgjbXktc3ZnX2Zsb3djaGFydC1wb2ludEVuZCkiLz48cGF0aCBkPSJNMzM5LjY4LDIwMkwzMzkuNjgsMjA2LjE2N0MzMzkuNjgsMjEwLjMzMywzMzkuNjgsMjE4LjY2NywzMjYuMTIyLDIyNi43NTVDMzEyLjU2NCwyMzQuODQyLDI4NS40NDcsMjQyLjY4NSwyNzEuODg5LDI0Ni42MDZMMjU4LjMzMSwyNTAuNTI3IiBpZD0iTC1zcWxyb3dzZXQtc3FsaXRlLTAiIGNsYXNzPSJlZGdlLXRoaWNrbmVzcy1ub3JtYWwgZWRnZS1wYXR0ZXJuLXNvbGlkIGZsb3djaGFydC1saW5rIExTLXNxbHJvd3NldCBMRS1zcWxpdGUiIHN0eWxlPSJmaWxsOm5vbmU7IiBtYXJrZXItZW5kPSJ1cmwoI215LXN2Z19mbG93Y2hhcnQtcG9pbnRFbmQpIi8+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWxzIj48ZyBjbGFzcz0iZWRnZUxhYmVsIj48ZyBjbGFzcz0ibGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsIDApIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMCIgaGVpZ2h0PSIwIj48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9ImVkZ2VMYWJlbCI+PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWwiPjxnIGNsYXNzPSJsYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMCkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIwIiBoZWlnaHQ9IjAiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0iZWRnZUxhYmVsIj48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbCI+PGcgY2xhc3M9ImxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAwKSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjAiIGhlaWdodD0iMCI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0iZWRnZUxhYmVsIj48ZyBjbGFzcz0ibGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsIDApIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMCIgaGVpZ2h0PSIwIj48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9ImVkZ2VMYWJlbCI+PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWwiPjxnIGNsYXNzPSJsYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMCkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIwIiBoZWlnaHQ9IjAiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0iZWRnZUxhYmVsIj48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbCI+PGcgY2xhc3M9ImxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAwKSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjAiIGhlaWdodD0iMCI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0iZWRnZUxhYmVsIj48ZyBjbGFzcz0ibGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsIDApIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMCIgaGVpZ2h0PSIwIj48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9ImVkZ2VMYWJlbCI+PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWwiPjxnIGNsYXNzPSJsYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMCkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIwIiBoZWlnaHQ9IjAiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0iZWRnZUxhYmVsIj48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjxnIGNsYXNzPSJub2RlcyI+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IGZsb3djaGFydC1sYWJlbCIgaWQ9ImZsb3djaGFydC1uYW1pbmctMCIgZGF0YS1ub2RlPSJ0cnVlIiBkYXRhLWlkPSJuYW1pbmciIHRyYW5zZm9ybT0idHJhbnNsYXRlKDM0OS42Nzk2ODc1LCAxMDEpIj48cmVjdCBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIiBzdHlsZT0iIiByeD0iMCIgcnk9IjAiIHg9Ii01Ni45NDUzMTI1IiB5PSItMTciIHdpZHRoPSIxMTMuODkwNjI1IiBoZWlnaHQ9IjM0Ii8+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNDkuNDQ1MzEyNSwgLTkuNSkiPjxyZWN0Lz48Zm9yZWlnbk9iamVjdCB3aWR0aD0iOTguODkwNjI1IiBoZWlnaHQ9IjE5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+amF2YS5uYW1pbmc8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IGZsb3djaGFydC1sYWJlbCIgaWQ9ImZsb3djaGFydC1sb2dnaW5nLTEiIGRhdGEtbm9kZT0idHJ1ZSIgZGF0YS1pZD0ibG9nZ2luZyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNTYuNDUzMTI1LCAxNykiPjxyZWN0IGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiIHN0eWxlPSIiIHJ4PSIwIiByeT0iMCIgeD0iLTU2LjQ1MzEyNSIgeT0iLTE3IiB3aWR0aD0iMTEyLjkwNjI1IiBoZWlnaHQ9IjM0Ii8+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNDguOTUzMTI1LCAtOS41KSI+PHJlY3QvPjxmb3JlaWduT2JqZWN0IHdpZHRoPSI5Ny45MDYyNSIgaGVpZ2h0PSIxOSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPmphdmEubG9nZ2luZzwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0ibm9kZSBkZWZhdWx0IGRlZmF1bHQgZmxvd2NoYXJ0LWxhYmVsIiBpZD0iZmxvd2NoYXJ0LXhtbC0yIiBkYXRhLW5vZGU9InRydWUiIGRhdGEtaWQ9InhtbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjA0LjQ2MDkzNzUsIDE3KSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjAiIHJ5PSIwIiB4PSItNDEuNTU0Njg3NSIgeT0iLTE3IiB3aWR0aD0iODMuMTA5Mzc1IiBoZWlnaHQ9IjM0Ii8+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMzQuMDU0Njg3NSwgLTkuNSkiPjxyZWN0Lz48Zm9yZWlnbk9iamVjdCB3aWR0aD0iNjguMTA5Mzc1IiBoZWlnaHQ9IjE5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+amF2YS54bWw8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IGZsb3djaGFydC1sYWJlbCIgaWQ9ImZsb3djaGFydC10cmFuc2FjdGlvbi0zIiBkYXRhLW5vZGU9InRydWUiIGRhdGEtaWQ9InRyYW5zYWN0aW9uIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzODAuMTk1MzEyNSwgMTcpIj48cmVjdCBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIiBzdHlsZT0iIiByeD0iMCIgcnk9IjAiIHg9Ii04NC4xNzk2ODc1IiB5PSItMTciIHdpZHRoPSIxNjguMzU5Mzc1IiBoZWlnaHQ9IjM0Ii8+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNzYuNjc5Njg3NSwgLTkuNSkiPjxyZWN0Lz48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMTUzLjM1OTM3NSIgaGVpZ2h0PSIxOSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPmphdmEudHJhbnNhY3Rpb24ueGE8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IGZsb3djaGFydC1sYWJlbCIgaWQ9ImZsb3djaGFydC1zbGY0ai00IiBkYXRhLW5vZGU9InRydWUiIGRhdGEtaWQ9InNsZjRqIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMTkuNzczNDM3NSwgMTg1KSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjAiIHJ5PSIwIiB4PSItMzkuNjg3NSIgeT0iLTE3IiB3aWR0aD0iNzkuMzc1IiBoZWlnaHQ9IjM0Ii8+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMzIuMTg3NSwgLTkuNSkiPjxyZWN0Lz48Zm9yZWlnbk9iamVjdCB3aWR0aD0iNjQuMzc1IiBoZWlnaHQ9IjE5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+b3JnLnNsZjRqPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZGVmYXVsdCBmbG93Y2hhcnQtbGFiZWwiIGlkPSJmbG93Y2hhcnQtc3FsLTUiIGRhdGEtbm9kZT0idHJ1ZSIgZGF0YS1pZD0ic3FsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyMDQuNDYwOTM3NSwgMTAxKSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjAiIHJ5PSIwIiB4PSItMzguMjczNDM3NSIgeT0iLTE3IiB3aWR0aD0iNzYuNTQ2ODc1IiBoZWlnaHQ9IjM0Ii8+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMzAuNzczNDM3NSwgLTkuNSkiPjxyZWN0Lz48Zm9yZWlnbk9iamVjdCB3aWR0aD0iNjEuNTQ2ODc1IiBoZWlnaHQ9IjE5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+amF2YS5zcWw8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IGZsb3djaGFydC1sYWJlbCIgaWQ9ImZsb3djaGFydC1zcWxyb3dzZXQtMTIiIGRhdGEtbm9kZT0idHJ1ZSIgZGF0YS1pZD0ic3Fscm93c2V0IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzMzkuNjc5Njg3NSwgMTg1KSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjAiIHJ5PSIwIiB4PSItNjcuNTkzNzUiIHk9Ii0xNyIgd2lkdGg9IjEzNS4xODc1IiBoZWlnaHQ9IjM0Ii8+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNjAuMDkzNzUsIC05LjUpIj48cmVjdC8+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjEyMC4xODc1IiBoZWlnaHQ9IjE5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+amF2YS5zcWwucm93c2V0PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZ3JlZW4gZmxvd2NoYXJ0LWxhYmVsIiBpZD0iZmxvd2NoYXJ0LXNxbGl0ZS0xNyIgZGF0YS1ub2RlPSJ0cnVlIiBkYXRhLWlkPSJzcWxpdGUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE5NC40NjA5Mzc1LCAyNjkpIj48cmVjdCBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIiBzdHlsZT0iIiByeD0iMCIgcnk9IjAiIHg9Ii04Ni4yODEyNSIgeT0iLTE3IiB3aWR0aD0iMTcyLjU2MjUiIGhlaWdodD0iMzQiLz48ZyBjbGFzcz0ibGFiZWwiIHN0eWxlPSIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC03OC43ODEyNSwgLTkuNSkiPjxyZWN0Lz48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMTU3LjU2MjUiIGhlaWdodD0iMTkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj5vcmcueGVyaWFsLnNxbGl0ZWpkYmM8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjwvZz48L2c+PC9zdmc+" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>org.xerial.sqlitejdbc</code> lets you create and interact with a <a href="https://www.sqlite.org/index.html">SQLite</a> database from Java.</p>
<h2 id="why-use-it">Why use it</h2>
<p>To quote the blurb on <a href="https://www.sqlite.org/index.html">the SQLite website</a></p>
<blockquote>
<p>SQLite is a C-language library that implements a small, fast, self-contained, high-reliability, full-featured, SQL database engine. SQLite is the most used database engine in the world. SQLite is built into all mobile phones and most computers and comes bundled inside countless other applications that people use every day.</p>
<p>The SQLite file format is stable, cross-platform, and backwards compatible and the developers pledge to keep it that way through the year 2050. SQLite database files are commonly used as containers to transfer rich content between systems and as a long-term archival format for data. There are over 1 trillion (1e12) SQLite databases in active use.</p>
<p>SQLite source code is in the public-domain and is free to everyone to use for any purpose.</p>
</blockquote>
<p>So if you want a data store, and it's okay if that data is in a file on the filesystem, SQLite is a very good choice.</p>
<h2 id="getting-started">Getting Started</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">sqlite</span><span class="op">.</span><span class="im">SQLiteDataSource</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">List</span><span class="op">;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="kw">throws</span> <span class="bu">Exception</span> <span class="op">{</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    var db <span class="op">=</span> <span class="kw">new</span> <span class="fu">SQLiteDataSource</span><span class="op">();</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    db<span class="op">.</span><span class="fu">setUrl</span><span class="op">(</span><span class="st">&quot;jdbc:sqlite:database.db&quot;</span><span class="op">);</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">try</span> <span class="op">(</span>var conn <span class="op">=</span> db<span class="op">.</span><span class="fu">getConnection</span><span class="op">();</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>         var stmt <span class="op">=</span> conn<span class="op">.</span><span class="fu">prepareStatement</span><span class="op">(</span><span class="st">&quot;&quot;&quot;</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>                 CREATE TABLE IF NOT EXISTS <span class="fu">widget</span><span class="op">(</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>                    id integer not <span class="kw">null</span> primary key<span class="op">,</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>                    name text not <span class="kw">null</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>                 <span class="op">)</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>                 <span class="st">&quot;&quot;&quot;)) {</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>        stmt<span class="op">.</span><span class="fu">execute</span><span class="op">();</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>    <span class="cf">try</span> <span class="op">(</span>var conn <span class="op">=</span> db<span class="op">.</span><span class="fu">getConnection</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span>var name <span class="op">:</span> <span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;Bob&quot;</span><span class="op">,</span> <span class="st">&quot;Susan&quot;</span><span class="op">,</span> <span class="st">&quot;Sob&quot;</span><span class="op">,</span> <span class="st">&quot;Busan&quot;</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>            <span class="cf">try</span> <span class="op">(</span>var stmt <span class="op">=</span> conn<span class="op">.</span><span class="fu">prepareStatement</span><span class="op">(</span><span class="st">&quot;&quot;&quot;</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>                 INSERT INTO <span class="fu">widget</span><span class="op">(</span>name<span class="op">)</span> <span class="fu">VALUES</span> <span class="op">(?)</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>                 <span class="st">&quot;&quot;&quot;)) {</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>                stmt<span class="op">.</span><span class="fu">setString</span><span class="op">(</span><span class="dv">1</span><span class="op">,</span> name<span class="op">);</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>                stmt<span class="op">.</span><span class="fu">execute</span><span class="op">();</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a>    <span class="co">// id=1, name=Bob</span></span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a>    <span class="co">// id=2, name=Susan</span></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a>    <span class="co">// id=3, name=Sob</span></span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a>    <span class="co">// id=4, name=Busan</span></span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a>    <span class="cf">try</span> <span class="op">(</span>var conn <span class="op">=</span> db<span class="op">.</span><span class="fu">getConnection</span><span class="op">();</span></span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a>         var stmt <span class="op">=</span> conn<span class="op">.</span><span class="fu">prepareStatement</span><span class="op">(</span><span class="st">&quot;&quot;&quot;</span></span>
<span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a>                 SELECT id<span class="op">,</span> name</span>
<span id="cb1-37"><a href="#cb1-37" aria-hidden="true" tabindex="-1"></a>                 FROM widget</span>
<span id="cb1-38"><a href="#cb1-38" aria-hidden="true" tabindex="-1"></a>                 <span class="st">&quot;&quot;&quot;)) {</span></span>
<span id="cb1-39"><a href="#cb1-39" aria-hidden="true" tabindex="-1"></a>        var rs <span class="op">=</span> stmt<span class="op">.</span><span class="fu">executeQuery</span><span class="op">();</span></span>
<span id="cb1-40"><a href="#cb1-40" aria-hidden="true" tabindex="-1"></a>        <span class="cf">while</span> <span class="op">(</span>rs<span class="op">.</span><span class="fu">next</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb1-41"><a href="#cb1-41" aria-hidden="true" tabindex="-1"></a>            <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span></span>
<span id="cb1-42"><a href="#cb1-42" aria-hidden="true" tabindex="-1"></a>                    STR<span class="op">.</span><span class="st">&quot;id=</span><span class="er">\{</span><span class="st">rs.getInt(&quot;</span>id<span class="st">&quot;)}, name=</span><span class="er">\{</span><span class="st">rs.getString(&quot;</span>name<span class="st">&quot;)}&quot;</span></span>
<span id="cb1-43"><a href="#cb1-43" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb1-44"><a href="#cb1-44" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-45"><a href="#cb1-45" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-46"><a href="#cb1-46" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>de.poiu.apron</title><link>https://mccue.dev/pages/12-23-23-java-library-of-the-day-23</link><description></description><pubDate>Sat, 23 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>de.poiu.apron</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">de.poiu.apron</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/de.poiu.apron/apron"><code>de.poiu.apron/apron</code></a></li>
<li>Module Name: <code>de.poiu.apron</code></li>
<li>GitHub: <a href="https://github.com/hupfdule/apron"><code>hupfdule/apron</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogMTQxLjgyOHB4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii04IC04IDE0MS44MjgxMjUgMTg0IiByb2xlPSJncmFwaGljcy1kb2N1bWVudCBkb2N1bWVudCIgYXJpYS1yb2xlZGVzY3JpcHRpb249ImZsb3djaGFydC12MiI+PHN0eWxlPiNteS1zdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O2ZpbGw6IzMzMzt9I215LXN2ZyAuZXJyb3ItaWNvbntmaWxsOiM1NTIyMjI7fSNteS1zdmcgLmVycm9yLXRleHR7ZmlsbDojNTUyMjIyO3N0cm9rZTojNTUyMjIyO30jbXktc3ZnIC5lZGdlLXRoaWNrbmVzcy1ub3JtYWx7c3Ryb2tlLXdpZHRoOjJweDt9I215LXN2ZyAuZWRnZS10aGlja25lc3MtdGhpY2t7c3Ryb2tlLXdpZHRoOjMuNXB4O30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tc29saWR7c3Ryb2tlLWRhc2hhcnJheTowO30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tZGFzaGVke3N0cm9rZS1kYXNoYXJyYXk6Mzt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLWRvdHRlZHtzdHJva2UtZGFzaGFycmF5OjI7fSNteS1zdmcgLm1hcmtlcntmaWxsOiMzMzMzMzM7c3Ryb2tlOiMzMzMzMzM7fSNteS1zdmcgLm1hcmtlci5jcm9zc3tzdHJva2U6IzMzMzMzMzt9I215LXN2ZyBzdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O30jbXktc3ZnIC5sYWJlbHtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Y29sb3I6IzMzMzt9I215LXN2ZyAuY2x1c3Rlci1sYWJlbCB0ZXh0e2ZpbGw6IzMzMzt9I215LXN2ZyAuY2x1c3Rlci1sYWJlbCBzcGFuLCNteS1zdmcgcHtjb2xvcjojMzMzO30jbXktc3ZnIC5sYWJlbCB0ZXh0LCNteS1zdmcgc3BhbiwjbXktc3ZnIHB7ZmlsbDojMzMzO2NvbG9yOiMzMzM7fSNteS1zdmcgLm5vZGUgcmVjdCwjbXktc3ZnIC5ub2RlIGNpcmNsZSwjbXktc3ZnIC5ub2RlIGVsbGlwc2UsI215LXN2ZyAubm9kZSBwb2x5Z29uLCNteS1zdmcgLm5vZGUgcGF0aHtmaWxsOiNFQ0VDRkY7c3Ryb2tlOiM5MzcwREI7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAuZmxvd2NoYXJ0LWxhYmVsIHRleHR7dGV4dC1hbmNob3I6bWlkZGxlO30jbXktc3ZnIC5ub2RlIC5rYXRleCBwYXRoe2ZpbGw6IzAwMDtzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5ub2RlIC5sYWJlbHt0ZXh0LWFsaWduOmNlbnRlcjt9I215LXN2ZyAubm9kZS5jbGlja2FibGV7Y3Vyc29yOnBvaW50ZXI7fSNteS1zdmcgLmFycm93aGVhZFBhdGh7ZmlsbDojMzMzMzMzO30jbXktc3ZnIC5lZGdlUGF0aCAucGF0aHtzdHJva2U6IzMzMzMzMztzdHJva2Utd2lkdGg6Mi4wcHg7fSNteS1zdmcgLmZsb3djaGFydC1saW5re3N0cm9rZTojMzMzMzMzO2ZpbGw6bm9uZTt9I215LXN2ZyAuZWRnZUxhYmVse2JhY2tncm91bmQtY29sb3I6I2U4ZThlODt0ZXh0LWFsaWduOmNlbnRlcjt9I215LXN2ZyAuZWRnZUxhYmVsIHJlY3R7b3BhY2l0eTowLjU7YmFja2dyb3VuZC1jb2xvcjojZThlOGU4O2ZpbGw6I2U4ZThlODt9I215LXN2ZyAubGFiZWxCa2d7YmFja2dyb3VuZC1jb2xvcjpyZ2JhKDIzMiwgMjMyLCAyMzIsIDAuNSk7fSNteS1zdmcgLmNsdXN0ZXIgcmVjdHtmaWxsOiNmZmZmZGU7c3Ryb2tlOiNhYWFhMzM7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAuY2x1c3RlciB0ZXh0e2ZpbGw6IzMzMzt9I215LXN2ZyAuY2x1c3RlciBzcGFuLCNteS1zdmcgcHtjb2xvcjojMzMzO30jbXktc3ZnIGRpdi5tZXJtYWlkVG9vbHRpcHtwb3NpdGlvbjphYnNvbHV0ZTt0ZXh0LWFsaWduOmNlbnRlcjttYXgtd2lkdGg6MjAwcHg7cGFkZGluZzoycHg7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxMnB4O2JhY2tncm91bmQ6aHNsKDgwLCAxMDAlLCA5Ni4yNzQ1MDk4MDM5JSk7Ym9yZGVyOjFweCBzb2xpZCAjYWFhYTMzO2JvcmRlci1yYWRpdXM6MnB4O3BvaW50ZXItZXZlbnRzOm5vbmU7ei1pbmRleDoxMDA7fSNteS1zdmcgLmZsb3djaGFydFRpdGxlVGV4dHt0ZXh0LWFuY2hvcjptaWRkbGU7Zm9udC1zaXplOjE4cHg7ZmlsbDojMzMzO30jbXktc3ZnIDpyb290ey0tbWVybWFpZC1mb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7fSNteS1zdmcgLmdyZWVuJmd0Oyp7c3Ryb2tlOnJnYigyNTUsIDAsIDApIWltcG9ydGFudDt9I215LXN2ZyAuZ3JlZW4gc3BhbntzdHJva2U6cmdiKDI1NSwgMCwgMCkhaW1wb3J0YW50O308L3N0eWxlPjxnPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtcG9pbnRFbmQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjYiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjEyIiBtYXJrZXJIZWlnaHQ9IjEyIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMCAwIEwgMTAgNSBMIDAgMTAgeiIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LXBvaW50U3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjQuNSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTIiIG1hcmtlckhlaWdodD0iMTIiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAwIDUgTCAxMCAxMCBMIDEwIDAgeiIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNpcmNsZUVuZCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iMTEiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxjaXJjbGUgY3g9IjUiIGN5PSI1IiByPSI1IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY2lyY2xlU3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9Ii0xIiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48Y2lyY2xlIGN4PSI1IiBjeT0iNSIgcj0iNSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNyb3NzRW5kIiBjbGFzcz0ibWFya2VyIGNyb3NzIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDExIDExIiByZWZYPSIxMiIgcmVmWT0iNS4yIiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDEsMSBsIDksOSBNIDEwLDEgbCAtOSw5IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAyOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY3Jvc3NTdGFydCIgY2xhc3M9Im1hcmtlciBjcm9zcyBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMSAxMSIgcmVmWD0iLTEiIHJlZlk9IjUuMiIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAxLDEgbCA5LDkgTSAxMCwxIGwgLTksOSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMjsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48ZyBjbGFzcz0icm9vdCI+PGcgY2xhc3M9ImNsdXN0ZXJzIi8+PGcgY2xhc3M9ImVkZ2VQYXRocyI+PHBhdGggZD0iTTYyLjkxNCwzNEw2Mi45MTQsMzguMTY3QzYyLjkxNCw0Mi4zMzMsNjIuOTE0LDUwLjY2Nyw2Mi45MTQsNTlDNjIuOTE0LDY3LjMzMyw2Mi45MTQsNzUuNjY3LDYyLjkxNCw4NEM2Mi45MTQsOTIuMzMzLDYyLjkxNCwxMDAuNjY3LDYyLjkxNCwxMDguMTE3QzYyLjkxNCwxMTUuNTY3LDYyLjkxNCwxMjIuMTMzLDYyLjkxNCwxMjUuNDE3TDYyLjkxNCwxMjguNyIgaWQ9IkwtbG9nZ2luZy1hcHJvbi0wIiBjbGFzcz0iZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1sb2dnaW5nIExFLWFwcm9uIiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLWVuZD0idXJsKCNteS1zdmdfZmxvd2NoYXJ0LXBvaW50RW5kKSIvPjwvZz48ZyBjbGFzcz0iZWRnZUxhYmVscyI+PGcgY2xhc3M9ImVkZ2VMYWJlbCI+PGcgY2xhc3M9ImxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAwKSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjAiIGhlaWdodD0iMCI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48L2c+PGcgY2xhc3M9Im5vZGVzIj48ZyBjbGFzcz0ibm9kZSBkZWZhdWx0IGRlZmF1bHQgZmxvd2NoYXJ0LWxhYmVsIiBpZD0iZmxvd2NoYXJ0LWxvZ2dpbmctMCIgZGF0YS1ub2RlPSJ0cnVlIiBkYXRhLWlkPSJsb2dnaW5nIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg2Mi45MTQwNjI1LCAxNykiPjxyZWN0IGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiIHN0eWxlPSIiIHJ4PSIwIiByeT0iMCIgeD0iLTU2LjQ1MzEyNSIgeT0iLTE3IiB3aWR0aD0iMTEyLjkwNjI1IiBoZWlnaHQ9IjM0Ii8+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNDguOTUzMTI1LCAtOS41KSI+PHJlY3QvPjxmb3JlaWduT2JqZWN0IHdpZHRoPSI5Ny45MDYyNSIgaGVpZ2h0PSIxOSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPmphdmEubG9nZ2luZzwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0ibm9kZSBkZWZhdWx0IGdyZWVuIGZsb3djaGFydC1sYWJlbCIgaWQ9ImZsb3djaGFydC1hcHJvbi0xIiBkYXRhLW5vZGU9InRydWUiIGRhdGEtaWQ9ImFwcm9uIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg2Mi45MTQwNjI1LCAxNTEpIj48cmVjdCBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIiBzdHlsZT0iIiByeD0iMCIgcnk9IjAiIHg9Ii02Mi45MTQwNjI1IiB5PSItMTciIHdpZHRoPSIxMjUuODI4MTI1IiBoZWlnaHQ9IjM0Ii8+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNTUuNDE0MDYyNSwgLTkuNSkiPjxyZWN0Lz48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMTEwLjgyODEyNSIgaGVpZ2h0PSIxOSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPmRlLnBvaXUuYXByb248L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjwvZz48L2c+PC9zdmc+" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>de.poiu.apron</code> gives you the ability to read and write <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Properties.html">properties</a> files while preserving comments, whitespace, and order of entries.</p>
<h2 id="why-use-it">Why use it</h2>
<p><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Properties.html">java.util.Properties</a> is one of the simpler ways to add configuration to a project. Properties files are just key value pairs separated by an equals sign.</p>
<pre class="properties"><code>key=value
other=otherValue</code></pre>
<p>But if you want to edit a properties file programmatically while keeping any formatting, ordering, or commenting that a human did manually you will run into trouble.</p>
<p>This is the niche that <code>de.poiu.apron</code> fills. You can have configuration files which are updated by a program and a human interchangeably.</p>
<h2 id="getting-started">Getting Started</h2>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">de</span><span class="op">.</span><span class="im">poiu</span><span class="op">.</span><span class="im">apron</span><span class="op">.</span><span class="im">PropertyFile</span><span class="op">;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">de</span><span class="op">.</span><span class="im">poiu</span><span class="op">.</span><span class="im">apron</span><span class="op">.</span><span class="im">entry</span><span class="op">.</span><span class="im">PropertyEntry</span><span class="op">;</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">nio</span><span class="op">.</span><span class="im">file</span><span class="op">.</span><span class="im">Files</span><span class="op">;</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">nio</span><span class="op">.</span><span class="im">file</span><span class="op">.</span><span class="im">Path</span><span class="op">;</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="kw">throws</span> <span class="bu">Exception</span> <span class="op">{</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>    var path <span class="op">=</span> Path<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;config.properties&quot;</span><span class="op">);</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>    var fileContents <span class="op">=</span> <span class="st">&quot;&quot;&quot;</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>            key<span class="op">=</span>value</span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>            # <span class="bu">Context</span> here</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>            otherKey<span class="op">=</span>otherValue</span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;&quot;&quot;;</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>    Files<span class="op">.</span><span class="fu">writeString</span><span class="op">(</span>path<span class="op">,</span> fileContents<span class="op">);</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>    PropertyFile file <span class="op">=</span> PropertyFile<span class="op">.</span><span class="fu">from</span><span class="op">(</span>path<span class="op">.</span><span class="fu">toFile</span><span class="op">());</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a>    <span class="co">// value</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>file<span class="op">.</span><span class="fu">get</span><span class="op">(</span><span class="st">&quot;key&quot;</span><span class="op">));</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>    file<span class="op">.</span><span class="fu">appendEntry</span><span class="op">(</span><span class="kw">new</span> <span class="fu">PropertyEntry</span><span class="op">(</span><span class="st">&quot;port&quot;</span><span class="op">,</span> <span class="st">&quot;4031&quot;</span><span class="op">));</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a>    file<span class="op">.</span><span class="fu">saveTo</span><span class="op">(</span>path<span class="op">.</span><span class="fu">toFile</span><span class="op">());</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a>    <span class="co">// key=value</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a>    <span class="co">// # Context here</span></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a>    <span class="co">// otherKey=otherValue</span></span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a>    <span class="co">// port = 4031</span></span>
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>Files<span class="op">.</span><span class="fu">readString</span><span class="op">(</span>path<span class="op">));</span></span>
<span id="cb2-29"><a href="#cb2-29" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>com.ethlo.time</title><link>https://mccue.dev/pages/12-22-23-java-library-of-the-day-22</link><description></description><pubDate>Fri, 22 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>com.ethlo.time</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">com.ethlo.time</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/com.ethlo.time/itu"><code>com.ethlo.time/itu</code></a></li>
<li>Module Name: <code>com.ethlo.time</code></li>
<li>GitHub: <a href="https://github.com/ethlo/itu"><code>ethlo/itu</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogMTUxLjcwM3B4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii04IC04IDE1MS43MDMxMjUgNTAiIHJvbGU9ImdyYXBoaWNzLWRvY3VtZW50IGRvY3VtZW50IiBhcmlhLXJvbGVkZXNjcmlwdGlvbj0iZmxvd2NoYXJ0LXYyIj48c3R5bGU+I215LXN2Z3tmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjE2cHg7ZmlsbDojMzMzO30jbXktc3ZnIC5lcnJvci1pY29ue2ZpbGw6IzU1MjIyMjt9I215LXN2ZyAuZXJyb3ItdGV4dHtmaWxsOiM1NTIyMjI7c3Ryb2tlOiM1NTIyMjI7fSNteS1zdmcgLmVkZ2UtdGhpY2tuZXNzLW5vcm1hbHtzdHJva2Utd2lkdGg6MnB4O30jbXktc3ZnIC5lZGdlLXRoaWNrbmVzcy10aGlja3tzdHJva2Utd2lkdGg6My41cHg7fSNteS1zdmcgLmVkZ2UtcGF0dGVybi1zb2xpZHtzdHJva2UtZGFzaGFycmF5OjA7fSNteS1zdmcgLmVkZ2UtcGF0dGVybi1kYXNoZWR7c3Ryb2tlLWRhc2hhcnJheTozO30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tZG90dGVke3N0cm9rZS1kYXNoYXJyYXk6Mjt9I215LXN2ZyAubWFya2Vye2ZpbGw6IzMzMzMzMztzdHJva2U6IzMzMzMzMzt9I215LXN2ZyAubWFya2VyLmNyb3Nze3N0cm9rZTojMzMzMzMzO30jbXktc3ZnIHN2Z3tmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjE2cHg7fSNteS1zdmcgLmxhYmVse2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtjb2xvcjojMzMzO30jbXktc3ZnIC5jbHVzdGVyLWxhYmVsIHRleHR7ZmlsbDojMzMzO30jbXktc3ZnIC5jbHVzdGVyLWxhYmVsIHNwYW4sI215LXN2ZyBwe2NvbG9yOiMzMzM7fSNteS1zdmcgLmxhYmVsIHRleHQsI215LXN2ZyBzcGFuLCNteS1zdmcgcHtmaWxsOiMzMzM7Y29sb3I6IzMzMzt9I215LXN2ZyAubm9kZSByZWN0LCNteS1zdmcgLm5vZGUgY2lyY2xlLCNteS1zdmcgLm5vZGUgZWxsaXBzZSwjbXktc3ZnIC5ub2RlIHBvbHlnb24sI215LXN2ZyAubm9kZSBwYXRoe2ZpbGw6I0VDRUNGRjtzdHJva2U6IzkzNzBEQjtzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5mbG93Y2hhcnQtbGFiZWwgdGV4dHt0ZXh0LWFuY2hvcjptaWRkbGU7fSNteS1zdmcgLm5vZGUgLmthdGV4IHBhdGh7ZmlsbDojMDAwO3N0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxcHg7fSNteS1zdmcgLm5vZGUgLmxhYmVse3RleHQtYWxpZ246Y2VudGVyO30jbXktc3ZnIC5ub2RlLmNsaWNrYWJsZXtjdXJzb3I6cG9pbnRlcjt9I215LXN2ZyAuYXJyb3doZWFkUGF0aHtmaWxsOiMzMzMzMzM7fSNteS1zdmcgLmVkZ2VQYXRoIC5wYXRoe3N0cm9rZTojMzMzMzMzO3N0cm9rZS13aWR0aDoyLjBweDt9I215LXN2ZyAuZmxvd2NoYXJ0LWxpbmt7c3Ryb2tlOiMzMzMzMzM7ZmlsbDpub25lO30jbXktc3ZnIC5lZGdlTGFiZWx7YmFja2dyb3VuZC1jb2xvcjojZThlOGU4O3RleHQtYWxpZ246Y2VudGVyO30jbXktc3ZnIC5lZGdlTGFiZWwgcmVjdHtvcGFjaXR5OjAuNTtiYWNrZ3JvdW5kLWNvbG9yOiNlOGU4ZTg7ZmlsbDojZThlOGU4O30jbXktc3ZnIC5sYWJlbEJrZ3tiYWNrZ3JvdW5kLWNvbG9yOnJnYmEoMjMyLCAyMzIsIDIzMiwgMC41KTt9I215LXN2ZyAuY2x1c3RlciByZWN0e2ZpbGw6I2ZmZmZkZTtzdHJva2U6I2FhYWEzMztzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5jbHVzdGVyIHRleHR7ZmlsbDojMzMzO30jbXktc3ZnIC5jbHVzdGVyIHNwYW4sI215LXN2ZyBwe2NvbG9yOiMzMzM7fSNteS1zdmcgZGl2Lm1lcm1haWRUb29sdGlwe3Bvc2l0aW9uOmFic29sdXRlO3RleHQtYWxpZ246Y2VudGVyO21heC13aWR0aDoyMDBweDtwYWRkaW5nOjJweDtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjEycHg7YmFja2dyb3VuZDpoc2woODAsIDEwMCUsIDk2LjI3NDUwOTgwMzklKTtib3JkZXI6MXB4IHNvbGlkICNhYWFhMzM7Ym9yZGVyLXJhZGl1czoycHg7cG9pbnRlci1ldmVudHM6bm9uZTt6LWluZGV4OjEwMDt9I215LXN2ZyAuZmxvd2NoYXJ0VGl0bGVUZXh0e3RleHQtYW5jaG9yOm1pZGRsZTtmb250LXNpemU6MThweDtmaWxsOiMzMzM7fSNteS1zdmcgOnJvb3R7LS1tZXJtYWlkLWZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjt9I215LXN2ZyAuZ3JlZW4mZ3Q7KntzdHJva2U6cmdiKDI1NSwgMCwgMCkhaW1wb3J0YW50O30jbXktc3ZnIC5ncmVlbiBzcGFue3N0cm9rZTpyZ2IoMjU1LCAwLCAwKSFpbXBvcnRhbnQ7fTwvc3R5bGU+PGc+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1wb2ludEVuZCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iNiIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTIiIG1hcmtlckhlaWdodD0iMTIiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAwIDAgTCAxMCA1IEwgMCAxMCB6IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtcG9pbnRTdGFydCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iNC41IiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMiIgbWFya2VySGVpZ2h0PSIxMiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDAgNSBMIDEwIDEwIEwgMTAgMCB6IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY2lyY2xlRW5kIiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSIxMSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PGNpcmNsZSBjeD0iNSIgY3k9IjUiIHI9IjUiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jaXJjbGVTdGFydCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iLTEiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxjaXJjbGUgY3g9IjUiIGN5PSI1IiByPSI1IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY3Jvc3NFbmQiIGNsYXNzPSJtYXJrZXIgY3Jvc3MgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTEgMTEiIHJlZlg9IjEyIiByZWZZPSI1LjIiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMSwxIGwgOSw5IE0gMTAsMSBsIC05LDkiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDI7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jcm9zc1N0YXJ0IiBjbGFzcz0ibWFya2VyIGNyb3NzIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDExIDExIiByZWZYPSItMSIgcmVmWT0iNS4yIiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDEsMSBsIDksOSBNIDEwLDEgbCAtOSw5IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAyOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxnIGNsYXNzPSJyb290Ij48ZyBjbGFzcz0iY2x1c3RlcnMiLz48ZyBjbGFzcz0iZWRnZVBhdGhzIi8+PGcgY2xhc3M9ImVkZ2VMYWJlbHMiLz48ZyBjbGFzcz0ibm9kZXMiPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZ3JlZW4gZmxvd2NoYXJ0LWxhYmVsIiBpZD0iZmxvd2NoYXJ0LXNsZjRqLTAiIGRhdGEtbm9kZT0idHJ1ZSIgZGF0YS1pZD0ic2xmNGoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDY3Ljg1MTU2MjUsIDE3KSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjAiIHJ5PSIwIiB4PSItNjcuODUxNTYyNSIgeT0iLTE3IiB3aWR0aD0iMTM1LjcwMzEyNSIgaGVpZ2h0PSIzNCIvPjxnIGNsYXNzPSJsYWJlbCIgc3R5bGU9IiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTYwLjM1MTU2MjUsIC05LjUpIj48cmVjdC8+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjEyMC43MDMxMjUiIGhlaWdodD0iMTkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj5jb20uZXRobG8udGltZTwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>com.ethlo.time</code> provides utilities for parsing and producing the date and time formats that you are likely to run into on the internet. Namely, <a href="https://www.ietf.org/rfc/rfc3339.txt">RFC-3339</a> timestamps and the <a href="https://www.w3.org/TR/NOTE-datetime">W3C date and time Formats</a>.</p>
<h2 id="why-use-it">Why use it</h2>
<p>While the <code>java.time</code> packages provide generic date and time parsing and can support a wide variety of formats, you still need to know what formats to pick. You also need to pick the same ones everywhere in your program.</p>
<p>This streamlines that process for the common case of working with time information you got from, or you want to put out into, the internet.</p>
<p>It also is <a href="https://github.com/ethlo/itu/blob/main/README">reportedly faster</a> than the code you would produce using the generic APIs.</p>
<h2 id="getting-started">Getting Started</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">time</span><span class="op">.</span><span class="im">OffsetDateTime</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">ethlo</span><span class="op">.</span><span class="im">time</span><span class="op">.</span><span class="im">DateTime</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">ethlo</span><span class="op">.</span><span class="im">time</span><span class="op">.</span><span class="im">ITU</span><span class="op">;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    DateTime dateTime</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>            <span class="op">=</span> ITU<span class="op">.</span><span class="fu">parseLenient</span><span class="op">(</span><span class="st">&quot;2012-12-27T19:07Z&quot;</span><span class="op">);</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    <span class="co">// 2012-12-27T19:07Z</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>dateTime<span class="op">);</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>    OffsetDateTime offsetDateTime</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>            <span class="op">=</span> ITU<span class="op">.</span><span class="fu">parseDateTime</span><span class="op">(</span><span class="st">&quot;2012-12-27T19:07:22.123456789-03:00&quot;</span><span class="op">);</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>    <span class="co">// 2012-12-27T22:07:22Z</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>ITU<span class="op">.</span><span class="fu">formatUtc</span><span class="op">(</span>offsetDateTime<span class="op">));</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>    <span class="co">// 2012-12-27T22:07:22.123Z</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>ITU<span class="op">.</span><span class="fu">formatUtcMilli</span><span class="op">(</span>offsetDateTime<span class="op">));</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>    <span class="co">// 2012-12-27T22:07:22.123456Z</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>ITU<span class="op">.</span><span class="fu">formatUtcMicro</span><span class="op">(</span>offsetDateTime<span class="op">));</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>    <span class="co">// 2012-12-27T22:07:22.123456789Z</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>ITU<span class="op">.</span><span class="fu">formatUtcNano</span><span class="op">(</span>offsetDateTime<span class="op">));</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>com.fasterxml.uuid</title><link>https://mccue.dev/pages/12-21-23-java-library-of-the-day-21</link><description></description><pubDate>Thu, 21 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>com.fasterxml.uuid</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">com.fasterxml.uuid</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/com.fasterxml.uuid/java-uuid-generator"><code>com.fasterxml.uuid/java-uuid-generator</code></a></li>
<li>Module Name: <code>com.fasterxml.uuid</code></li>
<li>GitHub: <a href="https://github.com/cowtowncoder/java-uuid-generator"><code>cowtowncoder/java-uuid-generator</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogMTg1Ljc2NnB4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii04IC04IDE4NS43NjU2MjUgMTM0IiByb2xlPSJncmFwaGljcy1kb2N1bWVudCBkb2N1bWVudCIgYXJpYS1yb2xlZGVzY3JpcHRpb249ImZsb3djaGFydC12MiI+PHN0eWxlPiNteS1zdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O2ZpbGw6IzMzMzt9I215LXN2ZyAuZXJyb3ItaWNvbntmaWxsOiM1NTIyMjI7fSNteS1zdmcgLmVycm9yLXRleHR7ZmlsbDojNTUyMjIyO3N0cm9rZTojNTUyMjIyO30jbXktc3ZnIC5lZGdlLXRoaWNrbmVzcy1ub3JtYWx7c3Ryb2tlLXdpZHRoOjJweDt9I215LXN2ZyAuZWRnZS10aGlja25lc3MtdGhpY2t7c3Ryb2tlLXdpZHRoOjMuNXB4O30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tc29saWR7c3Ryb2tlLWRhc2hhcnJheTowO30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tZGFzaGVke3N0cm9rZS1kYXNoYXJyYXk6Mzt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLWRvdHRlZHtzdHJva2UtZGFzaGFycmF5OjI7fSNteS1zdmcgLm1hcmtlcntmaWxsOiMzMzMzMzM7c3Ryb2tlOiMzMzMzMzM7fSNteS1zdmcgLm1hcmtlci5jcm9zc3tzdHJva2U6IzMzMzMzMzt9I215LXN2ZyBzdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O30jbXktc3ZnIC5sYWJlbHtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Y29sb3I6IzMzMzt9I215LXN2ZyAuY2x1c3Rlci1sYWJlbCB0ZXh0e2ZpbGw6IzMzMzt9I215LXN2ZyAuY2x1c3Rlci1sYWJlbCBzcGFuLCNteS1zdmcgcHtjb2xvcjojMzMzO30jbXktc3ZnIC5sYWJlbCB0ZXh0LCNteS1zdmcgc3BhbiwjbXktc3ZnIHB7ZmlsbDojMzMzO2NvbG9yOiMzMzM7fSNteS1zdmcgLm5vZGUgcmVjdCwjbXktc3ZnIC5ub2RlIGNpcmNsZSwjbXktc3ZnIC5ub2RlIGVsbGlwc2UsI215LXN2ZyAubm9kZSBwb2x5Z29uLCNteS1zdmcgLm5vZGUgcGF0aHtmaWxsOiNFQ0VDRkY7c3Ryb2tlOiM5MzcwREI7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAuZmxvd2NoYXJ0LWxhYmVsIHRleHR7dGV4dC1hbmNob3I6bWlkZGxlO30jbXktc3ZnIC5ub2RlIC5rYXRleCBwYXRoe2ZpbGw6IzAwMDtzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5ub2RlIC5sYWJlbHt0ZXh0LWFsaWduOmNlbnRlcjt9I215LXN2ZyAubm9kZS5jbGlja2FibGV7Y3Vyc29yOnBvaW50ZXI7fSNteS1zdmcgLmFycm93aGVhZFBhdGh7ZmlsbDojMzMzMzMzO30jbXktc3ZnIC5lZGdlUGF0aCAucGF0aHtzdHJva2U6IzMzMzMzMztzdHJva2Utd2lkdGg6Mi4wcHg7fSNteS1zdmcgLmZsb3djaGFydC1saW5re3N0cm9rZTojMzMzMzMzO2ZpbGw6bm9uZTt9I215LXN2ZyAuZWRnZUxhYmVse2JhY2tncm91bmQtY29sb3I6I2U4ZThlODt0ZXh0LWFsaWduOmNlbnRlcjt9I215LXN2ZyAuZWRnZUxhYmVsIHJlY3R7b3BhY2l0eTowLjU7YmFja2dyb3VuZC1jb2xvcjojZThlOGU4O2ZpbGw6I2U4ZThlODt9I215LXN2ZyAubGFiZWxCa2d7YmFja2dyb3VuZC1jb2xvcjpyZ2JhKDIzMiwgMjMyLCAyMzIsIDAuNSk7fSNteS1zdmcgLmNsdXN0ZXIgcmVjdHtmaWxsOiNmZmZmZGU7c3Ryb2tlOiNhYWFhMzM7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAuY2x1c3RlciB0ZXh0e2ZpbGw6IzMzMzt9I215LXN2ZyAuY2x1c3RlciBzcGFuLCNteS1zdmcgcHtjb2xvcjojMzMzO30jbXktc3ZnIGRpdi5tZXJtYWlkVG9vbHRpcHtwb3NpdGlvbjphYnNvbHV0ZTt0ZXh0LWFsaWduOmNlbnRlcjttYXgtd2lkdGg6MjAwcHg7cGFkZGluZzoycHg7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxMnB4O2JhY2tncm91bmQ6aHNsKDgwLCAxMDAlLCA5Ni4yNzQ1MDk4MDM5JSk7Ym9yZGVyOjFweCBzb2xpZCAjYWFhYTMzO2JvcmRlci1yYWRpdXM6MnB4O3BvaW50ZXItZXZlbnRzOm5vbmU7ei1pbmRleDoxMDA7fSNteS1zdmcgLmZsb3djaGFydFRpdGxlVGV4dHt0ZXh0LWFuY2hvcjptaWRkbGU7Zm9udC1zaXplOjE4cHg7ZmlsbDojMzMzO30jbXktc3ZnIDpyb290ey0tbWVybWFpZC1mb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7fSNteS1zdmcgLmdyZWVuJmd0Oyp7c3Ryb2tlOnJnYigyNTUsIDAsIDApIWltcG9ydGFudDt9I215LXN2ZyAuZ3JlZW4gc3BhbntzdHJva2U6cmdiKDI1NSwgMCwgMCkhaW1wb3J0YW50O308L3N0eWxlPjxnPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtcG9pbnRFbmQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjYiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjEyIiBtYXJrZXJIZWlnaHQ9IjEyIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMCAwIEwgMTAgNSBMIDAgMTAgeiIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LXBvaW50U3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjQuNSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTIiIG1hcmtlckhlaWdodD0iMTIiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAwIDUgTCAxMCAxMCBMIDEwIDAgeiIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNpcmNsZUVuZCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iMTEiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxjaXJjbGUgY3g9IjUiIGN5PSI1IiByPSI1IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY2lyY2xlU3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9Ii0xIiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48Y2lyY2xlIGN4PSI1IiBjeT0iNSIgcj0iNSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNyb3NzRW5kIiBjbGFzcz0ibWFya2VyIGNyb3NzIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDExIDExIiByZWZYPSIxMiIgcmVmWT0iNS4yIiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDEsMSBsIDksOSBNIDEwLDEgbCAtOSw5IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAyOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY3Jvc3NTdGFydCIgY2xhc3M9Im1hcmtlciBjcm9zcyBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMSAxMSIgcmVmWD0iLTEiIHJlZlk9IjUuMiIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAxLDEgbCA5LDkgTSAxMCwxIGwgLTksOSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMjsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48ZyBjbGFzcz0icm9vdCI+PGcgY2xhc3M9ImNsdXN0ZXJzIi8+PGcgY2xhc3M9ImVkZ2VQYXRocyI+PHBhdGggZD0iTTg0Ljg4MywzNEw4NC44ODMsMzguMTY3Qzg0Ljg4Myw0Mi4zMzMsODQuODgzLDUwLjY2Nyw4NC44ODMsNTguMTE3Qzg0Ljg4Myw2NS41NjcsODQuODgzLDcyLjEzMyw4NC44ODMsNzUuNDE3TDg0Ljg4Myw3OC43IiBpZD0iTC1zbGY0ai11dWlkLTAiIGNsYXNzPSJlZGdlLXRoaWNrbmVzcy1ub3JtYWwgZWRnZS1wYXR0ZXJuLXNvbGlkIGZsb3djaGFydC1saW5rIExTLXNsZjRqIExFLXV1aWQiIHN0eWxlPSJmaWxsOm5vbmU7IiBtYXJrZXItZW5kPSJ1cmwoI215LXN2Z19mbG93Y2hhcnQtcG9pbnRFbmQpIi8+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWxzIj48ZyBjbGFzcz0iZWRnZUxhYmVsIj48ZyBjbGFzcz0ibGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsIDApIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMCIgaGVpZ2h0PSIwIj48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9ImVkZ2VMYWJlbCI+PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjwvZz48ZyBjbGFzcz0ibm9kZXMiPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZGVmYXVsdCBmbG93Y2hhcnQtbGFiZWwiIGlkPSJmbG93Y2hhcnQtc2xmNGotMCIgZGF0YS1ub2RlPSJ0cnVlIiBkYXRhLWlkPSJzbGY0aiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoODQuODgyODEyNSwgMTcpIj48cmVjdCBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIiBzdHlsZT0iIiByeD0iMCIgcnk9IjAiIHg9Ii0zOS42ODc1IiB5PSItMTciIHdpZHRoPSI3OS4zNzUiIGhlaWdodD0iMzQiLz48ZyBjbGFzcz0ibGFiZWwiIHN0eWxlPSIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0zMi4xODc1LCAtOS41KSI+PHJlY3QvPjxmb3JlaWduT2JqZWN0IHdpZHRoPSI2NC4zNzUiIGhlaWdodD0iMTkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj5vcmcuc2xmNGo8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBncmVlbiBmbG93Y2hhcnQtbGFiZWwiIGlkPSJmbG93Y2hhcnQtdXVpZC0xIiBkYXRhLW5vZGU9InRydWUiIGRhdGEtaWQ9InV1aWQiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDg0Ljg4MjgxMjUsIDEwMSkiPjxyZWN0IGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiIHN0eWxlPSIiIHJ4PSIwIiByeT0iMCIgeD0iLTg0Ljg4MjgxMjUiIHk9Ii0xNyIgd2lkdGg9IjE2OS43NjU2MjUiIGhlaWdodD0iMzQiLz48ZyBjbGFzcz0ibGFiZWwiIHN0eWxlPSIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC03Ny4zODI4MTI1LCAtOS41KSI+PHJlY3QvPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIxNTQuNzY1NjI1IiBoZWlnaHQ9IjE5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+Y29tLmZhc3RlcnhtbC51dWlkPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjwvZz48L2c+PC9nPjwvc3ZnPg==" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>com.fasterxml.uuid</code> has methods to generate, and customize the generation of, UUIDs.</p>
<h2 id="why-use-it">Why use it</h2>
<p>Most of the time, folks use <code>UUID.randomUUID()</code> to get their universally unique identifiers. That makes a UUIDv4.</p>
<p>But the world of UUIDs is more varied than that and there are different kinds of UUIDs <a href="https://generate-uuid.com/which-uuid-version-should-you-use">that you might want to use</a>.</p>
<p>This includes <a href="https://uuid6.github.io/uuid6-ietf-draft/">UUIDv6</a> and <a href="https://uuid6.github.io/uuid6-ietf-draft/">UUIDv7</a>, which aren't referenced in the above link.</p>
<p>Fun fact though, this library <a href="https://cowtowncoder.medium.com/measuring-performance-of-java-uuid-fromstring-or-lack-thereof-d16a910fa32a">predates the addition of <code>UUID.randomUUID()</code> to the standard library</a>.</p>
<h2 id="getting-started">Getting Started</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">fasterxml</span><span class="op">.</span><span class="im">uuid</span><span class="op">.</span><span class="im">Generators</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    var uuidv7 <span class="op">=</span> Generators</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">timeBasedEpochGenerator</span><span class="op">().</span><span class="fu">generate</span><span class="op">();</span> <span class="co">// Version 7</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>uuidv7<span class="op">);</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    var uuidv5 <span class="op">=</span> Generators</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">nameBasedGenerator</span><span class="op">()</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">generate</span><span class="op">(</span><span class="st">&quot;string to hash&quot;</span><span class="op">);</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>uuidv5<span class="op">);</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>dev.mccue.microhttp.session</title><link>https://mccue.dev/pages/12-20-23-java-library-of-the-day-20</link><description></description><pubDate>Wed, 20 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>dev.mccue.microhttp.session</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">dev.mccue.microhttp.session</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/dev.mccue/microhttp-session"><code>dev.mccue/microhttp-session</code></a></li>
<li>Module Name: <code>dev.mccue.microhttp.session</code></li>
<li>GitHub: <a href="https://github.com/bowbahdoe/microhttp-session"><code>bowbahdoe/microhttp-session</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogMTI3NC4xN3B4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii04IC04IDEyNzQuMTcxODc1IDIxOCIgcm9sZT0iZ3JhcGhpY3MtZG9jdW1lbnQgZG9jdW1lbnQiIGFyaWEtcm9sZWRlc2NyaXB0aW9uPSJmbG93Y2hhcnQtdjIiPjxzdHlsZT4jbXktc3Zne2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtmb250LXNpemU6MTZweDtmaWxsOiMzMzM7fSNteS1zdmcgLmVycm9yLWljb257ZmlsbDojNTUyMjIyO30jbXktc3ZnIC5lcnJvci10ZXh0e2ZpbGw6IzU1MjIyMjtzdHJva2U6IzU1MjIyMjt9I215LXN2ZyAuZWRnZS10aGlja25lc3Mtbm9ybWFse3N0cm9rZS13aWR0aDoycHg7fSNteS1zdmcgLmVkZ2UtdGhpY2tuZXNzLXRoaWNre3N0cm9rZS13aWR0aDozLjVweDt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLXNvbGlke3N0cm9rZS1kYXNoYXJyYXk6MDt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLWRhc2hlZHtzdHJva2UtZGFzaGFycmF5OjM7fSNteS1zdmcgLmVkZ2UtcGF0dGVybi1kb3R0ZWR7c3Ryb2tlLWRhc2hhcnJheToyO30jbXktc3ZnIC5tYXJrZXJ7ZmlsbDojMzMzMzMzO3N0cm9rZTojMzMzMzMzO30jbXktc3ZnIC5tYXJrZXIuY3Jvc3N7c3Ryb2tlOiMzMzMzMzM7fSNteS1zdmcgc3Zne2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtmb250LXNpemU6MTZweDt9I215LXN2ZyAubGFiZWx7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2NvbG9yOiMzMzM7fSNteS1zdmcgLmNsdXN0ZXItbGFiZWwgdGV4dHtmaWxsOiMzMzM7fSNteS1zdmcgLmNsdXN0ZXItbGFiZWwgc3BhbiwjbXktc3ZnIHB7Y29sb3I6IzMzMzt9I215LXN2ZyAubGFiZWwgdGV4dCwjbXktc3ZnIHNwYW4sI215LXN2ZyBwe2ZpbGw6IzMzMztjb2xvcjojMzMzO30jbXktc3ZnIC5ub2RlIHJlY3QsI215LXN2ZyAubm9kZSBjaXJjbGUsI215LXN2ZyAubm9kZSBlbGxpcHNlLCNteS1zdmcgLm5vZGUgcG9seWdvbiwjbXktc3ZnIC5ub2RlIHBhdGh7ZmlsbDojRUNFQ0ZGO3N0cm9rZTojOTM3MERCO3N0cm9rZS13aWR0aDoxcHg7fSNteS1zdmcgLmZsb3djaGFydC1sYWJlbCB0ZXh0e3RleHQtYW5jaG9yOm1pZGRsZTt9I215LXN2ZyAubm9kZSAua2F0ZXggcGF0aHtmaWxsOiMwMDA7c3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAubm9kZSAubGFiZWx7dGV4dC1hbGlnbjpjZW50ZXI7fSNteS1zdmcgLm5vZGUuY2xpY2thYmxle2N1cnNvcjpwb2ludGVyO30jbXktc3ZnIC5hcnJvd2hlYWRQYXRoe2ZpbGw6IzMzMzMzMzt9I215LXN2ZyAuZWRnZVBhdGggLnBhdGh7c3Ryb2tlOiMzMzMzMzM7c3Ryb2tlLXdpZHRoOjIuMHB4O30jbXktc3ZnIC5mbG93Y2hhcnQtbGlua3tzdHJva2U6IzMzMzMzMztmaWxsOm5vbmU7fSNteS1zdmcgLmVkZ2VMYWJlbHtiYWNrZ3JvdW5kLWNvbG9yOiNlOGU4ZTg7dGV4dC1hbGlnbjpjZW50ZXI7fSNteS1zdmcgLmVkZ2VMYWJlbCByZWN0e29wYWNpdHk6MC41O2JhY2tncm91bmQtY29sb3I6I2U4ZThlODtmaWxsOiNlOGU4ZTg7fSNteS1zdmcgLmxhYmVsQmtne2JhY2tncm91bmQtY29sb3I6cmdiYSgyMzIsIDIzMiwgMjMyLCAwLjUpO30jbXktc3ZnIC5jbHVzdGVyIHJlY3R7ZmlsbDojZmZmZmRlO3N0cm9rZTojYWFhYTMzO3N0cm9rZS13aWR0aDoxcHg7fSNteS1zdmcgLmNsdXN0ZXIgdGV4dHtmaWxsOiMzMzM7fSNteS1zdmcgLmNsdXN0ZXIgc3BhbiwjbXktc3ZnIHB7Y29sb3I6IzMzMzt9I215LXN2ZyBkaXYubWVybWFpZFRvb2x0aXB7cG9zaXRpb246YWJzb2x1dGU7dGV4dC1hbGlnbjpjZW50ZXI7bWF4LXdpZHRoOjIwMHB4O3BhZGRpbmc6MnB4O2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtmb250LXNpemU6MTJweDtiYWNrZ3JvdW5kOmhzbCg4MCwgMTAwJSwgOTYuMjc0NTA5ODAzOSUpO2JvcmRlcjoxcHggc29saWQgI2FhYWEzMztib3JkZXItcmFkaXVzOjJweDtwb2ludGVyLWV2ZW50czpub25lO3otaW5kZXg6MTAwO30jbXktc3ZnIC5mbG93Y2hhcnRUaXRsZVRleHR7dGV4dC1hbmNob3I6bWlkZGxlO2ZvbnQtc2l6ZToxOHB4O2ZpbGw6IzMzMzt9I215LXN2ZyA6cm9vdHstLW1lcm1haWQtZm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO30jbXktc3ZnIC5ncmVlbiZndDsqe3N0cm9rZTpyZ2IoMjU1LCAwLCAwKSFpbXBvcnRhbnQ7fSNteS1zdmcgLmdyZWVuIHNwYW57c3Ryb2tlOnJnYigyNTUsIDAsIDApIWltcG9ydGFudDt9PC9zdHlsZT48Zz48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LXBvaW50RW5kIiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI2IiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMiIgbWFya2VySGVpZ2h0PSIxMiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDAgMCBMIDEwIDUgTCAwIDEwIHoiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1wb2ludFN0YXJ0IiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI0LjUiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjEyIiBtYXJrZXJIZWlnaHQ9IjEyIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMCA1IEwgMTAgMTAgTCAxMCAwIHoiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jaXJjbGVFbmQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjExIiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48Y2lyY2xlIGN4PSI1IiBjeT0iNSIgcj0iNSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNpcmNsZVN0YXJ0IiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSItMSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PGNpcmNsZSBjeD0iNSIgY3k9IjUiIHI9IjUiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jcm9zc0VuZCIgY2xhc3M9Im1hcmtlciBjcm9zcyBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMSAxMSIgcmVmWD0iMTIiIHJlZlk9IjUuMiIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAxLDEgbCA5LDkgTSAxMCwxIGwgLTksOSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMjsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNyb3NzU3RhcnQiIGNsYXNzPSJtYXJrZXIgY3Jvc3MgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTEgMTEiIHJlZlg9Ii0xIiByZWZZPSI1LjIiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMSwxIGwgOSw5IE0gMTAsMSBsIC05LDkiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDI7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PGcgY2xhc3M9InJvb3QiPjxnIGNsYXNzPSJjbHVzdGVycyIvPjxnIGNsYXNzPSJlZGdlUGF0aHMiPjxwYXRoIGQ9Ik0zNzguNTE2LDI1LjQ2NUwzMzcuNTczLDMxLjA1NEMyOTYuNjMsMzYuNjQzLDIxNC43NDUsNDcuODIyLDE3My44MDIsNTYuNjk0QzEzMi44NTksNjUuNTY3LDEzMi44NTksNzIuMTMzLDEzMi44NTksNzUuNDE3TDEzMi44NTksNzguNyIgaWQ9IkwtbWljcm9odHRwLW1pY3JvaHR0cHNldGNvb2tpZS0wIiBjbGFzcz0iZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1taWNyb2h0dHAgTEUtbWljcm9odHRwc2V0Y29va2llIiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLWVuZD0idXJsKCNteS1zdmdfZmxvd2NoYXJ0LXBvaW50RW5kKSIvPjxwYXRoIGQ9Ik00NDAuNTIzLDM0TDQ0MC41MjMsMzguMTY3QzQ0MC41MjMsNDIuMzMzLDQ0MC41MjMsNTAuNjY3LDQ0MC41MjMsNTguMTE3QzQ0MC41MjMsNjUuNTY3LDQ0MC41MjMsNzIuMTMzLDQ0MC41MjMsNzUuNDE3TDQ0MC41MjMsNzguNyIgaWQ9IkwtbWljcm9odHRwLW1pY3JvaHR0cGNvb2tpZXMtMCIgY2xhc3M9ImVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtbWljcm9odHRwIExFLW1pY3JvaHR0cGNvb2tpZXMiIHN0eWxlPSJmaWxsOm5vbmU7IiBtYXJrZXItZW5kPSJ1cmwoI215LXN2Z19mbG93Y2hhcnQtcG9pbnRFbmQpIi8+PHBhdGggZD0iTTUwMi41MzEsMjUuNjhMNTQyLjIwMiwzMS4yMzNDNTgxLjg3MiwzNi43ODcsNjYxLjIxNCw0Ny44OTMsNzAwLjg4NCw1Ni43M0M3NDAuNTU1LDY1LjU2Nyw3NDAuNTU1LDcyLjEzMyw3NDAuNTU1LDc1LjQxN0w3NDAuNTU1LDc4LjciIGlkPSJMLW1pY3JvaHR0cC1taWNyb2h0dHAtaGFuZGxlci0wIiBjbGFzcz0iZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1taWNyb2h0dHAgTEUtbWljcm9odHRwLWhhbmRsZXIiIHN0eWxlPSJmaWxsOm5vbmU7IiBtYXJrZXItZW5kPSJ1cmwoI215LXN2Z19mbG93Y2hhcnQtcG9pbnRFbmQpIi8+PHBhdGggZD0iTTEzMi44NTksMTE4TDEzMi44NTksMTIyLjE2N0MxMzIuODU5LDEyNi4zMzMsMTMyLjg1OSwxMzQuNjY3LDIxMi41NDcsMTQ0LjM0MUMyOTIuMjM1LDE1NC4wMTUsNDUxLjYxLDE2NS4wMyw1MzEuMjk4LDE3MC41MzhMNjEwLjk4NiwxNzYuMDQ1IiBpZD0iTC1taWNyb2h0dHBzZXRjb29raWUtbWljcm9odHRwc2Vzc2lvbi0wIiBjbGFzcz0iZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1taWNyb2h0dHBzZXRjb29raWUgTEUtbWljcm9odHRwc2Vzc2lvbiIgc3R5bGU9ImZpbGw6bm9uZTsiIG1hcmtlci1lbmQ9InVybCgjbXktc3ZnX2Zsb3djaGFydC1wb2ludEVuZCkiLz48cGF0aCBkPSJNNDQwLjUyMywxMThMNDQwLjUyMywxMjIuMTY3QzQ0MC41MjMsMTI2LjMzMyw0NDAuNTIzLDEzNC42NjcsNDY5LjQxNCwxNDIuODc4QzQ5OC4zMDQsMTUxLjA4OCw1NTYuMDg0LDE1OS4xNzcsNTg0Ljk3NCwxNjMuMjIxTDYxMy44NjUsMTY3LjI2NSIgaWQ9IkwtbWljcm9odHRwY29va2llcy1taWNyb2h0dHBzZXNzaW9uLTAiIGNsYXNzPSJlZGdlLXRoaWNrbmVzcy1ub3JtYWwgZWRnZS1wYXR0ZXJuLXNvbGlkIGZsb3djaGFydC1saW5rIExTLW1pY3JvaHR0cGNvb2tpZXMgTEUtbWljcm9odHRwc2Vzc2lvbiIgc3R5bGU9ImZpbGw6bm9uZTsiIG1hcmtlci1lbmQ9InVybCgjbXktc3ZnX2Zsb3djaGFydC1wb2ludEVuZCkiLz48cGF0aCBkPSJNNzQwLjU1NSwxMThMNzQwLjU1NSwxMjIuMTY3Qzc0MC41NTUsMTI2LjMzMyw3NDAuNTU1LDEzNC42NjcsNzQwLjU1NSwxNDIuMTE3Qzc0MC41NTUsMTQ5LjU2Nyw3NDAuNTU1LDE1Ni4xMzMsNzQwLjU1NSwxNTkuNDE3TDc0MC41NTUsMTYyLjciIGlkPSJMLW1pY3JvaHR0cC1oYW5kbGVyLW1pY3JvaHR0cHNlc3Npb24tMCIgY2xhc3M9ImVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtbWljcm9odHRwLWhhbmRsZXIgTEUtbWljcm9odHRwc2Vzc2lvbiIgc3R5bGU9ImZpbGw6bm9uZTsiIG1hcmtlci1lbmQ9InVybCgjbXktc3ZnX2Zsb3djaGFydC1wb2ludEVuZCkiLz48cGF0aCBkPSJNOTkyLjMzNiwxMThMOTkyLjMzNiwxMjIuMTY3Qzk5Mi4zMzYsMTI2LjMzMyw5OTIuMzM2LDEzNC42NjcsOTY4LjIyOSwxNDIuODU1Qzk0NC4xMjIsMTUxLjA0Myw4OTUuOTA4LDE1OS4wODUsODcxLjgwMSwxNjMuMTA3TDg0Ny42OTQsMTY3LjEyOCIgaWQ9IkwtYXN5bmMtbWljcm9odHRwc2Vzc2lvbi0wIiBjbGFzcz0iZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1hc3luYyBMRS1taWNyb2h0dHBzZXNzaW9uIiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLWVuZD0idXJsKCNteS1zdmdfZmxvd2NoYXJ0LXBvaW50RW5kKSIvPjxwYXRoIGQ9Ik0xMTg4LjUzMSwxMThMMTE4OC41MzEsMTIyLjE2N0MxMTg4LjUzMSwxMjYuMzMzLDExODguNTMxLDEzNC42NjcsMTEzNS40NjIsMTQzLjgwOUMxMDgyLjM5MiwxNTIuOTUxLDk3Ni4yNTIsMTYyLjkwMiw5MjMuMTgzLDE2Ny44NzhMODcwLjExMywxNzIuODUzIiBpZD0iTC1qc29uLW1pY3JvaHR0cHNlc3Npb24tMCIgY2xhc3M9ImVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtanNvbiBMRS1taWNyb2h0dHBzZXNzaW9uIiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLWVuZD0idXJsKCNteS1zdmdfZmxvd2NoYXJ0LXBvaW50RW5kKSIvPjwvZz48ZyBjbGFzcz0iZWRnZUxhYmVscyI+PGcgY2xhc3M9ImVkZ2VMYWJlbCI+PGcgY2xhc3M9ImxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAwKSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjAiIGhlaWdodD0iMCI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0iZWRnZUxhYmVsIj48ZyBjbGFzcz0ibGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsIDApIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMCIgaGVpZ2h0PSIwIj48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9ImVkZ2VMYWJlbCI+PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWwiPjxnIGNsYXNzPSJsYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMCkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIwIiBoZWlnaHQ9IjAiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0iZWRnZUxhYmVsIj48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbCI+PGcgY2xhc3M9ImxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAwKSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjAiIGhlaWdodD0iMCI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0iZWRnZUxhYmVsIj48ZyBjbGFzcz0ibGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsIDApIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMCIgaGVpZ2h0PSIwIj48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9ImVkZ2VMYWJlbCI+PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWwiPjxnIGNsYXNzPSJsYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMCkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIwIiBoZWlnaHQ9IjAiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0iZWRnZUxhYmVsIj48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbCI+PGcgY2xhc3M9ImxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAwKSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjAiIGhlaWdodD0iMCI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0iZWRnZUxhYmVsIj48ZyBjbGFzcz0ibGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsIDApIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMCIgaGVpZ2h0PSIwIj48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9ImVkZ2VMYWJlbCI+PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjwvZz48ZyBjbGFzcz0ibm9kZXMiPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZGVmYXVsdCBmbG93Y2hhcnQtbGFiZWwiIGlkPSJmbG93Y2hhcnQtbWljcm9odHRwLTAiIGRhdGEtbm9kZT0idHJ1ZSIgZGF0YS1pZD0ibWljcm9odHRwIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg0NDAuNTIzNDM3NSwgMTcpIj48cmVjdCBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIiBzdHlsZT0iIiByeD0iMCIgcnk9IjAiIHg9Ii02Mi4wMDc4MTI1IiB5PSItMTciIHdpZHRoPSIxMjQuMDE1NjI1IiBoZWlnaHQ9IjM0Ii8+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNTQuNTA3ODEyNSwgLTkuNSkiPjxyZWN0Lz48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMTA5LjAxNTYyNSIgaGVpZ2h0PSIxOSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPm9yZy5taWNyb2h0dHA8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IGZsb3djaGFydC1sYWJlbCIgaWQ9ImZsb3djaGFydC1taWNyb2h0dHBzZXRjb29raWUtMSIgZGF0YS1ub2RlPSJ0cnVlIiBkYXRhLWlkPSJtaWNyb2h0dHBzZXRjb29raWUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEzMi44NTkzNzUsIDEwMSkiPjxyZWN0IGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiIHN0eWxlPSIiIHJ4PSIwIiByeT0iMCIgeD0iLTEzMi44NTkzNzUiIHk9Ii0xNyIgd2lkdGg9IjI2NS43MTg3NSIgaGVpZ2h0PSIzNCIvPjxnIGNsYXNzPSJsYWJlbCIgc3R5bGU9IiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTEyNS4zNTkzNzUsIC05LjUpIj48cmVjdC8+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjI1MC43MTg3NSIgaGVpZ2h0PSIxOSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPmRldi5tY2N1ZS5taWNyb2h0dHAuc2V0Y29va2llPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZGVmYXVsdCBmbG93Y2hhcnQtbGFiZWwiIGlkPSJmbG93Y2hhcnQtbWljcm9odHRwY29va2llcy00IiBkYXRhLW5vZGU9InRydWUiIGRhdGEtaWQ9Im1pY3JvaHR0cGNvb2tpZXMiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQ0MC41MjM0Mzc1LCAxMDEpIj48cmVjdCBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIiBzdHlsZT0iIiByeD0iMCIgcnk9IjAiIHg9Ii0xMjQuODA0Njg3NSIgeT0iLTE3IiB3aWR0aD0iMjQ5LjYwOTM3NSIgaGVpZ2h0PSIzNCIvPjxnIGNsYXNzPSJsYWJlbCIgc3R5bGU9IiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTExNy4zMDQ2ODc1LCAtOS41KSI+PHJlY3QvPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIyMzQuNjA5Mzc1IiBoZWlnaHQ9IjE5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+ZGV2Lm1jY3VlLm1pY3JvaHR0cC5jb29raWVzPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZGVmYXVsdCBmbG93Y2hhcnQtbGFiZWwiIGlkPSJmbG93Y2hhcnQtbWljcm9odHRwLWhhbmRsZXItNyIgZGF0YS1ub2RlPSJ0cnVlIiBkYXRhLWlkPSJtaWNyb2h0dHAtaGFuZGxlciIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNzQwLjU1NDY4NzUsIDEwMSkiPjxyZWN0IGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiIHN0eWxlPSIiIHJ4PSIwIiByeT0iMCIgeD0iLTEyNS4yMjY1NjI1IiB5PSItMTciIHdpZHRoPSIyNTAuNDUzMTI1IiBoZWlnaHQ9IjM0Ii8+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTE3LjcyNjU2MjUsIC05LjUpIj48cmVjdC8+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjIzNS40NTMxMjUiIGhlaWdodD0iMTkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj5kZXYubWNjdWUubWljcm9odHRwLmhhbmRsZXI8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IGZsb3djaGFydC1sYWJlbCIgaWQ9ImZsb3djaGFydC1hc3luYy0xMCIgZGF0YS1ub2RlPSJ0cnVlIiBkYXRhLWlkPSJhc3luYyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOTkyLjMzNTkzNzUsIDEwMSkiPjxyZWN0IGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiIHN0eWxlPSIiIHJ4PSIwIiByeT0iMCIgeD0iLTc2LjU1NDY4NzUiIHk9Ii0xNyIgd2lkdGg9IjE1My4xMDkzNzUiIGhlaWdodD0iMzQiLz48ZyBjbGFzcz0ibGFiZWwiIHN0eWxlPSIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC02OS4wNTQ2ODc1LCAtOS41KSI+PHJlY3QvPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIxMzguMTA5Mzc1IiBoZWlnaHQ9IjE5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+ZGV2Lm1jY3VlLmFzeW5jPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZGVmYXVsdCBmbG93Y2hhcnQtbGFiZWwiIGlkPSJmbG93Y2hhcnQtanNvbi0xMSIgZGF0YS1ub2RlPSJ0cnVlIiBkYXRhLWlkPSJqc29uIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMTg4LjUzMTI1LCAxMDEpIj48cmVjdCBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIiBzdHlsZT0iIiByeD0iMCIgcnk9IjAiIHg9Ii02OS42NDA2MjUiIHk9Ii0xNyIgd2lkdGg9IjEzOS4yODEyNSIgaGVpZ2h0PSIzNCIvPjxnIGNsYXNzPSJsYWJlbCIgc3R5bGU9IiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTYyLjE0MDYyNSwgLTkuNSkiPjxyZWN0Lz48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMTI0LjI4MTI1IiBoZWlnaHQ9IjE5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+ZGV2Lm1jY3VlLmpzb248L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBncmVlbiBmbG93Y2hhcnQtbGFiZWwiIGlkPSJmbG93Y2hhcnQtbWljcm9odHRwc2Vzc2lvbi0xMiIgZGF0YS1ub2RlPSJ0cnVlIiBkYXRhLWlkPSJtaWNyb2h0dHBzZXNzaW9uIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg3NDAuNTU0Njg3NSwgMTg1KSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjAiIHJ5PSIwIiB4PSItMTI0LjI4MTI1IiB5PSItMTciIHdpZHRoPSIyNDguNTYyNSIgaGVpZ2h0PSIzNCIvPjxnIGNsYXNzPSJsYWJlbCIgc3R5bGU9IiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTExNi43ODEyNSwgLTkuNSkiPjxyZWN0Lz48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMjMzLjU2MjUiIGhlaWdodD0iMTkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj5kZXYubWNjdWUubWljcm9odHRwLnNlc3Npb248L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjwvZz48L2c+PC9zdmc+" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>dev.mccue.microhttp.session</code> provides an interface for encoding session data in microhttp responses and decoding session data from microhttp requests.</p>
<p>Last one from me for this series, I promise. This just took a lot of build up.</p>
<h2 id="why-use-it">Why use it</h2>
<p>If you are making a classical web app, <a href="https://htmx.org/essays/splitting-your-apis/">and maybe you should</a>, then you will want to store persistent data about your users.</p>
<p>Most often logins, but other things like <a href="https://flask.palletsprojects.com/en/2.3.x/patterns/flashing/">flash data</a> are also fair game.</p>
<p>This provides a composable interface to that capability.</p>
<h2 id="getting-started">Getting Started</h2>
<p>This example uses <a href="https://openjdk.org/jeps/429">ScopedValue</a>s so will require preview features.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.</span><span class="im">JsonDecoder</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">handler</span><span class="op">.</span><span class="im">DelegatingHandler</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">handler</span><span class="op">.</span><span class="im">RouteHandler</span><span class="op">;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">html</span><span class="op">.</span><span class="im">HtmlResponse</span><span class="op">;</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">session</span><span class="op">.</span><span class="im">ScopedSession</span><span class="op">;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">session</span><span class="op">.</span><span class="im">SessionManager</span><span class="op">;</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">session</span><span class="op">.</span><span class="im">SessionStore</span><span class="op">;</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">EventLoop</span><span class="op">;</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">Options</span><span class="op">;</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">List</span><span class="op">;</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">regex</span><span class="op">.</span><span class="im">Pattern</span><span class="op">;</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">static</span><span class="im"> dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">html</span><span class="op">.</span><span class="im">Html</span><span class="op">.</span><span class="im">HTML</span><span class="op">;</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="kw">throws</span> <span class="bu">Exception</span> <span class="op">{</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>    var indexHandler <span class="op">=</span> RouteHandler<span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;GET&quot;</span><span class="op">,</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Pattern</span><span class="op">.</span><span class="fu">compile</span><span class="op">(</span><span class="st">&quot;/&quot;</span><span class="op">),</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>            request <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>                var name <span class="op">=</span> ScopedSession<span class="op">.</span><span class="fu">get</span><span class="op">()</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>                        <span class="op">.</span><span class="fu">get</span><span class="op">(</span><span class="st">&quot;name&quot;</span><span class="op">,</span> JsonDecoder<span class="op">::</span>string<span class="op">)</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>                        <span class="op">.</span><span class="fu">orElse</span><span class="op">(</span><span class="st">&quot;?&quot;</span><span class="op">);</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="kw">new</span> <span class="fu">HtmlResponse</span><span class="op">(</span><span class="bu">HTML</span><span class="op">.</span><span class="st">&quot;&quot;&quot;</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>                        <span class="op">&lt;</span>h1<span class="op">&gt;</span> Your name is \<span class="op">{</span>name<span class="op">}</span> <span class="op">&lt;/</span>h1<span class="op">&gt;</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a>                        <span class="st">&quot;&quot;&quot;);</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a>    var nameHandler <span class="op">=</span> RouteHandler<span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;GET&quot;</span><span class="op">,</span></span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Pattern</span><span class="op">.</span><span class="fu">compile</span><span class="op">(</span><span class="st">&quot;/name/(?&lt;name&gt;.+)&quot;</span><span class="op">),</span></span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a>            <span class="op">(</span>matcher<span class="op">,</span> request<span class="op">)</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a>                ScopedSession<span class="op">.</span><span class="fu">update</span><span class="op">(</span>data <span class="op">-&gt;</span></span>
<span id="cb1-37"><a href="#cb1-37" aria-hidden="true" tabindex="-1"></a>                        data<span class="op">.</span><span class="fu">with</span><span class="op">(</span><span class="st">&quot;name&quot;</span><span class="op">,</span> matcher<span class="op">.</span><span class="fu">group</span><span class="op">(</span><span class="st">&quot;name&quot;</span><span class="op">)));</span></span>
<span id="cb1-38"><a href="#cb1-38" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="kw">new</span> <span class="fu">HtmlResponse</span><span class="op">(</span><span class="bu">HTML</span><span class="op">.</span><span class="st">&quot;Go back to /&quot;</span><span class="op">);</span></span>
<span id="cb1-39"><a href="#cb1-39" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb1-40"><a href="#cb1-40" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb1-41"><a href="#cb1-41" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-42"><a href="#cb1-42" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-43"><a href="#cb1-43" aria-hidden="true" tabindex="-1"></a>    var notFound <span class="op">=</span> <span class="kw">new</span> <span class="fu">HtmlResponse</span><span class="op">(</span><span class="dv">404</span><span class="op">,</span> <span class="bu">HTML</span><span class="op">.</span><span class="st">&quot;Not Found&quot;</span><span class="op">);</span></span>
<span id="cb1-44"><a href="#cb1-44" aria-hidden="true" tabindex="-1"></a>    var error <span class="op">=</span> <span class="kw">new</span> <span class="fu">HtmlResponse</span><span class="op">(</span><span class="dv">500</span><span class="op">,</span> <span class="bu">HTML</span><span class="op">.</span><span class="st">&quot;Internal Server Error&quot;</span><span class="op">);</span></span>
<span id="cb1-45"><a href="#cb1-45" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-46"><a href="#cb1-46" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Can also store in encrypted cookies</span></span>
<span id="cb1-47"><a href="#cb1-47" aria-hidden="true" tabindex="-1"></a>    var store <span class="op">=</span> SessionStore<span class="op">.</span><span class="fu">inMemory</span><span class="op">();</span></span>
<span id="cb1-48"><a href="#cb1-48" aria-hidden="true" tabindex="-1"></a>    var manager <span class="op">=</span> SessionManager<span class="op">.</span><span class="fu">builder</span><span class="op">()</span></span>
<span id="cb1-49"><a href="#cb1-49" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">store</span><span class="op">(</span>store<span class="op">)</span></span>
<span id="cb1-50"><a href="#cb1-50" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">build</span><span class="op">();</span></span>
<span id="cb1-51"><a href="#cb1-51" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-52"><a href="#cb1-52" aria-hidden="true" tabindex="-1"></a>    var rootHandler <span class="op">=</span> ScopedSession<span class="op">.</span><span class="fu">wrap</span><span class="op">(</span>manager<span class="op">,</span></span>
<span id="cb1-53"><a href="#cb1-53" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="fu">DelegatingHandler</span><span class="op">(</span><span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>indexHandler<span class="op">,</span> nameHandler<span class="op">),</span> notFound<span class="op">)</span></span>
<span id="cb1-54"><a href="#cb1-54" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb1-55"><a href="#cb1-55" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-56"><a href="#cb1-56" aria-hidden="true" tabindex="-1"></a>    var eventLoop <span class="op">=</span> <span class="kw">new</span> <span class="fu">EventLoop</span><span class="op">((</span>request<span class="op">,</span> callback<span class="op">)</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb1-57"><a href="#cb1-57" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb1-58"><a href="#cb1-58" aria-hidden="true" tabindex="-1"></a>            callback<span class="op">.</span><span class="fu">accept</span><span class="op">(</span>rootHandler<span class="op">.</span><span class="fu">handle</span><span class="op">(</span>request<span class="op">).</span><span class="fu">intoResponse</span><span class="op">());</span></span>
<span id="cb1-59"><a href="#cb1-59" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span><span class="bu">Exception</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-60"><a href="#cb1-60" aria-hidden="true" tabindex="-1"></a>            callback<span class="op">.</span><span class="fu">accept</span><span class="op">(</span>error<span class="op">.</span><span class="fu">intoResponse</span><span class="op">());</span></span>
<span id="cb1-61"><a href="#cb1-61" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-62"><a href="#cb1-62" aria-hidden="true" tabindex="-1"></a>    <span class="op">});</span></span>
<span id="cb1-63"><a href="#cb1-63" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-64"><a href="#cb1-64" aria-hidden="true" tabindex="-1"></a>    eventLoop<span class="op">.</span><span class="fu">start</span><span class="op">();</span></span>
<span id="cb1-65"><a href="#cb1-65" aria-hidden="true" tabindex="-1"></a>    eventLoop<span class="op">.</span><span class="fu">join</span><span class="op">();</span></span>
<span id="cb1-66"><a href="#cb1-66" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>dev.mccue.async</title><link>https://mccue.dev/pages/12-19-23-java-library-of-the-day-19</link><description></description><pubDate>Tue, 19 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>dev.mccue.async</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">dev.mccue.async</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/dev.mccue/async"><code>dev.mccue/async</code></a></li>
<li>Module Name: <code>dev.mccue.async</code></li>
<li>GitHub: <a href="https://github.com/bowbahdoe/java-async-utils"><code>bowbahdoe/java-async-utils</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogMTY5LjEwOXB4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii04IC04IDE2OS4xMDkzNzUgNTAiIHJvbGU9ImdyYXBoaWNzLWRvY3VtZW50IGRvY3VtZW50IiBhcmlhLXJvbGVkZXNjcmlwdGlvbj0iZmxvd2NoYXJ0LXYyIj48c3R5bGU+I215LXN2Z3tmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjE2cHg7ZmlsbDojMzMzO30jbXktc3ZnIC5lcnJvci1pY29ue2ZpbGw6IzU1MjIyMjt9I215LXN2ZyAuZXJyb3ItdGV4dHtmaWxsOiM1NTIyMjI7c3Ryb2tlOiM1NTIyMjI7fSNteS1zdmcgLmVkZ2UtdGhpY2tuZXNzLW5vcm1hbHtzdHJva2Utd2lkdGg6MnB4O30jbXktc3ZnIC5lZGdlLXRoaWNrbmVzcy10aGlja3tzdHJva2Utd2lkdGg6My41cHg7fSNteS1zdmcgLmVkZ2UtcGF0dGVybi1zb2xpZHtzdHJva2UtZGFzaGFycmF5OjA7fSNteS1zdmcgLmVkZ2UtcGF0dGVybi1kYXNoZWR7c3Ryb2tlLWRhc2hhcnJheTozO30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tZG90dGVke3N0cm9rZS1kYXNoYXJyYXk6Mjt9I215LXN2ZyAubWFya2Vye2ZpbGw6IzMzMzMzMztzdHJva2U6IzMzMzMzMzt9I215LXN2ZyAubWFya2VyLmNyb3Nze3N0cm9rZTojMzMzMzMzO30jbXktc3ZnIHN2Z3tmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjE2cHg7fSNteS1zdmcgLmxhYmVse2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtjb2xvcjojMzMzO30jbXktc3ZnIC5jbHVzdGVyLWxhYmVsIHRleHR7ZmlsbDojMzMzO30jbXktc3ZnIC5jbHVzdGVyLWxhYmVsIHNwYW4sI215LXN2ZyBwe2NvbG9yOiMzMzM7fSNteS1zdmcgLmxhYmVsIHRleHQsI215LXN2ZyBzcGFuLCNteS1zdmcgcHtmaWxsOiMzMzM7Y29sb3I6IzMzMzt9I215LXN2ZyAubm9kZSByZWN0LCNteS1zdmcgLm5vZGUgY2lyY2xlLCNteS1zdmcgLm5vZGUgZWxsaXBzZSwjbXktc3ZnIC5ub2RlIHBvbHlnb24sI215LXN2ZyAubm9kZSBwYXRoe2ZpbGw6I0VDRUNGRjtzdHJva2U6IzkzNzBEQjtzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5mbG93Y2hhcnQtbGFiZWwgdGV4dHt0ZXh0LWFuY2hvcjptaWRkbGU7fSNteS1zdmcgLm5vZGUgLmthdGV4IHBhdGh7ZmlsbDojMDAwO3N0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxcHg7fSNteS1zdmcgLm5vZGUgLmxhYmVse3RleHQtYWxpZ246Y2VudGVyO30jbXktc3ZnIC5ub2RlLmNsaWNrYWJsZXtjdXJzb3I6cG9pbnRlcjt9I215LXN2ZyAuYXJyb3doZWFkUGF0aHtmaWxsOiMzMzMzMzM7fSNteS1zdmcgLmVkZ2VQYXRoIC5wYXRoe3N0cm9rZTojMzMzMzMzO3N0cm9rZS13aWR0aDoyLjBweDt9I215LXN2ZyAuZmxvd2NoYXJ0LWxpbmt7c3Ryb2tlOiMzMzMzMzM7ZmlsbDpub25lO30jbXktc3ZnIC5lZGdlTGFiZWx7YmFja2dyb3VuZC1jb2xvcjojZThlOGU4O3RleHQtYWxpZ246Y2VudGVyO30jbXktc3ZnIC5lZGdlTGFiZWwgcmVjdHtvcGFjaXR5OjAuNTtiYWNrZ3JvdW5kLWNvbG9yOiNlOGU4ZTg7ZmlsbDojZThlOGU4O30jbXktc3ZnIC5sYWJlbEJrZ3tiYWNrZ3JvdW5kLWNvbG9yOnJnYmEoMjMyLCAyMzIsIDIzMiwgMC41KTt9I215LXN2ZyAuY2x1c3RlciByZWN0e2ZpbGw6I2ZmZmZkZTtzdHJva2U6I2FhYWEzMztzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5jbHVzdGVyIHRleHR7ZmlsbDojMzMzO30jbXktc3ZnIC5jbHVzdGVyIHNwYW4sI215LXN2ZyBwe2NvbG9yOiMzMzM7fSNteS1zdmcgZGl2Lm1lcm1haWRUb29sdGlwe3Bvc2l0aW9uOmFic29sdXRlO3RleHQtYWxpZ246Y2VudGVyO21heC13aWR0aDoyMDBweDtwYWRkaW5nOjJweDtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjEycHg7YmFja2dyb3VuZDpoc2woODAsIDEwMCUsIDk2LjI3NDUwOTgwMzklKTtib3JkZXI6MXB4IHNvbGlkICNhYWFhMzM7Ym9yZGVyLXJhZGl1czoycHg7cG9pbnRlci1ldmVudHM6bm9uZTt6LWluZGV4OjEwMDt9I215LXN2ZyAuZmxvd2NoYXJ0VGl0bGVUZXh0e3RleHQtYW5jaG9yOm1pZGRsZTtmb250LXNpemU6MThweDtmaWxsOiMzMzM7fSNteS1zdmcgOnJvb3R7LS1tZXJtYWlkLWZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjt9I215LXN2ZyAuZ3JlZW4mZ3Q7KntzdHJva2U6cmdiKDI1NSwgMCwgMCkhaW1wb3J0YW50O30jbXktc3ZnIC5ncmVlbiBzcGFue3N0cm9rZTpyZ2IoMjU1LCAwLCAwKSFpbXBvcnRhbnQ7fTwvc3R5bGU+PGc+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1wb2ludEVuZCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iNiIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTIiIG1hcmtlckhlaWdodD0iMTIiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAwIDAgTCAxMCA1IEwgMCAxMCB6IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtcG9pbnRTdGFydCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iNC41IiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMiIgbWFya2VySGVpZ2h0PSIxMiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDAgNSBMIDEwIDEwIEwgMTAgMCB6IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY2lyY2xlRW5kIiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSIxMSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PGNpcmNsZSBjeD0iNSIgY3k9IjUiIHI9IjUiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jaXJjbGVTdGFydCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iLTEiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxjaXJjbGUgY3g9IjUiIGN5PSI1IiByPSI1IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY3Jvc3NFbmQiIGNsYXNzPSJtYXJrZXIgY3Jvc3MgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTEgMTEiIHJlZlg9IjEyIiByZWZZPSI1LjIiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMSwxIGwgOSw5IE0gMTAsMSBsIC05LDkiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDI7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jcm9zc1N0YXJ0IiBjbGFzcz0ibWFya2VyIGNyb3NzIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDExIDExIiByZWZYPSItMSIgcmVmWT0iNS4yIiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDEsMSBsIDksOSBNIDEwLDEgbCAtOSw5IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAyOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxnIGNsYXNzPSJyb290Ij48ZyBjbGFzcz0iY2x1c3RlcnMiLz48ZyBjbGFzcz0iZWRnZVBhdGhzIi8+PGcgY2xhc3M9ImVkZ2VMYWJlbHMiLz48ZyBjbGFzcz0ibm9kZXMiPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZGVmYXVsdCBmbG93Y2hhcnQtbGFiZWwiIGlkPSJmbG93Y2hhcnQtYXN5bmMtMCIgZGF0YS1ub2RlPSJ0cnVlIiBkYXRhLWlkPSJhc3luYyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNzYuNTU0Njg3NSwgMTcpIj48cmVjdCBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIiBzdHlsZT0iIiByeD0iMCIgcnk9IjAiIHg9Ii03Ni41NTQ2ODc1IiB5PSItMTciIHdpZHRoPSIxNTMuMTA5Mzc1IiBoZWlnaHQ9IjM0Ii8+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNjkuMDU0Njg3NSwgLTkuNSkiPjxyZWN0Lz48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMTM4LjEwOTM3NSIgaGVpZ2h0PSIxOSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPmRldi5tY2N1ZS5hc3luYzwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>dev.mccue.async</code> provides one class - <code>Atom</code>. <code>Atom</code> wraps an <code>AtomicReference</code> and gives a simpler, if less powerful, API that is geared around atomic compare and swap operations.</p>
<h2 id="why-use-it">Why use it</h2>
<p>If you are from the Clojure world, this gives an API directly inspired by its <code>atom</code> construct. That can be appealing if you want to have managed immutable state and are used to that world.</p>
<p>The primary utility provided is having the atomic compare and swap logic already written out for you. It's only a handful of lines, but not something appealing to copy around a codebase.</p>
<h2 id="getting-started">Getting Started</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">ArrayList</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">async</span><span class="op">.</span><span class="im">Atom</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="kw">throws</span> <span class="bu">Exception</span> <span class="op">{</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    var data <span class="op">=</span> Atom<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="dv">0</span><span class="op">);</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">// 0</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>data<span class="op">.</span><span class="fu">get</span><span class="op">());</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>    data<span class="op">.</span><span class="fu">swap</span><span class="op">(</span>x <span class="op">-&gt;</span> x <span class="op">+</span> <span class="dv">1</span><span class="op">);</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>    <span class="co">// 1</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>data<span class="op">.</span><span class="fu">get</span><span class="op">());</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>    <span class="co">// A bunch of concurrent swaps is sorta a worse</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    <span class="co">// case situation for an atomic reference perf.</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>    <span class="co">// wise, but a good illustration of correctness.</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>    var threads <span class="op">=</span> <span class="kw">new</span> <span class="bu">ArrayList</span><span class="op">&lt;</span><span class="bu">Thread</span><span class="op">&gt;();</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="op">(</span><span class="dv">10000</span> <span class="op">-</span> <span class="dv">1</span><span class="op">);</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>        threads<span class="op">.</span><span class="fu">add</span><span class="op">(</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Thread</span><span class="op">.</span><span class="fu">startVirtualThread</span><span class="op">(()</span> <span class="op">-&gt;</span> data<span class="op">.</span><span class="fu">swap</span><span class="op">(</span>x <span class="op">-&gt;</span> x <span class="op">+</span> <span class="dv">1</span><span class="op">))</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span>var thread <span class="op">:</span> threads<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>        thread<span class="op">.</span><span class="fu">join</span><span class="op">();</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a>    <span class="co">// 10000</span></span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>data<span class="op">.</span><span class="fu">get</span><span class="op">());</span></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>dev.mccue.microhttp.json</title><link>https://mccue.dev/pages/12-18-23-java-library-of-the-day-18</link><description></description><pubDate>Mon, 18 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>dev.mccue.microhttp.json</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">dev.mccue.microhttp.json</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/dev.mccue/microhttp-json"><code>dev.mccue/microhttp-json</code></a></li>
<li>Module Name: <code>dev.mccue.microhttp.json</code></li>
<li>GitHub: <a href="https://github.com/bowbahdoe/microhttp-json"><code>bowbahdoe/microhttp-json</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogMjM4LjA0N3B4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii04IC04IDIzOC4wNDY4NzUgMTg0IiByb2xlPSJncmFwaGljcy1kb2N1bWVudCBkb2N1bWVudCIgYXJpYS1yb2xlZGVzY3JpcHRpb249ImZsb3djaGFydC12MiI+PHN0eWxlPiNteS1zdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O2ZpbGw6IzMzMzt9I215LXN2ZyAuZXJyb3ItaWNvbntmaWxsOiM1NTIyMjI7fSNteS1zdmcgLmVycm9yLXRleHR7ZmlsbDojNTUyMjIyO3N0cm9rZTojNTUyMjIyO30jbXktc3ZnIC5lZGdlLXRoaWNrbmVzcy1ub3JtYWx7c3Ryb2tlLXdpZHRoOjJweDt9I215LXN2ZyAuZWRnZS10aGlja25lc3MtdGhpY2t7c3Ryb2tlLXdpZHRoOjMuNXB4O30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tc29saWR7c3Ryb2tlLWRhc2hhcnJheTowO30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tZGFzaGVke3N0cm9rZS1kYXNoYXJyYXk6Mzt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLWRvdHRlZHtzdHJva2UtZGFzaGFycmF5OjI7fSNteS1zdmcgLm1hcmtlcntmaWxsOiMzMzMzMzM7c3Ryb2tlOiMzMzMzMzM7fSNteS1zdmcgLm1hcmtlci5jcm9zc3tzdHJva2U6IzMzMzMzMzt9I215LXN2ZyBzdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O30jbXktc3ZnIC5sYWJlbHtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Y29sb3I6IzMzMzt9I215LXN2ZyAuY2x1c3Rlci1sYWJlbCB0ZXh0e2ZpbGw6IzMzMzt9I215LXN2ZyAuY2x1c3Rlci1sYWJlbCBzcGFuLCNteS1zdmcgcHtjb2xvcjojMzMzO30jbXktc3ZnIC5sYWJlbCB0ZXh0LCNteS1zdmcgc3BhbiwjbXktc3ZnIHB7ZmlsbDojMzMzO2NvbG9yOiMzMzM7fSNteS1zdmcgLm5vZGUgcmVjdCwjbXktc3ZnIC5ub2RlIGNpcmNsZSwjbXktc3ZnIC5ub2RlIGVsbGlwc2UsI215LXN2ZyAubm9kZSBwb2x5Z29uLCNteS1zdmcgLm5vZGUgcGF0aHtmaWxsOiNFQ0VDRkY7c3Ryb2tlOiM5MzcwREI7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAuZmxvd2NoYXJ0LWxhYmVsIHRleHR7dGV4dC1hbmNob3I6bWlkZGxlO30jbXktc3ZnIC5ub2RlIC5rYXRleCBwYXRoe2ZpbGw6IzAwMDtzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5ub2RlIC5sYWJlbHt0ZXh0LWFsaWduOmNlbnRlcjt9I215LXN2ZyAubm9kZS5jbGlja2FibGV7Y3Vyc29yOnBvaW50ZXI7fSNteS1zdmcgLmFycm93aGVhZFBhdGh7ZmlsbDojMzMzMzMzO30jbXktc3ZnIC5lZGdlUGF0aCAucGF0aHtzdHJva2U6IzMzMzMzMztzdHJva2Utd2lkdGg6Mi4wcHg7fSNteS1zdmcgLmZsb3djaGFydC1saW5re3N0cm9rZTojMzMzMzMzO2ZpbGw6bm9uZTt9I215LXN2ZyAuZWRnZUxhYmVse2JhY2tncm91bmQtY29sb3I6I2U4ZThlODt0ZXh0LWFsaWduOmNlbnRlcjt9I215LXN2ZyAuZWRnZUxhYmVsIHJlY3R7b3BhY2l0eTowLjU7YmFja2dyb3VuZC1jb2xvcjojZThlOGU4O2ZpbGw6I2U4ZThlODt9I215LXN2ZyAubGFiZWxCa2d7YmFja2dyb3VuZC1jb2xvcjpyZ2JhKDIzMiwgMjMyLCAyMzIsIDAuNSk7fSNteS1zdmcgLmNsdXN0ZXIgcmVjdHtmaWxsOiNmZmZmZGU7c3Ryb2tlOiNhYWFhMzM7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAuY2x1c3RlciB0ZXh0e2ZpbGw6IzMzMzt9I215LXN2ZyAuY2x1c3RlciBzcGFuLCNteS1zdmcgcHtjb2xvcjojMzMzO30jbXktc3ZnIGRpdi5tZXJtYWlkVG9vbHRpcHtwb3NpdGlvbjphYnNvbHV0ZTt0ZXh0LWFsaWduOmNlbnRlcjttYXgtd2lkdGg6MjAwcHg7cGFkZGluZzoycHg7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxMnB4O2JhY2tncm91bmQ6aHNsKDgwLCAxMDAlLCA5Ni4yNzQ1MDk4MDM5JSk7Ym9yZGVyOjFweCBzb2xpZCAjYWFhYTMzO2JvcmRlci1yYWRpdXM6MnB4O3BvaW50ZXItZXZlbnRzOm5vbmU7ei1pbmRleDoxMDA7fSNteS1zdmcgLmZsb3djaGFydFRpdGxlVGV4dHt0ZXh0LWFuY2hvcjptaWRkbGU7Zm9udC1zaXplOjE4cHg7ZmlsbDojMzMzO30jbXktc3ZnIDpyb290ey0tbWVybWFpZC1mb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7fSNteS1zdmcgLmdyZWVuJmd0Oyp7c3Ryb2tlOnJnYigyNTUsIDAsIDApIWltcG9ydGFudDt9I215LXN2ZyAuZ3JlZW4gc3BhbntzdHJva2U6cmdiKDI1NSwgMCwgMCkhaW1wb3J0YW50O308L3N0eWxlPjxnPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtcG9pbnRFbmQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjYiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjEyIiBtYXJrZXJIZWlnaHQ9IjEyIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMCAwIEwgMTAgNSBMIDAgMTAgeiIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LXBvaW50U3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjQuNSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTIiIG1hcmtlckhlaWdodD0iMTIiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAwIDUgTCAxMCAxMCBMIDEwIDAgeiIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNpcmNsZUVuZCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iMTEiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxjaXJjbGUgY3g9IjUiIGN5PSI1IiByPSI1IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY2lyY2xlU3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9Ii0xIiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48Y2lyY2xlIGN4PSI1IiBjeT0iNSIgcj0iNSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNyb3NzRW5kIiBjbGFzcz0ibWFya2VyIGNyb3NzIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDExIDExIiByZWZYPSIxMiIgcmVmWT0iNS4yIiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDEsMSBsIDksOSBNIDEwLDEgbCAtOSw5IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAyOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY3Jvc3NTdGFydCIgY2xhc3M9Im1hcmtlciBjcm9zcyBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMSAxMSIgcmVmWD0iLTEiIHJlZlk9IjUuMiIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAxLDEgbCA5LDkgTSAxMCwxIGwgLTksOSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMjsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48ZyBjbGFzcz0icm9vdCI+PGcgY2xhc3M9ImNsdXN0ZXJzIi8+PGcgY2xhc3M9ImVkZ2VQYXRocyI+PHBhdGggZD0iTTExMS4wMjMsMzRMMTExLjAyMywzOC4xNjdDMTExLjAyMyw0Mi4zMzMsMTExLjAyMyw1MC42NjcsMTExLjAyMyw1OUMxMTEuMDIzLDY3LjMzMywxMTEuMDIzLDc1LjY2NywxMTEuMDIzLDg0QzExMS4wMjMsOTIuMzMzLDExMS4wMjMsMTAwLjY2NywxMTEuMDIzLDEwOC4xMTdDMTExLjAyMywxMTUuNTY3LDExMS4wMjMsMTIyLjEzMywxMTEuMDIzLDEyNS40MTdMMTExLjAyMywxMjguNyIgaWQ9IkwtanNvbi1taWNyb2h0dHBqc29uLTAiIGNsYXNzPSJlZGdlLXRoaWNrbmVzcy1ub3JtYWwgZWRnZS1wYXR0ZXJuLXNvbGlkIGZsb3djaGFydC1saW5rIExTLWpzb24gTEUtbWljcm9odHRwanNvbiIgc3R5bGU9ImZpbGw6bm9uZTsiIG1hcmtlci1lbmQ9InVybCgjbXktc3ZnX2Zsb3djaGFydC1wb2ludEVuZCkiLz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbHMiPjxnIGNsYXNzPSJlZGdlTGFiZWwiPjxnIGNsYXNzPSJsYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMCkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIwIiBoZWlnaHQ9IjAiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0iZWRnZUxhYmVsIj48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjxnIGNsYXNzPSJub2RlcyI+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IGZsb3djaGFydC1sYWJlbCIgaWQ9ImZsb3djaGFydC1qc29uLTAiIGRhdGEtbm9kZT0idHJ1ZSIgZGF0YS1pZD0ianNvbiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTExLjAyMzQzNzUsIDE3KSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjAiIHJ5PSIwIiB4PSItNjkuNjQwNjI1IiB5PSItMTciIHdpZHRoPSIxMzkuMjgxMjUiIGhlaWdodD0iMzQiLz48ZyBjbGFzcz0ibGFiZWwiIHN0eWxlPSIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC02Mi4xNDA2MjUsIC05LjUpIj48cmVjdC8+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjEyNC4yODEyNSIgaGVpZ2h0PSIxOSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPmRldi5tY2N1ZS5qc29uPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZ3JlZW4gZmxvd2NoYXJ0LWxhYmVsIiBpZD0iZmxvd2NoYXJ0LW1pY3JvaHR0cGpzb24tMSIgZGF0YS1ub2RlPSJ0cnVlIiBkYXRhLWlkPSJtaWNyb2h0dHBqc29uIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMTEuMDIzNDM3NSwgMTUxKSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjAiIHJ5PSIwIiB4PSItMTExLjAyMzQzNzUiIHk9Ii0xNyIgd2lkdGg9IjIyMi4wNDY4NzUiIGhlaWdodD0iMzQiLz48ZyBjbGFzcz0ibGFiZWwiIHN0eWxlPSIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xMDMuNTIzNDM3NSwgLTkuNSkiPjxyZWN0Lz48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMjA3LjA0Njg3NSIgaGVpZ2h0PSIxOSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPmRldi5tY2N1ZS5taWNyb2h0dHAuanNvbjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>dev.mccue.microhttp.json</code> provides <code>JsonResponse</code>, a class which implements <code>IntoResponse</code> and thus can be used alongside <code>microhttp</code> and <code>microhttp-handler</code> to produce responses which contain html.</p>
<p>It automatically adds the appropriate <code>Content-Type</code> header, determines the HTTP reason phrase with <code>reasonphrase</code>, and accepts the <code>Json</code> type provided by <code>dev.mccue.json</code>.</p>
<h2 id="why-use-it">Why use it</h2>
<p>If you are using <code>microhttp</code> with <code>microhttp-handler</code>, it boxes up the logic needed in order to return json responses. This would otherwise be cumbersome to write at every needed location</p>
<h2 id="getting-started">Getting Started</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">handler</span><span class="op">.</span><span class="im">RouteHandler</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">json</span><span class="op">.</span><span class="im">JsonResponse</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">regex</span><span class="op">.</span><span class="im">Pattern</span><span class="op">;</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">regex</span><span class="op">.</span><span class="im">Matcher</span><span class="op">;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> BasicHandler <span class="kw">extends</span> RouteHandler <span class="op">{</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    <span class="fu">IndexHandler</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">(</span><span class="st">&quot;GET&quot;</span><span class="op">,</span> <span class="bu">Pattern</span><span class="op">.</span><span class="fu">compile</span><span class="op">(</span><span class="st">&quot;/&quot;</span><span class="op">));</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> JsonResponse <span class="fu">handleRoute</span><span class="op">(</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Matcher</span> matcher<span class="op">,</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Request</span> request</span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">JsonResponse</span><span class="op">(</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>                Json<span class="op">.</span><span class="fu">objectBuilder</span><span class="op">()</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>                    <span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;name&quot;</span><span class="op">,</span> <span class="st">&quot;bob&quot;</span><span class="op">)</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>                    <span class="op">.</span><span class="fu">build</span><span class="op">()</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>dev.mccue.json</title><link>https://mccue.dev/pages/12-17-23-java-library-of-the-day-17</link><description></description><pubDate>Sun, 17 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>dev.mccue.json</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">dev.mccue.json</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/dev.mccue/json"><code>dev.mccue/json</code></a></li>
<li>Module Name: <code>dev.mccue.json</code></li>
<li>GitHub: <a href="https://github.com/bowbahdoe/json"><code>bowbahdoe/json</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogMTU1LjI4MXB4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii04IC04IDE1NS4yODEyNSA1MCIgcm9sZT0iZ3JhcGhpY3MtZG9jdW1lbnQgZG9jdW1lbnQiIGFyaWEtcm9sZWRlc2NyaXB0aW9uPSJmbG93Y2hhcnQtdjIiPjxzdHlsZT4jbXktc3Zne2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtmb250LXNpemU6MTZweDtmaWxsOiMzMzM7fSNteS1zdmcgLmVycm9yLWljb257ZmlsbDojNTUyMjIyO30jbXktc3ZnIC5lcnJvci10ZXh0e2ZpbGw6IzU1MjIyMjtzdHJva2U6IzU1MjIyMjt9I215LXN2ZyAuZWRnZS10aGlja25lc3Mtbm9ybWFse3N0cm9rZS13aWR0aDoycHg7fSNteS1zdmcgLmVkZ2UtdGhpY2tuZXNzLXRoaWNre3N0cm9rZS13aWR0aDozLjVweDt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLXNvbGlke3N0cm9rZS1kYXNoYXJyYXk6MDt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLWRhc2hlZHtzdHJva2UtZGFzaGFycmF5OjM7fSNteS1zdmcgLmVkZ2UtcGF0dGVybi1kb3R0ZWR7c3Ryb2tlLWRhc2hhcnJheToyO30jbXktc3ZnIC5tYXJrZXJ7ZmlsbDojMzMzMzMzO3N0cm9rZTojMzMzMzMzO30jbXktc3ZnIC5tYXJrZXIuY3Jvc3N7c3Ryb2tlOiMzMzMzMzM7fSNteS1zdmcgc3Zne2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtmb250LXNpemU6MTZweDt9I215LXN2ZyAubGFiZWx7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2NvbG9yOiMzMzM7fSNteS1zdmcgLmNsdXN0ZXItbGFiZWwgdGV4dHtmaWxsOiMzMzM7fSNteS1zdmcgLmNsdXN0ZXItbGFiZWwgc3BhbiwjbXktc3ZnIHB7Y29sb3I6IzMzMzt9I215LXN2ZyAubGFiZWwgdGV4dCwjbXktc3ZnIHNwYW4sI215LXN2ZyBwe2ZpbGw6IzMzMztjb2xvcjojMzMzO30jbXktc3ZnIC5ub2RlIHJlY3QsI215LXN2ZyAubm9kZSBjaXJjbGUsI215LXN2ZyAubm9kZSBlbGxpcHNlLCNteS1zdmcgLm5vZGUgcG9seWdvbiwjbXktc3ZnIC5ub2RlIHBhdGh7ZmlsbDojRUNFQ0ZGO3N0cm9rZTojOTM3MERCO3N0cm9rZS13aWR0aDoxcHg7fSNteS1zdmcgLmZsb3djaGFydC1sYWJlbCB0ZXh0e3RleHQtYW5jaG9yOm1pZGRsZTt9I215LXN2ZyAubm9kZSAua2F0ZXggcGF0aHtmaWxsOiMwMDA7c3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAubm9kZSAubGFiZWx7dGV4dC1hbGlnbjpjZW50ZXI7fSNteS1zdmcgLm5vZGUuY2xpY2thYmxle2N1cnNvcjpwb2ludGVyO30jbXktc3ZnIC5hcnJvd2hlYWRQYXRoe2ZpbGw6IzMzMzMzMzt9I215LXN2ZyAuZWRnZVBhdGggLnBhdGh7c3Ryb2tlOiMzMzMzMzM7c3Ryb2tlLXdpZHRoOjIuMHB4O30jbXktc3ZnIC5mbG93Y2hhcnQtbGlua3tzdHJva2U6IzMzMzMzMztmaWxsOm5vbmU7fSNteS1zdmcgLmVkZ2VMYWJlbHtiYWNrZ3JvdW5kLWNvbG9yOiNlOGU4ZTg7dGV4dC1hbGlnbjpjZW50ZXI7fSNteS1zdmcgLmVkZ2VMYWJlbCByZWN0e29wYWNpdHk6MC41O2JhY2tncm91bmQtY29sb3I6I2U4ZThlODtmaWxsOiNlOGU4ZTg7fSNteS1zdmcgLmxhYmVsQmtne2JhY2tncm91bmQtY29sb3I6cmdiYSgyMzIsIDIzMiwgMjMyLCAwLjUpO30jbXktc3ZnIC5jbHVzdGVyIHJlY3R7ZmlsbDojZmZmZmRlO3N0cm9rZTojYWFhYTMzO3N0cm9rZS13aWR0aDoxcHg7fSNteS1zdmcgLmNsdXN0ZXIgdGV4dHtmaWxsOiMzMzM7fSNteS1zdmcgLmNsdXN0ZXIgc3BhbiwjbXktc3ZnIHB7Y29sb3I6IzMzMzt9I215LXN2ZyBkaXYubWVybWFpZFRvb2x0aXB7cG9zaXRpb246YWJzb2x1dGU7dGV4dC1hbGlnbjpjZW50ZXI7bWF4LXdpZHRoOjIwMHB4O3BhZGRpbmc6MnB4O2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtmb250LXNpemU6MTJweDtiYWNrZ3JvdW5kOmhzbCg4MCwgMTAwJSwgOTYuMjc0NTA5ODAzOSUpO2JvcmRlcjoxcHggc29saWQgI2FhYWEzMztib3JkZXItcmFkaXVzOjJweDtwb2ludGVyLWV2ZW50czpub25lO3otaW5kZXg6MTAwO30jbXktc3ZnIC5mbG93Y2hhcnRUaXRsZVRleHR7dGV4dC1hbmNob3I6bWlkZGxlO2ZvbnQtc2l6ZToxOHB4O2ZpbGw6IzMzMzt9I215LXN2ZyA6cm9vdHstLW1lcm1haWQtZm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO30jbXktc3ZnIC5ncmVlbiZndDsqe3N0cm9rZTpyZ2IoMjU1LCAwLCAwKSFpbXBvcnRhbnQ7fSNteS1zdmcgLmdyZWVuIHNwYW57c3Ryb2tlOnJnYigyNTUsIDAsIDApIWltcG9ydGFudDt9PC9zdHlsZT48Zz48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LXBvaW50RW5kIiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI2IiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMiIgbWFya2VySGVpZ2h0PSIxMiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDAgMCBMIDEwIDUgTCAwIDEwIHoiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1wb2ludFN0YXJ0IiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI0LjUiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjEyIiBtYXJrZXJIZWlnaHQ9IjEyIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMCA1IEwgMTAgMTAgTCAxMCAwIHoiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jaXJjbGVFbmQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjExIiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48Y2lyY2xlIGN4PSI1IiBjeT0iNSIgcj0iNSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNpcmNsZVN0YXJ0IiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSItMSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PGNpcmNsZSBjeD0iNSIgY3k9IjUiIHI9IjUiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jcm9zc0VuZCIgY2xhc3M9Im1hcmtlciBjcm9zcyBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMSAxMSIgcmVmWD0iMTIiIHJlZlk9IjUuMiIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAxLDEgbCA5LDkgTSAxMCwxIGwgLTksOSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMjsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNyb3NzU3RhcnQiIGNsYXNzPSJtYXJrZXIgY3Jvc3MgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTEgMTEiIHJlZlg9Ii0xIiByZWZZPSI1LjIiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMSwxIGwgOSw5IE0gMTAsMSBsIC05LDkiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDI7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PGcgY2xhc3M9InJvb3QiPjxnIGNsYXNzPSJjbHVzdGVycyIvPjxnIGNsYXNzPSJlZGdlUGF0aHMiLz48ZyBjbGFzcz0iZWRnZUxhYmVscyIvPjxnIGNsYXNzPSJub2RlcyI+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBncmVlbiBmbG93Y2hhcnQtbGFiZWwiIGlkPSJmbG93Y2hhcnQtanNvbi0wIiBkYXRhLW5vZGU9InRydWUiIGRhdGEtaWQ9Impzb24iIHRyYW5zZm9ybT0idHJhbnNsYXRlKDY5LjY0MDYyNSwgMTcpIj48cmVjdCBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIiBzdHlsZT0iIiByeD0iMCIgcnk9IjAiIHg9Ii02OS42NDA2MjUiIHk9Ii0xNyIgd2lkdGg9IjEzOS4yODEyNSIgaGVpZ2h0PSIzNCIvPjxnIGNsYXNzPSJsYWJlbCIgc3R5bGU9IiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTYyLjE0MDYyNSwgLTkuNSkiPjxyZWN0Lz48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMTI0LjI4MTI1IiBoZWlnaHQ9IjE5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+ZGV2Lm1jY3VlLmpzb248L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjwvZz48L2c+PC9zdmc+" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>dev.mccue.json</code> provides the ability to read and write JSON data as well as to encode data into JSON and decode data from JSON.</p>
<h2 id="why-use-it">Why use it</h2>
<p>Most popular JSON libraries use data-binding. You make a class, possibly annotate it a little bit, and then some automatic logic binds the data inside a JSON structure to the fields of your class.</p>
<p>This has clear upsides, but it's hard to explain to newcomers. The underlying mechanism of data-binding is either reflection or compile-time code generation. Both are processes that are hard to "touch." The escape hatches in libraries that assume data-binding is the default mode of operation are less than ergonomic.</p>
<p>This takes the other approach, making people manually extract data from JSON, but does so in a way that is composable. You have to write more code, but the mechanics of the code are more plain to see.</p>
<p>I've <a href="https://mccue.dev/pages/2-26-23-json">written about this before</a>. I'm listing it here because some libraries I wrote that I'll introduce later depend on it.</p>
<h2 id="getting-started">Getting Started</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.</span><span class="im">Json</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.</span><span class="im">JsonDecoder</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.</span><span class="im">JsonEncodable</span><span class="op">;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Superhero</span><span class="op">(</span><span class="bu">String</span> name<span class="op">)</span> <span class="kw">implements</span> JsonEncodable <span class="op">{</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> Json <span class="fu">toJson</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> Json<span class="op">.</span><span class="fu">objectBuilder</span><span class="op">()</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;name&quot;</span><span class="op">,</span> name<span class="op">)</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">build</span><span class="op">();</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> Superhero <span class="fu">fromJson</span><span class="op">(</span>Json json<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Superhero</span><span class="op">(</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>            JsonDecoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span>json<span class="op">,</span> <span class="st">&quot;name&quot;</span><span class="op">,</span> JsonDecoder<span class="op">::</span>string<span class="op">)</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>    var superhero <span class="op">=</span> <span class="kw">new</span> <span class="fu">Superhero</span><span class="op">(</span><span class="st">&quot;superman&quot;</span><span class="op">);</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>    var json <span class="op">=</span> superhero<span class="op">.</span><span class="fu">toJson</span><span class="op">();</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>    var jsonStr <span class="op">=</span> Json<span class="op">.</span><span class="fu">writeString</span><span class="op">(</span>json<span class="op">);</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>    var roundTripped <span class="op">=</span> Json<span class="op">.</span><span class="fu">readString</span><span class="op">(</span>jsonStr<span class="op">);</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>    var newSuperhero <span class="op">=</span> Superhero<span class="op">.</span><span class="fu">fromJson</span><span class="op">(</span>roundTripped<span class="op">);</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>superhero<span class="op">);</span></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>jsonStr<span class="op">);</span></span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>newSuperhero<span class="op">);</span></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>com.samskivert.jmustache</title><link>https://mccue.dev/pages/12-16-23-java-library-of-the-day-16</link><description></description><pubDate>Sat, 16 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>com.samskivert.jmustache</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">com.samskivert.jmustache</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/com.samskivert/jmustache"><code>com.samskivert/jmustache</code></a></li>
<li>Module Name: <code>com.samskivert.jmustache</code></li>
<li>GitHub: <a href="https://github.com/samskivert/jmustache"><code>samskivert/jmustache</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogMjQ2LjY1NnB4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii04IC04IDI0Ni42NTYyNSA1MCIgcm9sZT0iZ3JhcGhpY3MtZG9jdW1lbnQgZG9jdW1lbnQiIGFyaWEtcm9sZWRlc2NyaXB0aW9uPSJmbG93Y2hhcnQtdjIiPjxzdHlsZT4jbXktc3Zne2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtmb250LXNpemU6MTZweDtmaWxsOiMzMzM7fSNteS1zdmcgLmVycm9yLWljb257ZmlsbDojNTUyMjIyO30jbXktc3ZnIC5lcnJvci10ZXh0e2ZpbGw6IzU1MjIyMjtzdHJva2U6IzU1MjIyMjt9I215LXN2ZyAuZWRnZS10aGlja25lc3Mtbm9ybWFse3N0cm9rZS13aWR0aDoycHg7fSNteS1zdmcgLmVkZ2UtdGhpY2tuZXNzLXRoaWNre3N0cm9rZS13aWR0aDozLjVweDt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLXNvbGlke3N0cm9rZS1kYXNoYXJyYXk6MDt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLWRhc2hlZHtzdHJva2UtZGFzaGFycmF5OjM7fSNteS1zdmcgLmVkZ2UtcGF0dGVybi1kb3R0ZWR7c3Ryb2tlLWRhc2hhcnJheToyO30jbXktc3ZnIC5tYXJrZXJ7ZmlsbDojMzMzMzMzO3N0cm9rZTojMzMzMzMzO30jbXktc3ZnIC5tYXJrZXIuY3Jvc3N7c3Ryb2tlOiMzMzMzMzM7fSNteS1zdmcgc3Zne2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtmb250LXNpemU6MTZweDt9I215LXN2ZyAubGFiZWx7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2NvbG9yOiMzMzM7fSNteS1zdmcgLmNsdXN0ZXItbGFiZWwgdGV4dHtmaWxsOiMzMzM7fSNteS1zdmcgLmNsdXN0ZXItbGFiZWwgc3BhbiwjbXktc3ZnIHB7Y29sb3I6IzMzMzt9I215LXN2ZyAubGFiZWwgdGV4dCwjbXktc3ZnIHNwYW4sI215LXN2ZyBwe2ZpbGw6IzMzMztjb2xvcjojMzMzO30jbXktc3ZnIC5ub2RlIHJlY3QsI215LXN2ZyAubm9kZSBjaXJjbGUsI215LXN2ZyAubm9kZSBlbGxpcHNlLCNteS1zdmcgLm5vZGUgcG9seWdvbiwjbXktc3ZnIC5ub2RlIHBhdGh7ZmlsbDojRUNFQ0ZGO3N0cm9rZTojOTM3MERCO3N0cm9rZS13aWR0aDoxcHg7fSNteS1zdmcgLmZsb3djaGFydC1sYWJlbCB0ZXh0e3RleHQtYW5jaG9yOm1pZGRsZTt9I215LXN2ZyAubm9kZSAua2F0ZXggcGF0aHtmaWxsOiMwMDA7c3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAubm9kZSAubGFiZWx7dGV4dC1hbGlnbjpjZW50ZXI7fSNteS1zdmcgLm5vZGUuY2xpY2thYmxle2N1cnNvcjpwb2ludGVyO30jbXktc3ZnIC5hcnJvd2hlYWRQYXRoe2ZpbGw6IzMzMzMzMzt9I215LXN2ZyAuZWRnZVBhdGggLnBhdGh7c3Ryb2tlOiMzMzMzMzM7c3Ryb2tlLXdpZHRoOjIuMHB4O30jbXktc3ZnIC5mbG93Y2hhcnQtbGlua3tzdHJva2U6IzMzMzMzMztmaWxsOm5vbmU7fSNteS1zdmcgLmVkZ2VMYWJlbHtiYWNrZ3JvdW5kLWNvbG9yOiNlOGU4ZTg7dGV4dC1hbGlnbjpjZW50ZXI7fSNteS1zdmcgLmVkZ2VMYWJlbCByZWN0e29wYWNpdHk6MC41O2JhY2tncm91bmQtY29sb3I6I2U4ZThlODtmaWxsOiNlOGU4ZTg7fSNteS1zdmcgLmxhYmVsQmtne2JhY2tncm91bmQtY29sb3I6cmdiYSgyMzIsIDIzMiwgMjMyLCAwLjUpO30jbXktc3ZnIC5jbHVzdGVyIHJlY3R7ZmlsbDojZmZmZmRlO3N0cm9rZTojYWFhYTMzO3N0cm9rZS13aWR0aDoxcHg7fSNteS1zdmcgLmNsdXN0ZXIgdGV4dHtmaWxsOiMzMzM7fSNteS1zdmcgLmNsdXN0ZXIgc3BhbiwjbXktc3ZnIHB7Y29sb3I6IzMzMzt9I215LXN2ZyBkaXYubWVybWFpZFRvb2x0aXB7cG9zaXRpb246YWJzb2x1dGU7dGV4dC1hbGlnbjpjZW50ZXI7bWF4LXdpZHRoOjIwMHB4O3BhZGRpbmc6MnB4O2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtmb250LXNpemU6MTJweDtiYWNrZ3JvdW5kOmhzbCg4MCwgMTAwJSwgOTYuMjc0NTA5ODAzOSUpO2JvcmRlcjoxcHggc29saWQgI2FhYWEzMztib3JkZXItcmFkaXVzOjJweDtwb2ludGVyLWV2ZW50czpub25lO3otaW5kZXg6MTAwO30jbXktc3ZnIC5mbG93Y2hhcnRUaXRsZVRleHR7dGV4dC1hbmNob3I6bWlkZGxlO2ZvbnQtc2l6ZToxOHB4O2ZpbGw6IzMzMzt9I215LXN2ZyA6cm9vdHstLW1lcm1haWQtZm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO30jbXktc3ZnIC5ncmVlbiZndDsqe3N0cm9rZTpyZ2IoMjU1LCAwLCAwKSFpbXBvcnRhbnQ7fSNteS1zdmcgLmdyZWVuIHNwYW57c3Ryb2tlOnJnYigyNTUsIDAsIDApIWltcG9ydGFudDt9PC9zdHlsZT48Zz48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LXBvaW50RW5kIiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI2IiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMiIgbWFya2VySGVpZ2h0PSIxMiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDAgMCBMIDEwIDUgTCAwIDEwIHoiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1wb2ludFN0YXJ0IiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI0LjUiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjEyIiBtYXJrZXJIZWlnaHQ9IjEyIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMCA1IEwgMTAgMTAgTCAxMCAwIHoiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jaXJjbGVFbmQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjExIiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48Y2lyY2xlIGN4PSI1IiBjeT0iNSIgcj0iNSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNpcmNsZVN0YXJ0IiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSItMSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PGNpcmNsZSBjeD0iNSIgY3k9IjUiIHI9IjUiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jcm9zc0VuZCIgY2xhc3M9Im1hcmtlciBjcm9zcyBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMSAxMSIgcmVmWD0iMTIiIHJlZlk9IjUuMiIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAxLDEgbCA5LDkgTSAxMCwxIGwgLTksOSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMjsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNyb3NzU3RhcnQiIGNsYXNzPSJtYXJrZXIgY3Jvc3MgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTEgMTEiIHJlZlg9Ii0xIiByZWZZPSI1LjIiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMSwxIGwgOSw5IE0gMTAsMSBsIC05LDkiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDI7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PGcgY2xhc3M9InJvb3QiPjxnIGNsYXNzPSJjbHVzdGVycyIvPjxnIGNsYXNzPSJlZGdlUGF0aHMiLz48ZyBjbGFzcz0iZWRnZUxhYmVscyIvPjxnIGNsYXNzPSJub2RlcyI+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBncmVlbiBmbG93Y2hhcnQtbGFiZWwiIGlkPSJmbG93Y2hhcnQtam11c3RhY2hlLTAiIGRhdGEtbm9kZT0idHJ1ZSIgZGF0YS1pZD0iam11c3RhY2hlIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMTUuMzI4MTI1LCAxNykiPjxyZWN0IGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiIHN0eWxlPSIiIHJ4PSIwIiByeT0iMCIgeD0iLTExNS4zMjgxMjUiIHk9Ii0xNyIgd2lkdGg9IjIzMC42NTYyNSIgaGVpZ2h0PSIzNCIvPjxnIGNsYXNzPSJsYWJlbCIgc3R5bGU9IiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTEwNy44MjgxMjUsIC05LjUpIj48cmVjdC8+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjIxNS42NTYyNSIgaGVpZ2h0PSIxOSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPmNvbS5zYW1za2l2ZXJ0LmptdXN0YWNoZTwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>com.samskivert.jmustache</code> is an implementation of the <a href="https://mustache.github.io/">Mustache templating language</a>.</p>
<h2 id="why-use-it">Why use it</h2>
<p>Mustache is one of many templating languages used for generating HTML. It has the unique advantage of being especially portable between languages and environments.</p>
<p>This comes as a result of a deliberate choice to not allow much "logic" in templates. To quote <a href="https://mustache.github.io/mustache.5.html">its man page</a>:</p>
<blockquote>
<p>We call it "logic-less" because there are no if statements, else clauses, or for loops. Instead there are only tags. Some tags are replaced with a value, some nothing, and others a series of values.</p>
</blockquote>
<p>This comes at a cost - you need to arrange all the information for a template up-front - but does make it easier to consider the behavior of a template in isolation.</p>
<p>Of the implementations of mustache available for the JVM, <code>com.samskivert.jmustache</code> has the fewest moving pieces, is <a href="https://github.com/mustache/spec">up-to-date with the specification</a>, and is <a href="https://github.com/agentgt/template-benchmark">faster</a> than other implementations that do their work at runtime.</p>
<h2 id="getting-started">Getting Started</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">samskivert</span><span class="op">.</span><span class="im">mustache</span><span class="op">.</span><span class="im">Mustache</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">List</span><span class="op">;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">Map</span><span class="op">;</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Cartoon</span><span class="op">(</span><span class="bu">String</span> name<span class="op">,</span> <span class="dt">boolean</span> hasMovie<span class="op">)</span> <span class="op">{}</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    var cartoons <span class="op">=</span> <span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="fu">Cartoon</span><span class="op">(</span><span class="st">&quot;Space Ghost Coast to Coast&quot;</span><span class="op">,</span> <span class="kw">false</span><span class="op">),</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="fu">Cartoon</span><span class="op">(</span><span class="st">&quot;Harvey Birdman, Attorney at Law&quot;</span><span class="op">,</span> <span class="kw">false</span><span class="op">),</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="fu">Cartoon</span><span class="op">(</span><span class="st">&quot;Sealab 2021&quot;</span><span class="op">,</span> <span class="kw">false</span><span class="op">),</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="fu">Cartoon</span><span class="op">(</span><span class="st">&quot;The Venture Bros.&quot;</span><span class="op">,</span> <span class="kw">true</span><span class="op">)</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    var template <span class="op">=</span> <span class="st">&quot;&quot;&quot;</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>            <span class="op">&lt;</span>html<span class="op">&gt;</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>              <span class="op">&lt;</span>body<span class="op">&gt;</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>                <span class="op">&lt;</span>h1<span class="op">&gt;</span> Cartoons <span class="op">&lt;/</span>h1<span class="op">&gt;</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>                <span class="op">&lt;</span>ul<span class="op">&gt;</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>                <span class="op">{{</span>#cartoons<span class="op">}}</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>                  <span class="op">&lt;</span>li<span class="op">&gt;</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>                    <span class="op">{{</span>name<span class="op">}}</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>                    <span class="op">{{</span>#hasMovie<span class="op">}}</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>                      <span class="op">(</span>there is a movie<span class="op">)</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>                    <span class="op">{{/</span>hasMovie<span class="op">}}</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>                  <span class="op">&lt;/</span>li<span class="op">&gt;</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a>                <span class="op">{{/</span>cartoons<span class="op">}}</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a>                <span class="op">&lt;/</span>ul<span class="op">&gt;</span></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a>              <span class="op">&lt;/</span>body<span class="op">&gt;</span></span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a>            <span class="op">&lt;/</span>html<span class="op">&gt;</span></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;&quot;&quot;;</span></span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a>    var compiledTemplate <span class="op">=</span> Mustache<span class="op">.</span><span class="fu">compiler</span><span class="op">()</span></span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">compile</span><span class="op">(</span>template<span class="op">);</span></span>
<span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-37"><a href="#cb1-37" aria-hidden="true" tabindex="-1"></a>    var renderedTemplate <span class="op">=</span> compiledTemplate<span class="op">.</span><span class="fu">execute</span><span class="op">(</span></span>
<span id="cb1-38"><a href="#cb1-38" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Map</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;cartoons&quot;</span><span class="op">,</span> cartoons<span class="op">)</span></span>
<span id="cb1-39"><a href="#cb1-39" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb1-40"><a href="#cb1-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-41"><a href="#cb1-41" aria-hidden="true" tabindex="-1"></a>    <span class="co">// &lt;html&gt;</span></span>
<span id="cb1-42"><a href="#cb1-42" aria-hidden="true" tabindex="-1"></a>    <span class="co">//  &lt;body&gt;</span></span>
<span id="cb1-43"><a href="#cb1-43" aria-hidden="true" tabindex="-1"></a>    <span class="co">//    &lt;h1&gt; Cartoons &lt;/h1&gt;</span></span>
<span id="cb1-44"><a href="#cb1-44" aria-hidden="true" tabindex="-1"></a>    <span class="co">//    &lt;ul&gt;</span></span>
<span id="cb1-45"><a href="#cb1-45" aria-hidden="true" tabindex="-1"></a>    <span class="co">//      &lt;li&gt;</span></span>
<span id="cb1-46"><a href="#cb1-46" aria-hidden="true" tabindex="-1"></a>    <span class="co">//        Space Ghost Coast to Coast</span></span>
<span id="cb1-47"><a href="#cb1-47" aria-hidden="true" tabindex="-1"></a>    <span class="co">//      &lt;/li&gt;</span></span>
<span id="cb1-48"><a href="#cb1-48" aria-hidden="true" tabindex="-1"></a>    <span class="co">//      &lt;li&gt;</span></span>
<span id="cb1-49"><a href="#cb1-49" aria-hidden="true" tabindex="-1"></a>    <span class="co">//        Harvey Birdman, Attorney at Law</span></span>
<span id="cb1-50"><a href="#cb1-50" aria-hidden="true" tabindex="-1"></a>    <span class="co">//      &lt;/li&gt;</span></span>
<span id="cb1-51"><a href="#cb1-51" aria-hidden="true" tabindex="-1"></a>    <span class="co">//      &lt;li&gt;</span></span>
<span id="cb1-52"><a href="#cb1-52" aria-hidden="true" tabindex="-1"></a>    <span class="co">//        Sealab 2021</span></span>
<span id="cb1-53"><a href="#cb1-53" aria-hidden="true" tabindex="-1"></a>    <span class="co">//      &lt;/li&gt;</span></span>
<span id="cb1-54"><a href="#cb1-54" aria-hidden="true" tabindex="-1"></a>    <span class="co">//      &lt;li&gt;</span></span>
<span id="cb1-55"><a href="#cb1-55" aria-hidden="true" tabindex="-1"></a>    <span class="co">//        The Venture Bros.</span></span>
<span id="cb1-56"><a href="#cb1-56" aria-hidden="true" tabindex="-1"></a>    <span class="co">//          (there is a movie)</span></span>
<span id="cb1-57"><a href="#cb1-57" aria-hidden="true" tabindex="-1"></a>    <span class="co">//      &lt;/li&gt;</span></span>
<span id="cb1-58"><a href="#cb1-58" aria-hidden="true" tabindex="-1"></a>    <span class="co">//    &lt;/ul&gt;</span></span>
<span id="cb1-59"><a href="#cb1-59" aria-hidden="true" tabindex="-1"></a>    <span class="co">//  &lt;/body&gt;</span></span>
<span id="cb1-60"><a href="#cb1-60" aria-hidden="true" tabindex="-1"></a>    <span class="co">//&lt;/html&gt;</span></span>
<span id="cb1-61"><a href="#cb1-61" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>renderedTemplate<span class="op">);</span></span>
<span id="cb1-62"><a href="#cb1-62" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>com.nulabinc.zxcvbn</title><link>https://mccue.dev/pages/12-15-23-java-library-of-the-day-15</link><description></description><pubDate>Fri, 15 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>com.nulabinc.zxcvbn</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">com.nulabinc.zxcvbn</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/com.nulab-inc/zxcvbn"><code>com.nulab-inc/zxcvbn</code></a></li>
<li>Module Name: <code>com.nulabinc.zxcvbn</code></li>
<li>GitHub: <a href="https://github.com/nulab/zxcvbn4j"><code>nulab/zxcvbn4j</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogMTk5LjU2MnB4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii04IC04IDE5OS41NjI1IDUwIiByb2xlPSJncmFwaGljcy1kb2N1bWVudCBkb2N1bWVudCIgYXJpYS1yb2xlZGVzY3JpcHRpb249ImZsb3djaGFydC12MiI+PHN0eWxlPiNteS1zdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O2ZpbGw6IzMzMzt9I215LXN2ZyAuZXJyb3ItaWNvbntmaWxsOiM1NTIyMjI7fSNteS1zdmcgLmVycm9yLXRleHR7ZmlsbDojNTUyMjIyO3N0cm9rZTojNTUyMjIyO30jbXktc3ZnIC5lZGdlLXRoaWNrbmVzcy1ub3JtYWx7c3Ryb2tlLXdpZHRoOjJweDt9I215LXN2ZyAuZWRnZS10aGlja25lc3MtdGhpY2t7c3Ryb2tlLXdpZHRoOjMuNXB4O30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tc29saWR7c3Ryb2tlLWRhc2hhcnJheTowO30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tZGFzaGVke3N0cm9rZS1kYXNoYXJyYXk6Mzt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLWRvdHRlZHtzdHJva2UtZGFzaGFycmF5OjI7fSNteS1zdmcgLm1hcmtlcntmaWxsOiMzMzMzMzM7c3Ryb2tlOiMzMzMzMzM7fSNteS1zdmcgLm1hcmtlci5jcm9zc3tzdHJva2U6IzMzMzMzMzt9I215LXN2ZyBzdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O30jbXktc3ZnIC5sYWJlbHtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Y29sb3I6IzMzMzt9I215LXN2ZyAuY2x1c3Rlci1sYWJlbCB0ZXh0e2ZpbGw6IzMzMzt9I215LXN2ZyAuY2x1c3Rlci1sYWJlbCBzcGFuLCNteS1zdmcgcHtjb2xvcjojMzMzO30jbXktc3ZnIC5sYWJlbCB0ZXh0LCNteS1zdmcgc3BhbiwjbXktc3ZnIHB7ZmlsbDojMzMzO2NvbG9yOiMzMzM7fSNteS1zdmcgLm5vZGUgcmVjdCwjbXktc3ZnIC5ub2RlIGNpcmNsZSwjbXktc3ZnIC5ub2RlIGVsbGlwc2UsI215LXN2ZyAubm9kZSBwb2x5Z29uLCNteS1zdmcgLm5vZGUgcGF0aHtmaWxsOiNFQ0VDRkY7c3Ryb2tlOiM5MzcwREI7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAuZmxvd2NoYXJ0LWxhYmVsIHRleHR7dGV4dC1hbmNob3I6bWlkZGxlO30jbXktc3ZnIC5ub2RlIC5rYXRleCBwYXRoe2ZpbGw6IzAwMDtzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5ub2RlIC5sYWJlbHt0ZXh0LWFsaWduOmNlbnRlcjt9I215LXN2ZyAubm9kZS5jbGlja2FibGV7Y3Vyc29yOnBvaW50ZXI7fSNteS1zdmcgLmFycm93aGVhZFBhdGh7ZmlsbDojMzMzMzMzO30jbXktc3ZnIC5lZGdlUGF0aCAucGF0aHtzdHJva2U6IzMzMzMzMztzdHJva2Utd2lkdGg6Mi4wcHg7fSNteS1zdmcgLmZsb3djaGFydC1saW5re3N0cm9rZTojMzMzMzMzO2ZpbGw6bm9uZTt9I215LXN2ZyAuZWRnZUxhYmVse2JhY2tncm91bmQtY29sb3I6I2U4ZThlODt0ZXh0LWFsaWduOmNlbnRlcjt9I215LXN2ZyAuZWRnZUxhYmVsIHJlY3R7b3BhY2l0eTowLjU7YmFja2dyb3VuZC1jb2xvcjojZThlOGU4O2ZpbGw6I2U4ZThlODt9I215LXN2ZyAubGFiZWxCa2d7YmFja2dyb3VuZC1jb2xvcjpyZ2JhKDIzMiwgMjMyLCAyMzIsIDAuNSk7fSNteS1zdmcgLmNsdXN0ZXIgcmVjdHtmaWxsOiNmZmZmZGU7c3Ryb2tlOiNhYWFhMzM7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAuY2x1c3RlciB0ZXh0e2ZpbGw6IzMzMzt9I215LXN2ZyAuY2x1c3RlciBzcGFuLCNteS1zdmcgcHtjb2xvcjojMzMzO30jbXktc3ZnIGRpdi5tZXJtYWlkVG9vbHRpcHtwb3NpdGlvbjphYnNvbHV0ZTt0ZXh0LWFsaWduOmNlbnRlcjttYXgtd2lkdGg6MjAwcHg7cGFkZGluZzoycHg7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxMnB4O2JhY2tncm91bmQ6aHNsKDgwLCAxMDAlLCA5Ni4yNzQ1MDk4MDM5JSk7Ym9yZGVyOjFweCBzb2xpZCAjYWFhYTMzO2JvcmRlci1yYWRpdXM6MnB4O3BvaW50ZXItZXZlbnRzOm5vbmU7ei1pbmRleDoxMDA7fSNteS1zdmcgLmZsb3djaGFydFRpdGxlVGV4dHt0ZXh0LWFuY2hvcjptaWRkbGU7Zm9udC1zaXplOjE4cHg7ZmlsbDojMzMzO30jbXktc3ZnIDpyb290ey0tbWVybWFpZC1mb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7fSNteS1zdmcgLmdyZWVuJmd0Oyp7c3Ryb2tlOnJnYigyNTUsIDAsIDApIWltcG9ydGFudDt9I215LXN2ZyAuZ3JlZW4gc3BhbntzdHJva2U6cmdiKDI1NSwgMCwgMCkhaW1wb3J0YW50O308L3N0eWxlPjxnPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtcG9pbnRFbmQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjYiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjEyIiBtYXJrZXJIZWlnaHQ9IjEyIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMCAwIEwgMTAgNSBMIDAgMTAgeiIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LXBvaW50U3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjQuNSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTIiIG1hcmtlckhlaWdodD0iMTIiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAwIDUgTCAxMCAxMCBMIDEwIDAgeiIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNpcmNsZUVuZCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iMTEiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxjaXJjbGUgY3g9IjUiIGN5PSI1IiByPSI1IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY2lyY2xlU3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9Ii0xIiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48Y2lyY2xlIGN4PSI1IiBjeT0iNSIgcj0iNSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNyb3NzRW5kIiBjbGFzcz0ibWFya2VyIGNyb3NzIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDExIDExIiByZWZYPSIxMiIgcmVmWT0iNS4yIiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDEsMSBsIDksOSBNIDEwLDEgbCAtOSw5IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAyOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY3Jvc3NTdGFydCIgY2xhc3M9Im1hcmtlciBjcm9zcyBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMSAxMSIgcmVmWD0iLTEiIHJlZlk9IjUuMiIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAxLDEgbCA5LDkgTSAxMCwxIGwgLTksOSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMjsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48ZyBjbGFzcz0icm9vdCI+PGcgY2xhc3M9ImNsdXN0ZXJzIi8+PGcgY2xhc3M9ImVkZ2VQYXRocyIvPjxnIGNsYXNzPSJlZGdlTGFiZWxzIi8+PGcgY2xhc3M9Im5vZGVzIj48ZyBjbGFzcz0ibm9kZSBkZWZhdWx0IGdyZWVuIGZsb3djaGFydC1sYWJlbCIgaWQ9ImZsb3djaGFydC16eGN2Ym4tMCIgZGF0YS1ub2RlPSJ0cnVlIiBkYXRhLWlkPSJ6eGN2Ym4iIHRyYW5zZm9ybT0idHJhbnNsYXRlKDkxLjc4MTI1LCAxNykiPjxyZWN0IGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiIHN0eWxlPSIiIHJ4PSIwIiByeT0iMCIgeD0iLTkxLjc4MTI1IiB5PSItMTciIHdpZHRoPSIxODMuNTYyNSIgaGVpZ2h0PSIzNCIvPjxnIGNsYXNzPSJsYWJlbCIgc3R5bGU9IiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTg0LjI4MTI1LCAtOS41KSI+PHJlY3QvPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIxNjguNTYyNSIgaGVpZ2h0PSIxOSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPmNvbS5udWxhYmluYy56eGN2Ym48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjwvZz48L2c+PC9zdmc+" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>com.nulabinc.zxcvbn</code>, so named after one of the <a href="https://en.wikipedia.org/wiki/Wikipedia:10,000_most_common_passwords">100 most common passwords</a>, is a password strength estimator.</p>
<h2 id="why-use-it">Why use it</h2>
<p>People aren't very good at picking passwords. While it is technically their fault if they make their password <code>123456</code> and get their bank account stolen, that can very quickly become your problem.</p>
<p>Some services try to mitigate this by asking that passwords have letters, numbers, and "special characters" in them. This doesn't stop things like <code>P@ssW1rd!</code>, which will be guessed by password crackers in under a millisecond.</p>
<p><code>com.nulabinc.zxcvbn</code> will instead try to figure out how easy it will be for a password cracker to guess the password. This will lead to your users having generally stronger passwords.</p>
<h2 id="getting-started">Getting Started</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">nulabinc</span><span class="op">.</span><span class="im">zxcvbn</span><span class="op">.</span><span class="im">WipeableString</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">nulabinc</span><span class="op">.</span><span class="im">zxcvbn</span><span class="op">.</span><span class="im">Zxcvbn</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    var zxcvbn <span class="op">=</span> <span class="kw">new</span> <span class="fu">Zxcvbn</span><span class="op">();</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Pro-tip, storing passwords in mutable structures lets</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    <span class="co">// you lower the time they are floating around in program</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    <span class="co">// memory. This decreases the window of opportunity for</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>    <span class="co">// attackers that might have found a way to poke around</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>    <span class="co">// in your process.</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>    <span class="co">//</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>    <span class="co">// If that sort of attack isn&#39;t in your threat model, you</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>    <span class="co">// can use regular Strings.</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>    var password <span class="op">=</span> <span class="kw">new</span> <span class="fu">WipeableString</span><span class="op">(</span><span class="st">&quot;P@ssw0rd!&quot;</span><span class="op">);</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>    var strength <span class="op">=</span> zxcvbn<span class="op">.</span><span class="fu">measure</span><span class="op">(</span>password<span class="op">);</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>    var warning <span class="op">=</span> strength<span class="op">.</span><span class="fu">getFeedback</span><span class="op">()</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">getWarning</span><span class="op">();</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>    <span class="co">// This is similar to a commonly used password.</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>warning<span class="op">);</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>    var suggestions <span class="op">=</span> strength<span class="op">.</span><span class="fu">getFeedback</span><span class="op">()</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">getSuggestions</span><span class="op">();</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Add another word or two. Uncommon words are better.</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Capitalization doesn&#39;t help very much.</span></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Predictable substitutions like &#39;@&#39; instead of &#39;a&#39; don&#39;t help very much.</span></span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="bu">String</span><span class="op">.</span><span class="fu">join</span><span class="op">(</span><span class="st">&quot;</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> suggestions<span class="op">));</span></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a>    <span class="co">// fair</span></span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a>    <span class="cf">switch</span> <span class="op">(</span>strength<span class="op">.</span><span class="fu">getScore</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a>        <span class="cf">case</span> <span class="dv">0</span> <span class="op">-&gt;</span> <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;weak&quot;</span><span class="op">);</span></span>
<span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a>        <span class="cf">case</span> <span class="dv">1</span> <span class="op">-&gt;</span> <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;fair&quot;</span><span class="op">);</span></span>
<span id="cb1-37"><a href="#cb1-37" aria-hidden="true" tabindex="-1"></a>        <span class="cf">case</span> <span class="dv">2</span> <span class="op">-&gt;</span> <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;good&quot;</span><span class="op">);</span></span>
<span id="cb1-38"><a href="#cb1-38" aria-hidden="true" tabindex="-1"></a>        <span class="cf">case</span> <span class="dv">3</span> <span class="op">-&gt;</span> <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;strong&quot;</span><span class="op">);</span></span>
<span id="cb1-39"><a href="#cb1-39" aria-hidden="true" tabindex="-1"></a>        <span class="kw">default</span> <span class="op">-&gt;</span> <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;very strong&quot;</span><span class="op">);</span></span>
<span id="cb1-40"><a href="#cb1-40" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-41"><a href="#cb1-41" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>dev.mccue.microhttp.cookies</title><link>https://mccue.dev/pages/12-14-23-java-library-of-the-day-14</link><description></description><pubDate>Thu, 14 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>dev.mccue.microhttp.cookies</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">dev.mccue.microhttp.cookies</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/dev.mccue/microhttp-cookies"><code>dev.mccue/microhttp-cookies</code></a></li>
<li>Module Name: <code>dev.mccue.microhttp.cookies</code></li>
<li>GitHub: <a href="https://github.com/bowbahdoe/microhttp-cookies"><code>bowbahdoe/microhttp-cookies</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogMjY1LjYwOXB4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii04IC04IDI2NS42MDkzNzUgMTM0IiByb2xlPSJncmFwaGljcy1kb2N1bWVudCBkb2N1bWVudCIgYXJpYS1yb2xlZGVzY3JpcHRpb249ImZsb3djaGFydC12MiI+PHN0eWxlPiNteS1zdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O2ZpbGw6IzMzMzt9I215LXN2ZyAuZXJyb3ItaWNvbntmaWxsOiM1NTIyMjI7fSNteS1zdmcgLmVycm9yLXRleHR7ZmlsbDojNTUyMjIyO3N0cm9rZTojNTUyMjIyO30jbXktc3ZnIC5lZGdlLXRoaWNrbmVzcy1ub3JtYWx7c3Ryb2tlLXdpZHRoOjJweDt9I215LXN2ZyAuZWRnZS10aGlja25lc3MtdGhpY2t7c3Ryb2tlLXdpZHRoOjMuNXB4O30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tc29saWR7c3Ryb2tlLWRhc2hhcnJheTowO30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tZGFzaGVke3N0cm9rZS1kYXNoYXJyYXk6Mzt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLWRvdHRlZHtzdHJva2UtZGFzaGFycmF5OjI7fSNteS1zdmcgLm1hcmtlcntmaWxsOiMzMzMzMzM7c3Ryb2tlOiMzMzMzMzM7fSNteS1zdmcgLm1hcmtlci5jcm9zc3tzdHJva2U6IzMzMzMzMzt9I215LXN2ZyBzdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O30jbXktc3ZnIC5sYWJlbHtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Y29sb3I6IzMzMzt9I215LXN2ZyAuY2x1c3Rlci1sYWJlbCB0ZXh0e2ZpbGw6IzMzMzt9I215LXN2ZyAuY2x1c3Rlci1sYWJlbCBzcGFuLCNteS1zdmcgcHtjb2xvcjojMzMzO30jbXktc3ZnIC5sYWJlbCB0ZXh0LCNteS1zdmcgc3BhbiwjbXktc3ZnIHB7ZmlsbDojMzMzO2NvbG9yOiMzMzM7fSNteS1zdmcgLm5vZGUgcmVjdCwjbXktc3ZnIC5ub2RlIGNpcmNsZSwjbXktc3ZnIC5ub2RlIGVsbGlwc2UsI215LXN2ZyAubm9kZSBwb2x5Z29uLCNteS1zdmcgLm5vZGUgcGF0aHtmaWxsOiNFQ0VDRkY7c3Ryb2tlOiM5MzcwREI7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAuZmxvd2NoYXJ0LWxhYmVsIHRleHR7dGV4dC1hbmNob3I6bWlkZGxlO30jbXktc3ZnIC5ub2RlIC5rYXRleCBwYXRoe2ZpbGw6IzAwMDtzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5ub2RlIC5sYWJlbHt0ZXh0LWFsaWduOmNlbnRlcjt9I215LXN2ZyAubm9kZS5jbGlja2FibGV7Y3Vyc29yOnBvaW50ZXI7fSNteS1zdmcgLmFycm93aGVhZFBhdGh7ZmlsbDojMzMzMzMzO30jbXktc3ZnIC5lZGdlUGF0aCAucGF0aHtzdHJva2U6IzMzMzMzMztzdHJva2Utd2lkdGg6Mi4wcHg7fSNteS1zdmcgLmZsb3djaGFydC1saW5re3N0cm9rZTojMzMzMzMzO2ZpbGw6bm9uZTt9I215LXN2ZyAuZWRnZUxhYmVse2JhY2tncm91bmQtY29sb3I6I2U4ZThlODt0ZXh0LWFsaWduOmNlbnRlcjt9I215LXN2ZyAuZWRnZUxhYmVsIHJlY3R7b3BhY2l0eTowLjU7YmFja2dyb3VuZC1jb2xvcjojZThlOGU4O2ZpbGw6I2U4ZThlODt9I215LXN2ZyAubGFiZWxCa2d7YmFja2dyb3VuZC1jb2xvcjpyZ2JhKDIzMiwgMjMyLCAyMzIsIDAuNSk7fSNteS1zdmcgLmNsdXN0ZXIgcmVjdHtmaWxsOiNmZmZmZGU7c3Ryb2tlOiNhYWFhMzM7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAuY2x1c3RlciB0ZXh0e2ZpbGw6IzMzMzt9I215LXN2ZyAuY2x1c3RlciBzcGFuLCNteS1zdmcgcHtjb2xvcjojMzMzO30jbXktc3ZnIGRpdi5tZXJtYWlkVG9vbHRpcHtwb3NpdGlvbjphYnNvbHV0ZTt0ZXh0LWFsaWduOmNlbnRlcjttYXgtd2lkdGg6MjAwcHg7cGFkZGluZzoycHg7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxMnB4O2JhY2tncm91bmQ6aHNsKDgwLCAxMDAlLCA5Ni4yNzQ1MDk4MDM5JSk7Ym9yZGVyOjFweCBzb2xpZCAjYWFhYTMzO2JvcmRlci1yYWRpdXM6MnB4O3BvaW50ZXItZXZlbnRzOm5vbmU7ei1pbmRleDoxMDA7fSNteS1zdmcgLmZsb3djaGFydFRpdGxlVGV4dHt0ZXh0LWFuY2hvcjptaWRkbGU7Zm9udC1zaXplOjE4cHg7ZmlsbDojMzMzO30jbXktc3ZnIDpyb290ey0tbWVybWFpZC1mb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7fSNteS1zdmcgLmdyZWVuJmd0Oyp7c3Ryb2tlOnJnYigyNTUsIDAsIDApIWltcG9ydGFudDt9I215LXN2ZyAuZ3JlZW4gc3BhbntzdHJva2U6cmdiKDI1NSwgMCwgMCkhaW1wb3J0YW50O308L3N0eWxlPjxnPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtcG9pbnRFbmQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjYiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjEyIiBtYXJrZXJIZWlnaHQ9IjEyIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMCAwIEwgMTAgNSBMIDAgMTAgeiIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LXBvaW50U3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjQuNSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTIiIG1hcmtlckhlaWdodD0iMTIiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAwIDUgTCAxMCAxMCBMIDEwIDAgeiIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNpcmNsZUVuZCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iMTEiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxjaXJjbGUgY3g9IjUiIGN5PSI1IiByPSI1IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY2lyY2xlU3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9Ii0xIiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48Y2lyY2xlIGN4PSI1IiBjeT0iNSIgcj0iNSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNyb3NzRW5kIiBjbGFzcz0ibWFya2VyIGNyb3NzIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDExIDExIiByZWZYPSIxMiIgcmVmWT0iNS4yIiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDEsMSBsIDksOSBNIDEwLDEgbCAtOSw5IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAyOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY3Jvc3NTdGFydCIgY2xhc3M9Im1hcmtlciBjcm9zcyBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMSAxMSIgcmVmWD0iLTEiIHJlZlk9IjUuMiIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAxLDEgbCA5LDkgTSAxMCwxIGwgLTksOSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMjsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48ZyBjbGFzcz0icm9vdCI+PGcgY2xhc3M9ImNsdXN0ZXJzIi8+PGcgY2xhc3M9ImVkZ2VQYXRocyI+PHBhdGggZD0iTTEyNC44MDUsMzRMMTI0LjgwNSwzOC4xNjdDMTI0LjgwNSw0Mi4zMzMsMTI0LjgwNSw1MC42NjcsMTI0LjgwNSw1OC4xMTdDMTI0LjgwNSw2NS41NjcsMTI0LjgwNSw3Mi4xMzMsMTI0LjgwNSw3NS40MTdMMTI0LjgwNSw3OC43IiBpZD0iTC1taWNyb2h0dHAtbWljcm9odHRwY29va2llcy0wIiBjbGFzcz0iZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1taWNyb2h0dHAgTEUtbWljcm9odHRwY29va2llcyIgc3R5bGU9ImZpbGw6bm9uZTsiIG1hcmtlci1lbmQ9InVybCgjbXktc3ZnX2Zsb3djaGFydC1wb2ludEVuZCkiLz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbHMiPjxnIGNsYXNzPSJlZGdlTGFiZWwiPjxnIGNsYXNzPSJsYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMCkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIwIiBoZWlnaHQ9IjAiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0iZWRnZUxhYmVsIj48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjxnIGNsYXNzPSJub2RlcyI+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IGZsb3djaGFydC1sYWJlbCIgaWQ9ImZsb3djaGFydC1taWNyb2h0dHAtMCIgZGF0YS1ub2RlPSJ0cnVlIiBkYXRhLWlkPSJtaWNyb2h0dHAiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEyNC44MDQ2ODc1LCAxNykiPjxyZWN0IGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiIHN0eWxlPSIiIHJ4PSIwIiByeT0iMCIgeD0iLTYyLjAwNzgxMjUiIHk9Ii0xNyIgd2lkdGg9IjEyNC4wMTU2MjUiIGhlaWdodD0iMzQiLz48ZyBjbGFzcz0ibGFiZWwiIHN0eWxlPSIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC01NC41MDc4MTI1LCAtOS41KSI+PHJlY3QvPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIxMDkuMDE1NjI1IiBoZWlnaHQ9IjE5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+b3JnLm1pY3JvaHR0cDwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0ibm9kZSBkZWZhdWx0IGdyZWVuIGZsb3djaGFydC1sYWJlbCIgaWQ9ImZsb3djaGFydC1taWNyb2h0dHBjb29raWVzLTEiIGRhdGEtbm9kZT0idHJ1ZSIgZGF0YS1pZD0ibWljcm9odHRwY29va2llcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTI0LjgwNDY4NzUsIDEwMSkiPjxyZWN0IGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiIHN0eWxlPSIiIHJ4PSIwIiByeT0iMCIgeD0iLTEyNC44MDQ2ODc1IiB5PSItMTciIHdpZHRoPSIyNDkuNjA5Mzc1IiBoZWlnaHQ9IjM0Ii8+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTE3LjMwNDY4NzUsIC05LjUpIj48cmVjdC8+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjIzNC42MDkzNzUiIGhlaWdodD0iMTkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj5kZXYubWNjdWUubWljcm9odHRwLmNvb2tpZXM8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjwvZz48L2c+PC9zdmc+" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>dev.mccue.microhttp.cookies</code> provides a utility parsing cookie headers sent in requests, specifically microhttp's <code>Request</code> objects.</p>
<h2 id="why-use-it">Why use it</h2>
<p>If you've asked a user to send you a cookie on subsequent requests, such as with <code>dev.mccue.microhttp.setcookie</code>, you will most likely want to interpret the data in that cookie when you get it.</p>
<p>This library provides the ability to do that.</p>
<h2 id="getting-started">Getting Started</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">cookies</span><span class="op">.</span><span class="im">Cookies</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">setcookie</span><span class="op">.</span><span class="im">SetCookieHeader</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">EventLoop</span><span class="op">;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">Options</span><span class="op">;</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">Response</span><span class="op">;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">List</span><span class="op">;</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="kw">throws</span> <span class="bu">Exception</span> <span class="op">{</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>    var eventLoop <span class="op">=</span> <span class="kw">new</span> <span class="fu">EventLoop</span><span class="op">((</span>request<span class="op">,</span> consumer<span class="op">)</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>        var cookies <span class="op">=</span> Cookies<span class="op">.</span><span class="fu">parse</span><span class="op">(</span>request<span class="op">);</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>        var counter <span class="op">=</span> cookies<span class="op">.</span><span class="fu">get</span><span class="op">(</span><span class="st">&quot;Counter&quot;</span><span class="op">)</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">orElse</span><span class="op">(</span><span class="st">&quot;0&quot;</span><span class="op">);</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>        var setCookieHeader <span class="op">=</span> SetCookieHeader<span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;Counter&quot;</span><span class="op">,</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Integer</span><span class="op">.</span><span class="fu">toString</span><span class="op">(</span><span class="bu">Integer</span><span class="op">.</span><span class="fu">parseInt</span><span class="op">(</span>counter<span class="op">)</span> <span class="op">+</span> <span class="dv">1</span><span class="op">)</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>        consumer<span class="op">.</span><span class="fu">accept</span><span class="op">(</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>                <span class="kw">new</span> <span class="bu">Response</span><span class="op">(</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>                        <span class="dv">200</span><span class="op">,</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>                        <span class="st">&quot;OK&quot;</span><span class="op">,</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>                        <span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>setCookieHeader<span class="op">),</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>                        counter<span class="op">.</span><span class="fu">getBytes</span><span class="op">()</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>                <span class="op">)</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">});</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a>    eventLoop<span class="op">.</span><span class="fu">start</span><span class="op">();</span></span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a>    eventLoop<span class="op">.</span><span class="fu">join</span><span class="op">();</span></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>dev.mccue.microhttp.setcookie</title><link>https://mccue.dev/pages/12-13-23-java-library-of-the-day-13</link><description></description><pubDate>Wed, 13 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>dev.mccue.microhttp.setcookie</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">dev.mccue.microhttp.setcookie</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/dev.mccue/microhttp-setcookie"><code>dev.mccue/microhttp-setcookie</code></a></li>
<li>Module Name: <code>dev.mccue.microhttp.setcookie</code></li>
<li>GitHub: <a href="https://github.com/bowbahdoe/microhttp-setcookie"><code>bowbahdoe/microhttp-setcookie</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogMjgxLjcxOXB4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii04IC04IDI4MS43MTg3NSAxMzQiIHJvbGU9ImdyYXBoaWNzLWRvY3VtZW50IGRvY3VtZW50IiBhcmlhLXJvbGVkZXNjcmlwdGlvbj0iZmxvd2NoYXJ0LXYyIj48c3R5bGU+I215LXN2Z3tmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjE2cHg7ZmlsbDojMzMzO30jbXktc3ZnIC5lcnJvci1pY29ue2ZpbGw6IzU1MjIyMjt9I215LXN2ZyAuZXJyb3ItdGV4dHtmaWxsOiM1NTIyMjI7c3Ryb2tlOiM1NTIyMjI7fSNteS1zdmcgLmVkZ2UtdGhpY2tuZXNzLW5vcm1hbHtzdHJva2Utd2lkdGg6MnB4O30jbXktc3ZnIC5lZGdlLXRoaWNrbmVzcy10aGlja3tzdHJva2Utd2lkdGg6My41cHg7fSNteS1zdmcgLmVkZ2UtcGF0dGVybi1zb2xpZHtzdHJva2UtZGFzaGFycmF5OjA7fSNteS1zdmcgLmVkZ2UtcGF0dGVybi1kYXNoZWR7c3Ryb2tlLWRhc2hhcnJheTozO30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tZG90dGVke3N0cm9rZS1kYXNoYXJyYXk6Mjt9I215LXN2ZyAubWFya2Vye2ZpbGw6IzMzMzMzMztzdHJva2U6IzMzMzMzMzt9I215LXN2ZyAubWFya2VyLmNyb3Nze3N0cm9rZTojMzMzMzMzO30jbXktc3ZnIHN2Z3tmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjE2cHg7fSNteS1zdmcgLmxhYmVse2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtjb2xvcjojMzMzO30jbXktc3ZnIC5jbHVzdGVyLWxhYmVsIHRleHR7ZmlsbDojMzMzO30jbXktc3ZnIC5jbHVzdGVyLWxhYmVsIHNwYW4sI215LXN2ZyBwe2NvbG9yOiMzMzM7fSNteS1zdmcgLmxhYmVsIHRleHQsI215LXN2ZyBzcGFuLCNteS1zdmcgcHtmaWxsOiMzMzM7Y29sb3I6IzMzMzt9I215LXN2ZyAubm9kZSByZWN0LCNteS1zdmcgLm5vZGUgY2lyY2xlLCNteS1zdmcgLm5vZGUgZWxsaXBzZSwjbXktc3ZnIC5ub2RlIHBvbHlnb24sI215LXN2ZyAubm9kZSBwYXRoe2ZpbGw6I0VDRUNGRjtzdHJva2U6IzkzNzBEQjtzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5mbG93Y2hhcnQtbGFiZWwgdGV4dHt0ZXh0LWFuY2hvcjptaWRkbGU7fSNteS1zdmcgLm5vZGUgLmthdGV4IHBhdGh7ZmlsbDojMDAwO3N0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxcHg7fSNteS1zdmcgLm5vZGUgLmxhYmVse3RleHQtYWxpZ246Y2VudGVyO30jbXktc3ZnIC5ub2RlLmNsaWNrYWJsZXtjdXJzb3I6cG9pbnRlcjt9I215LXN2ZyAuYXJyb3doZWFkUGF0aHtmaWxsOiMzMzMzMzM7fSNteS1zdmcgLmVkZ2VQYXRoIC5wYXRoe3N0cm9rZTojMzMzMzMzO3N0cm9rZS13aWR0aDoyLjBweDt9I215LXN2ZyAuZmxvd2NoYXJ0LWxpbmt7c3Ryb2tlOiMzMzMzMzM7ZmlsbDpub25lO30jbXktc3ZnIC5lZGdlTGFiZWx7YmFja2dyb3VuZC1jb2xvcjojZThlOGU4O3RleHQtYWxpZ246Y2VudGVyO30jbXktc3ZnIC5lZGdlTGFiZWwgcmVjdHtvcGFjaXR5OjAuNTtiYWNrZ3JvdW5kLWNvbG9yOiNlOGU4ZTg7ZmlsbDojZThlOGU4O30jbXktc3ZnIC5sYWJlbEJrZ3tiYWNrZ3JvdW5kLWNvbG9yOnJnYmEoMjMyLCAyMzIsIDIzMiwgMC41KTt9I215LXN2ZyAuY2x1c3RlciByZWN0e2ZpbGw6I2ZmZmZkZTtzdHJva2U6I2FhYWEzMztzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5jbHVzdGVyIHRleHR7ZmlsbDojMzMzO30jbXktc3ZnIC5jbHVzdGVyIHNwYW4sI215LXN2ZyBwe2NvbG9yOiMzMzM7fSNteS1zdmcgZGl2Lm1lcm1haWRUb29sdGlwe3Bvc2l0aW9uOmFic29sdXRlO3RleHQtYWxpZ246Y2VudGVyO21heC13aWR0aDoyMDBweDtwYWRkaW5nOjJweDtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjEycHg7YmFja2dyb3VuZDpoc2woODAsIDEwMCUsIDk2LjI3NDUwOTgwMzklKTtib3JkZXI6MXB4IHNvbGlkICNhYWFhMzM7Ym9yZGVyLXJhZGl1czoycHg7cG9pbnRlci1ldmVudHM6bm9uZTt6LWluZGV4OjEwMDt9I215LXN2ZyAuZmxvd2NoYXJ0VGl0bGVUZXh0e3RleHQtYW5jaG9yOm1pZGRsZTtmb250LXNpemU6MThweDtmaWxsOiMzMzM7fSNteS1zdmcgOnJvb3R7LS1tZXJtYWlkLWZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjt9I215LXN2ZyAuZ3JlZW4mZ3Q7KntzdHJva2U6cmdiKDI1NSwgMCwgMCkhaW1wb3J0YW50O30jbXktc3ZnIC5ncmVlbiBzcGFue3N0cm9rZTpyZ2IoMjU1LCAwLCAwKSFpbXBvcnRhbnQ7fTwvc3R5bGU+PGc+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1wb2ludEVuZCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iNiIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTIiIG1hcmtlckhlaWdodD0iMTIiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAwIDAgTCAxMCA1IEwgMCAxMCB6IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtcG9pbnRTdGFydCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iNC41IiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMiIgbWFya2VySGVpZ2h0PSIxMiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDAgNSBMIDEwIDEwIEwgMTAgMCB6IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY2lyY2xlRW5kIiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSIxMSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PGNpcmNsZSBjeD0iNSIgY3k9IjUiIHI9IjUiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jaXJjbGVTdGFydCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iLTEiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxjaXJjbGUgY3g9IjUiIGN5PSI1IiByPSI1IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY3Jvc3NFbmQiIGNsYXNzPSJtYXJrZXIgY3Jvc3MgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTEgMTEiIHJlZlg9IjEyIiByZWZZPSI1LjIiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMSwxIGwgOSw5IE0gMTAsMSBsIC05LDkiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDI7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jcm9zc1N0YXJ0IiBjbGFzcz0ibWFya2VyIGNyb3NzIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDExIDExIiByZWZYPSItMSIgcmVmWT0iNS4yIiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDEsMSBsIDksOSBNIDEwLDEgbCAtOSw5IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAyOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxnIGNsYXNzPSJyb290Ij48ZyBjbGFzcz0iY2x1c3RlcnMiLz48ZyBjbGFzcz0iZWRnZVBhdGhzIj48cGF0aCBkPSJNMTMyLjg1OSwzNEwxMzIuODU5LDM4LjE2N0MxMzIuODU5LDQyLjMzMywxMzIuODU5LDUwLjY2NywxMzIuODU5LDU4LjExN0MxMzIuODU5LDY1LjU2NywxMzIuODU5LDcyLjEzMywxMzIuODU5LDc1LjQxN0wxMzIuODU5LDc4LjciIGlkPSJMLW1pY3JvaHR0cC1taWNyb2h0dHBzZXRjb29raWUtMCIgY2xhc3M9ImVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtbWljcm9odHRwIExFLW1pY3JvaHR0cHNldGNvb2tpZSIgc3R5bGU9ImZpbGw6bm9uZTsiIG1hcmtlci1lbmQ9InVybCgjbXktc3ZnX2Zsb3djaGFydC1wb2ludEVuZCkiLz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbHMiPjxnIGNsYXNzPSJlZGdlTGFiZWwiPjxnIGNsYXNzPSJsYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMCkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIwIiBoZWlnaHQ9IjAiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0iZWRnZUxhYmVsIj48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjxnIGNsYXNzPSJub2RlcyI+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IGZsb3djaGFydC1sYWJlbCIgaWQ9ImZsb3djaGFydC1taWNyb2h0dHAtMCIgZGF0YS1ub2RlPSJ0cnVlIiBkYXRhLWlkPSJtaWNyb2h0dHAiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEzMi44NTkzNzUsIDE3KSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjAiIHJ5PSIwIiB4PSItNjIuMDA3ODEyNSIgeT0iLTE3IiB3aWR0aD0iMTI0LjAxNTYyNSIgaGVpZ2h0PSIzNCIvPjxnIGNsYXNzPSJsYWJlbCIgc3R5bGU9IiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTU0LjUwNzgxMjUsIC05LjUpIj48cmVjdC8+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjEwOS4wMTU2MjUiIGhlaWdodD0iMTkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj5vcmcubWljcm9odHRwPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZ3JlZW4gZmxvd2NoYXJ0LWxhYmVsIiBpZD0iZmxvd2NoYXJ0LW1pY3JvaHR0cHNldGNvb2tpZS0xIiBkYXRhLW5vZGU9InRydWUiIGRhdGEtaWQ9Im1pY3JvaHR0cHNldGNvb2tpZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTMyLjg1OTM3NSwgMTAxKSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjAiIHJ5PSIwIiB4PSItMTMyLjg1OTM3NSIgeT0iLTE3IiB3aWR0aD0iMjY1LjcxODc1IiBoZWlnaHQ9IjM0Ii8+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTI1LjM1OTM3NSwgLTkuNSkiPjxyZWN0Lz48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMjUwLjcxODc1IiBoZWlnaHQ9IjE5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+ZGV2Lm1jY3VlLm1pY3JvaHR0cC5zZXRjb29raWU8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjwvZz48L2c+PC9zdmc+" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>dev.mccue.microhttp.setcookie</code> provides a utility for generating a <code>Set-Cookie</code> header for use in a microhttp <code>Response</code>.</p>
<h2 id="why-use-it">Why use it</h2>
<p>Whenever a web browser receives a response from a website, depending on user settings, it will look for any <code>SetCookie</code> headers in that response. Data conveyed in those headers will be sent back to the server with every subsequent request.</p>
<p>This is one of the easiest ways to have persistent state, like user sessions, on a website.</p>
<h2 id="getting-started">Getting Started</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">Header</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">setcookie</span><span class="op">.</span><span class="im">SameSite</span><span class="op">;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">setcookie</span><span class="op">.</span><span class="im">SetCookieHeader</span><span class="op">;</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    Header header <span class="op">=</span> SetCookieHeader<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;name&quot;</span><span class="op">,</span> <span class="st">&quot;value&quot;</span><span class="op">);</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Header[name=Set-Cookie, value=name=value]</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>header<span class="op">);</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>    Header otherHeader <span class="op">=</span> SetCookieHeader<span class="op">.</span><span class="fu">builder</span><span class="op">(</span><span class="st">&quot;name2&quot;</span><span class="op">,</span> <span class="st">&quot;value2&quot;</span><span class="op">)</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">sameSite</span><span class="op">(</span>SameSite<span class="op">.</span><span class="fu">STRICT</span><span class="op">)</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">secure</span><span class="op">(</span><span class="kw">true</span><span class="op">)</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">build</span><span class="op">();</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Header[name=Set-Cookie, value=name2=value2; SameSite=Strict; Secure]</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>otherHeader<span class="op">);</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>com.sanctionco.jmail</title><link>https://mccue.dev/pages/12-12-23-java-library-of-the-day-12</link><description></description><pubDate>Tue, 12 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>com.sanctionco.jmail</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">com.sanctionco.jmail</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/com.sanctionco.jmail/jmail"><code>com.sanctionco.jmail/jmail</code></a></li>
<li>Module Name: <code>com.sanctionco.jmail</code></li>
<li>GitHub: <a href="https://github.com/RohanNagar/jmail"><code>RohanNagar/jmail</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogMjAwLjEwOXB4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii04IC04IDIwMC4xMDkzNzUgMTM0IiByb2xlPSJncmFwaGljcy1kb2N1bWVudCBkb2N1bWVudCIgYXJpYS1yb2xlZGVzY3JpcHRpb249ImZsb3djaGFydC12MiI+PHN0eWxlPiNteS1zdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O2ZpbGw6IzMzMzt9I215LXN2ZyAuZXJyb3ItaWNvbntmaWxsOiM1NTIyMjI7fSNteS1zdmcgLmVycm9yLXRleHR7ZmlsbDojNTUyMjIyO3N0cm9rZTojNTUyMjIyO30jbXktc3ZnIC5lZGdlLXRoaWNrbmVzcy1ub3JtYWx7c3Ryb2tlLXdpZHRoOjJweDt9I215LXN2ZyAuZWRnZS10aGlja25lc3MtdGhpY2t7c3Ryb2tlLXdpZHRoOjMuNXB4O30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tc29saWR7c3Ryb2tlLWRhc2hhcnJheTowO30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tZGFzaGVke3N0cm9rZS1kYXNoYXJyYXk6Mzt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLWRvdHRlZHtzdHJva2UtZGFzaGFycmF5OjI7fSNteS1zdmcgLm1hcmtlcntmaWxsOiMzMzMzMzM7c3Ryb2tlOiMzMzMzMzM7fSNteS1zdmcgLm1hcmtlci5jcm9zc3tzdHJva2U6IzMzMzMzMzt9I215LXN2ZyBzdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O30jbXktc3ZnIC5sYWJlbHtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Y29sb3I6IzMzMzt9I215LXN2ZyAuY2x1c3Rlci1sYWJlbCB0ZXh0e2ZpbGw6IzMzMzt9I215LXN2ZyAuY2x1c3Rlci1sYWJlbCBzcGFuLCNteS1zdmcgcHtjb2xvcjojMzMzO30jbXktc3ZnIC5sYWJlbCB0ZXh0LCNteS1zdmcgc3BhbiwjbXktc3ZnIHB7ZmlsbDojMzMzO2NvbG9yOiMzMzM7fSNteS1zdmcgLm5vZGUgcmVjdCwjbXktc3ZnIC5ub2RlIGNpcmNsZSwjbXktc3ZnIC5ub2RlIGVsbGlwc2UsI215LXN2ZyAubm9kZSBwb2x5Z29uLCNteS1zdmcgLm5vZGUgcGF0aHtmaWxsOiNFQ0VDRkY7c3Ryb2tlOiM5MzcwREI7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAuZmxvd2NoYXJ0LWxhYmVsIHRleHR7dGV4dC1hbmNob3I6bWlkZGxlO30jbXktc3ZnIC5ub2RlIC5rYXRleCBwYXRoe2ZpbGw6IzAwMDtzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5ub2RlIC5sYWJlbHt0ZXh0LWFsaWduOmNlbnRlcjt9I215LXN2ZyAubm9kZS5jbGlja2FibGV7Y3Vyc29yOnBvaW50ZXI7fSNteS1zdmcgLmFycm93aGVhZFBhdGh7ZmlsbDojMzMzMzMzO30jbXktc3ZnIC5lZGdlUGF0aCAucGF0aHtzdHJva2U6IzMzMzMzMztzdHJva2Utd2lkdGg6Mi4wcHg7fSNteS1zdmcgLmZsb3djaGFydC1saW5re3N0cm9rZTojMzMzMzMzO2ZpbGw6bm9uZTt9I215LXN2ZyAuZWRnZUxhYmVse2JhY2tncm91bmQtY29sb3I6I2U4ZThlODt0ZXh0LWFsaWduOmNlbnRlcjt9I215LXN2ZyAuZWRnZUxhYmVsIHJlY3R7b3BhY2l0eTowLjU7YmFja2dyb3VuZC1jb2xvcjojZThlOGU4O2ZpbGw6I2U4ZThlODt9I215LXN2ZyAubGFiZWxCa2d7YmFja2dyb3VuZC1jb2xvcjpyZ2JhKDIzMiwgMjMyLCAyMzIsIDAuNSk7fSNteS1zdmcgLmNsdXN0ZXIgcmVjdHtmaWxsOiNmZmZmZGU7c3Ryb2tlOiNhYWFhMzM7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAuY2x1c3RlciB0ZXh0e2ZpbGw6IzMzMzt9I215LXN2ZyAuY2x1c3RlciBzcGFuLCNteS1zdmcgcHtjb2xvcjojMzMzO30jbXktc3ZnIGRpdi5tZXJtYWlkVG9vbHRpcHtwb3NpdGlvbjphYnNvbHV0ZTt0ZXh0LWFsaWduOmNlbnRlcjttYXgtd2lkdGg6MjAwcHg7cGFkZGluZzoycHg7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxMnB4O2JhY2tncm91bmQ6aHNsKDgwLCAxMDAlLCA5Ni4yNzQ1MDk4MDM5JSk7Ym9yZGVyOjFweCBzb2xpZCAjYWFhYTMzO2JvcmRlci1yYWRpdXM6MnB4O3BvaW50ZXItZXZlbnRzOm5vbmU7ei1pbmRleDoxMDA7fSNteS1zdmcgLmZsb3djaGFydFRpdGxlVGV4dHt0ZXh0LWFuY2hvcjptaWRkbGU7Zm9udC1zaXplOjE4cHg7ZmlsbDojMzMzO30jbXktc3ZnIDpyb290ey0tbWVybWFpZC1mb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7fSNteS1zdmcgLmdyZWVuJmd0Oyp7c3Ryb2tlOnJnYigyNTUsIDAsIDApIWltcG9ydGFudDt9I215LXN2ZyAuZ3JlZW4gc3BhbntzdHJva2U6cmdiKDI1NSwgMCwgMCkhaW1wb3J0YW50O308L3N0eWxlPjxnPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtcG9pbnRFbmQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjYiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjEyIiBtYXJrZXJIZWlnaHQ9IjEyIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMCAwIEwgMTAgNSBMIDAgMTAgeiIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LXBvaW50U3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjQuNSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTIiIG1hcmtlckhlaWdodD0iMTIiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAwIDUgTCAxMCAxMCBMIDEwIDAgeiIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNpcmNsZUVuZCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iMTEiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxjaXJjbGUgY3g9IjUiIGN5PSI1IiByPSI1IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY2lyY2xlU3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9Ii0xIiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48Y2lyY2xlIGN4PSI1IiBjeT0iNSIgcj0iNSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNyb3NzRW5kIiBjbGFzcz0ibWFya2VyIGNyb3NzIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDExIDExIiByZWZYPSIxMiIgcmVmWT0iNS4yIiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDEsMSBsIDksOSBNIDEwLDEgbCAtOSw5IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAyOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY3Jvc3NTdGFydCIgY2xhc3M9Im1hcmtlciBjcm9zcyBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMSAxMSIgcmVmWD0iLTEiIHJlZlk9IjUuMiIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAxLDEgbCA5LDkgTSAxMCwxIGwgLTksOSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMjsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48ZyBjbGFzcz0icm9vdCI+PGcgY2xhc3M9ImNsdXN0ZXJzIi8+PGcgY2xhc3M9ImVkZ2VQYXRocyI+PHBhdGggZD0iTTkyLjA1NSwzNEw5Mi4wNTUsMzguMTY3QzkyLjA1NSw0Mi4zMzMsOTIuMDU1LDUwLjY2Nyw5Mi4wNTUsNTguMTE3QzkyLjA1NSw2NS41NjcsOTIuMDU1LDcyLjEzMyw5Mi4wNTUsNzUuNDE3TDkyLjA1NSw3OC43IiBpZD0iTC1qYXZhbmFtaW5nLWptYWlsLTAiIGNsYXNzPSJlZGdlLXRoaWNrbmVzcy1ub3JtYWwgZWRnZS1wYXR0ZXJuLXNvbGlkIGZsb3djaGFydC1saW5rIExTLWphdmFuYW1pbmcgTEUtam1haWwiIHN0eWxlPSJmaWxsOm5vbmU7IiBtYXJrZXItZW5kPSJ1cmwoI215LXN2Z19mbG93Y2hhcnQtcG9pbnRFbmQpIi8+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWxzIj48ZyBjbGFzcz0iZWRnZUxhYmVsIj48ZyBjbGFzcz0ibGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsIDApIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMCIgaGVpZ2h0PSIwIj48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9ImVkZ2VMYWJlbCI+PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjwvZz48ZyBjbGFzcz0ibm9kZXMiPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZGVmYXVsdCBmbG93Y2hhcnQtbGFiZWwiIGlkPSJmbG93Y2hhcnQtamF2YW5hbWluZy0wIiBkYXRhLW5vZGU9InRydWUiIGRhdGEtaWQ9ImphdmFuYW1pbmciIHRyYW5zZm9ybT0idHJhbnNsYXRlKDkyLjA1NDY4NzUsIDE3KSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjAiIHJ5PSIwIiB4PSItNTYuOTQ1MzEyNSIgeT0iLTE3IiB3aWR0aD0iMTEzLjg5MDYyNSIgaGVpZ2h0PSIzNCIvPjxnIGNsYXNzPSJsYWJlbCIgc3R5bGU9IiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTQ5LjQ0NTMxMjUsIC05LjUpIj48cmVjdC8+PGZvcmVpZ25PYmplY3Qgd2lkdGg9Ijk4Ljg5MDYyNSIgaGVpZ2h0PSIxOSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPmphdmEubmFtaW5nPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZ3JlZW4gZmxvd2NoYXJ0LWxhYmVsIiBpZD0iZmxvd2NoYXJ0LWptYWlsLTEiIGRhdGEtbm9kZT0idHJ1ZSIgZGF0YS1pZD0iam1haWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDkyLjA1NDY4NzUsIDEwMSkiPjxyZWN0IGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiIHN0eWxlPSIiIHJ4PSIwIiByeT0iMCIgeD0iLTkyLjA1NDY4NzUiIHk9Ii0xNyIgd2lkdGg9IjE4NC4xMDkzNzUiIGhlaWdodD0iMzQiLz48ZyBjbGFzcz0ibGFiZWwiIHN0eWxlPSIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC04NC41NTQ2ODc1LCAtOS41KSI+PHJlY3QvPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIxNjkuMTA5Mzc1IiBoZWlnaHQ9IjE5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+Y29tLnNhbmN0aW9uY28uam1haWw8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjwvZz48L2c+PC9zdmc+" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>com.sanctionco.jmail</code> parses and validates email addresses.</p>
<h2 id="why-use-it">Why use it</h2>
<p>Web applications often need to work with email addresses in some form.</p>
<p>If you find yourself needing to check if something is a valid email address, <a href="https://www.rohannagar.com/jmail/"><code>jmail</code> is more correct than the alternatives and generally around twice as fast.</a>.</p>
<p>If you find yourself wanting to represent an email address in your domain, the <code>Email</code> type provided by this library will serve you well. You'd want to use that over a <code>String</code> for the same reason you'd want to store a path in a <code>Path</code> or an address in a <code>URI</code>.</p>
<h2 id="getting-started">Getting Started</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">sanctionco</span><span class="op">.</span><span class="im">jmail</span><span class="op">.</span><span class="im">Email</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">sanctionco</span><span class="op">.</span><span class="im">jmail</span><span class="op">.</span><span class="im">JMail</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">// false</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>JMail<span class="op">.</span><span class="fu">isValid</span><span class="op">(</span><span class="st">&quot;gibberish&quot;</span><span class="op">));</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    <span class="co">// true</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>JMail<span class="op">.</span><span class="fu">isValid</span><span class="op">(</span><span class="st">&quot;apple@example.com&quot;</span><span class="op">));</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>    Email email <span class="op">=</span> Email<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;apple@example.com&quot;</span><span class="op">)</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">orElseThrow</span><span class="op">();</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">User</span><span class="op">(</span>Email email<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>    User user <span class="op">=</span> <span class="kw">new</span> <span class="fu">User</span><span class="op">(</span>email<span class="op">);</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>    <span class="co">// User[email=apple@example.com]</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>user<span class="op">);</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>    <span class="co">// example.com</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>user<span class="op">.</span><span class="fu">email</span><span class="op">().</span><span class="fu">domain</span><span class="op">());</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>org.apiguardian.api</title><link>https://mccue.dev/pages/12-11-23-java-library-of-the-day-11</link><description></description><pubDate>Mon, 11 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>org.apiguardian.api</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">org.apiguardian.api</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/org.apiguardian/apiguardian-api"><code>org.apiguardian/apiguardian-api</code></a></li>
<li>Module Name: <code>org.apiguardian.api</code></li>
<li>GitHub: <a href="https://github.com/apiguardian-team/apiguardian"><code>apiguardian-team/apiguardian</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogMTg3LjE3MnB4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii04IC04IDE4Ny4xNzE4NzUgNTAiIHJvbGU9ImdyYXBoaWNzLWRvY3VtZW50IGRvY3VtZW50IiBhcmlhLXJvbGVkZXNjcmlwdGlvbj0iZmxvd2NoYXJ0LXYyIj48c3R5bGU+I215LXN2Z3tmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjE2cHg7ZmlsbDojMzMzO30jbXktc3ZnIC5lcnJvci1pY29ue2ZpbGw6IzU1MjIyMjt9I215LXN2ZyAuZXJyb3ItdGV4dHtmaWxsOiM1NTIyMjI7c3Ryb2tlOiM1NTIyMjI7fSNteS1zdmcgLmVkZ2UtdGhpY2tuZXNzLW5vcm1hbHtzdHJva2Utd2lkdGg6MnB4O30jbXktc3ZnIC5lZGdlLXRoaWNrbmVzcy10aGlja3tzdHJva2Utd2lkdGg6My41cHg7fSNteS1zdmcgLmVkZ2UtcGF0dGVybi1zb2xpZHtzdHJva2UtZGFzaGFycmF5OjA7fSNteS1zdmcgLmVkZ2UtcGF0dGVybi1kYXNoZWR7c3Ryb2tlLWRhc2hhcnJheTozO30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tZG90dGVke3N0cm9rZS1kYXNoYXJyYXk6Mjt9I215LXN2ZyAubWFya2Vye2ZpbGw6IzMzMzMzMztzdHJva2U6IzMzMzMzMzt9I215LXN2ZyAubWFya2VyLmNyb3Nze3N0cm9rZTojMzMzMzMzO30jbXktc3ZnIHN2Z3tmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjE2cHg7fSNteS1zdmcgLmxhYmVse2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtjb2xvcjojMzMzO30jbXktc3ZnIC5jbHVzdGVyLWxhYmVsIHRleHR7ZmlsbDojMzMzO30jbXktc3ZnIC5jbHVzdGVyLWxhYmVsIHNwYW4sI215LXN2ZyBwe2NvbG9yOiMzMzM7fSNteS1zdmcgLmxhYmVsIHRleHQsI215LXN2ZyBzcGFuLCNteS1zdmcgcHtmaWxsOiMzMzM7Y29sb3I6IzMzMzt9I215LXN2ZyAubm9kZSByZWN0LCNteS1zdmcgLm5vZGUgY2lyY2xlLCNteS1zdmcgLm5vZGUgZWxsaXBzZSwjbXktc3ZnIC5ub2RlIHBvbHlnb24sI215LXN2ZyAubm9kZSBwYXRoe2ZpbGw6I0VDRUNGRjtzdHJva2U6IzkzNzBEQjtzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5mbG93Y2hhcnQtbGFiZWwgdGV4dHt0ZXh0LWFuY2hvcjptaWRkbGU7fSNteS1zdmcgLm5vZGUgLmthdGV4IHBhdGh7ZmlsbDojMDAwO3N0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxcHg7fSNteS1zdmcgLm5vZGUgLmxhYmVse3RleHQtYWxpZ246Y2VudGVyO30jbXktc3ZnIC5ub2RlLmNsaWNrYWJsZXtjdXJzb3I6cG9pbnRlcjt9I215LXN2ZyAuYXJyb3doZWFkUGF0aHtmaWxsOiMzMzMzMzM7fSNteS1zdmcgLmVkZ2VQYXRoIC5wYXRoe3N0cm9rZTojMzMzMzMzO3N0cm9rZS13aWR0aDoyLjBweDt9I215LXN2ZyAuZmxvd2NoYXJ0LWxpbmt7c3Ryb2tlOiMzMzMzMzM7ZmlsbDpub25lO30jbXktc3ZnIC5lZGdlTGFiZWx7YmFja2dyb3VuZC1jb2xvcjojZThlOGU4O3RleHQtYWxpZ246Y2VudGVyO30jbXktc3ZnIC5lZGdlTGFiZWwgcmVjdHtvcGFjaXR5OjAuNTtiYWNrZ3JvdW5kLWNvbG9yOiNlOGU4ZTg7ZmlsbDojZThlOGU4O30jbXktc3ZnIC5sYWJlbEJrZ3tiYWNrZ3JvdW5kLWNvbG9yOnJnYmEoMjMyLCAyMzIsIDIzMiwgMC41KTt9I215LXN2ZyAuY2x1c3RlciByZWN0e2ZpbGw6I2ZmZmZkZTtzdHJva2U6I2FhYWEzMztzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5jbHVzdGVyIHRleHR7ZmlsbDojMzMzO30jbXktc3ZnIC5jbHVzdGVyIHNwYW4sI215LXN2ZyBwe2NvbG9yOiMzMzM7fSNteS1zdmcgZGl2Lm1lcm1haWRUb29sdGlwe3Bvc2l0aW9uOmFic29sdXRlO3RleHQtYWxpZ246Y2VudGVyO21heC13aWR0aDoyMDBweDtwYWRkaW5nOjJweDtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjEycHg7YmFja2dyb3VuZDpoc2woODAsIDEwMCUsIDk2LjI3NDUwOTgwMzklKTtib3JkZXI6MXB4IHNvbGlkICNhYWFhMzM7Ym9yZGVyLXJhZGl1czoycHg7cG9pbnRlci1ldmVudHM6bm9uZTt6LWluZGV4OjEwMDt9I215LXN2ZyAuZmxvd2NoYXJ0VGl0bGVUZXh0e3RleHQtYW5jaG9yOm1pZGRsZTtmb250LXNpemU6MThweDtmaWxsOiMzMzM7fSNteS1zdmcgOnJvb3R7LS1tZXJtYWlkLWZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjt9I215LXN2ZyAuZ3JlZW4mZ3Q7KntzdHJva2U6cmdiKDI1NSwgMCwgMCkhaW1wb3J0YW50O30jbXktc3ZnIC5ncmVlbiBzcGFue3N0cm9rZTpyZ2IoMjU1LCAwLCAwKSFpbXBvcnRhbnQ7fTwvc3R5bGU+PGc+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1wb2ludEVuZCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iNiIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTIiIG1hcmtlckhlaWdodD0iMTIiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAwIDAgTCAxMCA1IEwgMCAxMCB6IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtcG9pbnRTdGFydCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iNC41IiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMiIgbWFya2VySGVpZ2h0PSIxMiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDAgNSBMIDEwIDEwIEwgMTAgMCB6IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY2lyY2xlRW5kIiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSIxMSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PGNpcmNsZSBjeD0iNSIgY3k9IjUiIHI9IjUiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jaXJjbGVTdGFydCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iLTEiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxjaXJjbGUgY3g9IjUiIGN5PSI1IiByPSI1IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY3Jvc3NFbmQiIGNsYXNzPSJtYXJrZXIgY3Jvc3MgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTEgMTEiIHJlZlg9IjEyIiByZWZZPSI1LjIiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMSwxIGwgOSw5IE0gMTAsMSBsIC05LDkiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDI7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jcm9zc1N0YXJ0IiBjbGFzcz0ibWFya2VyIGNyb3NzIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDExIDExIiByZWZYPSItMSIgcmVmWT0iNS4yIiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDEsMSBsIDksOSBNIDEwLDEgbCAtOSw5IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAyOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxnIGNsYXNzPSJyb290Ij48ZyBjbGFzcz0iY2x1c3RlcnMiLz48ZyBjbGFzcz0iZWRnZVBhdGhzIi8+PGcgY2xhc3M9ImVkZ2VMYWJlbHMiLz48ZyBjbGFzcz0ibm9kZXMiPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZ3JlZW4gZmxvd2NoYXJ0LWxhYmVsIiBpZD0iZmxvd2NoYXJ0LWFwaWd1YXJkaWFuLTAiIGRhdGEtbm9kZT0idHJ1ZSIgZGF0YS1pZD0iYXBpZ3VhcmRpYW4iIHRyYW5zZm9ybT0idHJhbnNsYXRlKDg1LjU4NTkzNzUsIDE3KSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjAiIHJ5PSIwIiB4PSItODUuNTg1OTM3NSIgeT0iLTE3IiB3aWR0aD0iMTcxLjE3MTg3NSIgaGVpZ2h0PSIzNCIvPjxnIGNsYXNzPSJsYWJlbCIgc3R5bGU9IiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTc4LjA4NTkzNzUsIC05LjUpIj48cmVjdC8+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjE1Ni4xNzE4NzUiIGhlaWdodD0iMTkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj5vcmcuYXBpZ3VhcmRpYW4uYXBpPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjwvZz48L2c+PC9nPjwvc3ZnPg==" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>org.apiguardian.api</code> provides an <code>@API</code> annotation. This gives a structured place to document API stability guarantees.</p>
<h2 id="why-use-it">Why use it</h2>
<p>If you are writing an application, generally no API is truly stable. You are free to change whatever you need to in order to make the software work.</p>
<p>Libraries are different. Libraries are used by people whose code you have no control over, but with whom you form an implicit social contract where they trust you to not break their code with new library releases.</p>
<p>Explicitly documenting which elements of an API you are committed to maintaining, which you are experimenting with, and which they really shouldn't be touching is therefore a useful thing to do.</p>
<p>Annotations will show up prominently in generated documentation, which makes them a good mechanism for documenting these guarantees (or lack there-of).</p>
<h2 id="getting-started">Getting Started</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">apiguardian</span><span class="op">.</span><span class="im">api</span><span class="op">.</span><span class="im">API</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> MathOps <span class="op">{</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">MathOps</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    <span class="at">@API</span><span class="op">(</span>status <span class="op">=</span> API<span class="op">.</span><span class="fu">Status</span><span class="op">.</span><span class="fu">STABLE</span><span class="op">)</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">double</span> <span class="fu">pi</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fl">3.14</span><span class="op">;</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>    <span class="at">@API</span><span class="op">(</span>status <span class="op">=</span> API<span class="op">.</span><span class="fu">Status</span><span class="op">.</span><span class="fu">EXPERIMENTAL</span><span class="op">)</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">double</span> <span class="fu">tau</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fu">pi</span><span class="op">()</span> <span class="op">*</span> <span class="dv">2</span><span class="op">;</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>dev.mccue.microhttp-html</title><link>https://mccue.dev/pages/12-10-23-java-library-of-the-day-10</link><description></description><pubDate>Sun, 10 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>dev.mccue.microhttp-html</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">dev.mccue.microhttp-html</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/dev.mccue/microhttp-html"><code>dev.mccue/microhttp-html</code></a></li>
<li>Module Name: <code>dev.mccue.microhttp-html</code></li>
<li>GitHub: <a href="https://github.com/bowbahdoe/microhttp-html"><code>bowbahdoe/microhttp-html</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogNzYwLjAzMXB4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii0yNi4xMDQ5OTk1NDIyMzYzMjggLTggNzYwLjAzMDc2MTcxODc1IDIxOCIgcm9sZT0iZ3JhcGhpY3MtZG9jdW1lbnQgZG9jdW1lbnQiIGFyaWEtcm9sZWRlc2NyaXB0aW9uPSJmbG93Y2hhcnQtdjIiPjxzdHlsZT4jbXktc3Zne2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtmb250LXNpemU6MTZweDtmaWxsOiMzMzM7fSNteS1zdmcgLmVycm9yLWljb257ZmlsbDojNTUyMjIyO30jbXktc3ZnIC5lcnJvci10ZXh0e2ZpbGw6IzU1MjIyMjtzdHJva2U6IzU1MjIyMjt9I215LXN2ZyAuZWRnZS10aGlja25lc3Mtbm9ybWFse3N0cm9rZS13aWR0aDoycHg7fSNteS1zdmcgLmVkZ2UtdGhpY2tuZXNzLXRoaWNre3N0cm9rZS13aWR0aDozLjVweDt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLXNvbGlke3N0cm9rZS1kYXNoYXJyYXk6MDt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLWRhc2hlZHtzdHJva2UtZGFzaGFycmF5OjM7fSNteS1zdmcgLmVkZ2UtcGF0dGVybi1kb3R0ZWR7c3Ryb2tlLWRhc2hhcnJheToyO30jbXktc3ZnIC5tYXJrZXJ7ZmlsbDojMzMzMzMzO3N0cm9rZTojMzMzMzMzO30jbXktc3ZnIC5tYXJrZXIuY3Jvc3N7c3Ryb2tlOiMzMzMzMzM7fSNteS1zdmcgc3Zne2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtmb250LXNpemU6MTZweDt9I215LXN2ZyAubGFiZWx7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2NvbG9yOiMzMzM7fSNteS1zdmcgLmNsdXN0ZXItbGFiZWwgdGV4dHtmaWxsOiMzMzM7fSNteS1zdmcgLmNsdXN0ZXItbGFiZWwgc3BhbiwjbXktc3ZnIHB7Y29sb3I6IzMzMzt9I215LXN2ZyAubGFiZWwgdGV4dCwjbXktc3ZnIHNwYW4sI215LXN2ZyBwe2ZpbGw6IzMzMztjb2xvcjojMzMzO30jbXktc3ZnIC5ub2RlIHJlY3QsI215LXN2ZyAubm9kZSBjaXJjbGUsI215LXN2ZyAubm9kZSBlbGxpcHNlLCNteS1zdmcgLm5vZGUgcG9seWdvbiwjbXktc3ZnIC5ub2RlIHBhdGh7ZmlsbDojRUNFQ0ZGO3N0cm9rZTojOTM3MERCO3N0cm9rZS13aWR0aDoxcHg7fSNteS1zdmcgLmZsb3djaGFydC1sYWJlbCB0ZXh0e3RleHQtYW5jaG9yOm1pZGRsZTt9I215LXN2ZyAubm9kZSAua2F0ZXggcGF0aHtmaWxsOiMwMDA7c3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAubm9kZSAubGFiZWx7dGV4dC1hbGlnbjpjZW50ZXI7fSNteS1zdmcgLm5vZGUuY2xpY2thYmxle2N1cnNvcjpwb2ludGVyO30jbXktc3ZnIC5hcnJvd2hlYWRQYXRoe2ZpbGw6IzMzMzMzMzt9I215LXN2ZyAuZWRnZVBhdGggLnBhdGh7c3Ryb2tlOiMzMzMzMzM7c3Ryb2tlLXdpZHRoOjIuMHB4O30jbXktc3ZnIC5mbG93Y2hhcnQtbGlua3tzdHJva2U6IzMzMzMzMztmaWxsOm5vbmU7fSNteS1zdmcgLmVkZ2VMYWJlbHtiYWNrZ3JvdW5kLWNvbG9yOiNlOGU4ZTg7dGV4dC1hbGlnbjpjZW50ZXI7fSNteS1zdmcgLmVkZ2VMYWJlbCByZWN0e29wYWNpdHk6MC41O2JhY2tncm91bmQtY29sb3I6I2U4ZThlODtmaWxsOiNlOGU4ZTg7fSNteS1zdmcgLmxhYmVsQmtne2JhY2tncm91bmQtY29sb3I6cmdiYSgyMzIsIDIzMiwgMjMyLCAwLjUpO30jbXktc3ZnIC5jbHVzdGVyIHJlY3R7ZmlsbDojZmZmZmRlO3N0cm9rZTojYWFhYTMzO3N0cm9rZS13aWR0aDoxcHg7fSNteS1zdmcgLmNsdXN0ZXIgdGV4dHtmaWxsOiMzMzM7fSNteS1zdmcgLmNsdXN0ZXIgc3BhbiwjbXktc3ZnIHB7Y29sb3I6IzMzMzt9I215LXN2ZyBkaXYubWVybWFpZFRvb2x0aXB7cG9zaXRpb246YWJzb2x1dGU7dGV4dC1hbGlnbjpjZW50ZXI7bWF4LXdpZHRoOjIwMHB4O3BhZGRpbmc6MnB4O2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtmb250LXNpemU6MTJweDtiYWNrZ3JvdW5kOmhzbCg4MCwgMTAwJSwgOTYuMjc0NTA5ODAzOSUpO2JvcmRlcjoxcHggc29saWQgI2FhYWEzMztib3JkZXItcmFkaXVzOjJweDtwb2ludGVyLWV2ZW50czpub25lO3otaW5kZXg6MTAwO30jbXktc3ZnIC5mbG93Y2hhcnRUaXRsZVRleHR7dGV4dC1hbmNob3I6bWlkZGxlO2ZvbnQtc2l6ZToxOHB4O2ZpbGw6IzMzMzt9I215LXN2ZyA6cm9vdHstLW1lcm1haWQtZm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO30jbXktc3ZnIC5ncmVlbiZndDsqe3N0cm9rZTpyZ2IoMjU1LCAwLCAwKSFpbXBvcnRhbnQ7fSNteS1zdmcgLmdyZWVuIHNwYW57c3Ryb2tlOnJnYigyNTUsIDAsIDApIWltcG9ydGFudDt9PC9zdHlsZT48Zz48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LXBvaW50RW5kIiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI2IiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMiIgbWFya2VySGVpZ2h0PSIxMiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDAgMCBMIDEwIDUgTCAwIDEwIHoiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1wb2ludFN0YXJ0IiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI0LjUiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjEyIiBtYXJrZXJIZWlnaHQ9IjEyIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMCA1IEwgMTAgMTAgTCAxMCAwIHoiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jaXJjbGVFbmQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjExIiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48Y2lyY2xlIGN4PSI1IiBjeT0iNSIgcj0iNSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNpcmNsZVN0YXJ0IiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSItMSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PGNpcmNsZSBjeD0iNSIgY3k9IjUiIHI9IjUiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jcm9zc0VuZCIgY2xhc3M9Im1hcmtlciBjcm9zcyBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMSAxMSIgcmVmWD0iMTIiIHJlZlk9IjUuMiIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAxLDEgbCA5LDkgTSAxMCwxIGwgLTksOSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMjsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNyb3NzU3RhcnQiIGNsYXNzPSJtYXJrZXIgY3Jvc3MgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTEgMTEiIHJlZlg9Ii0xIiByZWZZPSI1LjIiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMSwxIGwgOSw5IE0gMTAsMSBsIC05LDkiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDI7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PGcgY2xhc3M9InJvb3QiPjxnIGNsYXNzPSJjbHVzdGVycyIvPjxnIGNsYXNzPSJlZGdlUGF0aHMiPjxwYXRoIGQ9Ik05NC40MzUsMzRMMTAyLjM4MiwzOC4xNjdDMTEwLjMzLDQyLjMzMywxMjYuMjI2LDUwLjY2NywxMzQuMTczLDU4LjExN0MxNDIuMTIxLDY1LjU2NywxNDIuMTIxLDcyLjEzMywxNDIuMTIxLDc1LjQxN0wxNDIuMTIxLDc4LjciIGlkPSJMLW1pY3JvaHR0cC1taWNyb2h0dHAtaGFuZGxlci0wIiBjbGFzcz0iZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1taWNyb2h0dHAgTEUtbWljcm9odHRwLWhhbmRsZXIiIHN0eWxlPSJmaWxsOm5vbmU7IiBtYXJrZXItZW5kPSJ1cmwoI215LXN2Z19mbG93Y2hhcnQtcG9pbnRFbmQpIi8+PHBhdGggZD0iTTI5LjU4MSwzNEwyMS42MzMsMzguMTY3QzEzLjY4Niw0Mi4zMzMsLTIuMjEsNTAuNjY3LC0xMC4xNTgsNjEuODMzQy0xOC4xMDUsNzMsLTE4LjEwNSw4NywtMTguMTA1LDEwMUMtMTguMTA1LDExNSwtMTguMTA1LDEyOSwxMi40OTMsMTQwLjI1OUM0My4wOTEsMTUxLjUxOCwxMDQuMjg4LDE2MC4wMzcsMTM0Ljg4NywxNjQuMjk2TDE2NS40ODUsMTY4LjU1NSIgaWQ9IkwtbWljcm9odHRwLW1pY3JvaHR0cC1odG1sLTAiIGNsYXNzPSJlZGdlLXRoaWNrbmVzcy1ub3JtYWwgZWRnZS1wYXR0ZXJuLXNvbGlkIGZsb3djaGFydC1saW5rIExTLW1pY3JvaHR0cCBMRS1taWNyb2h0dHAtaHRtbCIgc3R5bGU9ImZpbGw6bm9uZTsiIG1hcmtlci1lbmQ9InVybCgjbXktc3ZnX2Zsb3djaGFydC1wb2ludEVuZCkiLz48cGF0aCBkPSJNMTQyLjEyMSwxMThMMTQyLjEyMSwxMjIuMTY3QzE0Mi4xMjEsMTI2LjMzMywxNDIuMTIxLDEzNC42NjcsMTU1LjMxMiwxNDIuNzQ5QzE2OC41MDQsMTUwLjgzMSwxOTQuODg2LDE1OC42NjEsMjA4LjA3NywxNjIuNTc3TDIyMS4yNjksMTY2LjQ5MiIgaWQ9IkwtbWljcm9odHRwLWhhbmRsZXItbWljcm9odHRwLWh0bWwtMCIgY2xhc3M9ImVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtbWljcm9odHRwLWhhbmRsZXIgTEUtbWljcm9odHRwLWh0bWwiIHN0eWxlPSJmaWxsOm5vbmU7IiBtYXJrZXItZW5kPSJ1cmwoI215LXN2Z19mbG93Y2hhcnQtcG9pbnRFbmQpIi8+PHBhdGggZD0iTTQyNS4xMjksMTE4TDQyNS4xMjksMTIyLjE2N0M0MjUuMTI5LDEyNi4zMzMsNDI1LjEyOSwxMzQuNjY3LDQxMS45MzgsMTQyLjc0OUMzOTguNzQ2LDE1MC44MzEsMzcyLjM2NCwxNTguNjYxLDM1OS4xNzMsMTYyLjU3N0wzNDUuOTgxLDE2Ni40OTIiIGlkPSJMLXJlYXNvbnBocmFzZS1taWNyb2h0dHAtaHRtbC0wIiBjbGFzcz0iZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1yZWFzb25waHJhc2UgTEUtbWljcm9odHRwLWh0bWwiIHN0eWxlPSJmaWxsOm5vbmU7IiBtYXJrZXItZW5kPSJ1cmwoI215LXN2Z19mbG93Y2hhcnQtcG9pbnRFbmQpIi8+PHBhdGggZD0iTTY1NC40MTgsMTE4TDY1NC40MTgsMTIyLjE2N0M2NTQuNDE4LDEyNi4zMzMsNjU0LjQxOCwxMzQuNjY3LDYxMi4zMTIsMTQzLjYwM0M1NzAuMjA2LDE1Mi41MzksNDg1Ljk5NCwxNjIuMDc4LDQ0My44ODgsMTY2Ljg0N0w0MDEuNzgyLDE3MS42MTYiIGlkPSJMLWh0bWwtbWljcm9odHRwLWh0bWwtMCIgY2xhc3M9ImVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtaHRtbCBMRS1taWNyb2h0dHAtaHRtbCIgc3R5bGU9ImZpbGw6bm9uZTsiIG1hcmtlci1lbmQ9InVybCgjbXktc3ZnX2Zsb3djaGFydC1wb2ludEVuZCkiLz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbHMiPjxnIGNsYXNzPSJlZGdlTGFiZWwiPjxnIGNsYXNzPSJsYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMCkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIwIiBoZWlnaHQ9IjAiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0iZWRnZUxhYmVsIj48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbCI+PGcgY2xhc3M9ImxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAwKSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjAiIGhlaWdodD0iMCI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0iZWRnZUxhYmVsIj48ZyBjbGFzcz0ibGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsIDApIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMCIgaGVpZ2h0PSIwIj48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9ImVkZ2VMYWJlbCI+PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWwiPjxnIGNsYXNzPSJsYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMCkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIwIiBoZWlnaHQ9IjAiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0iZWRnZUxhYmVsIj48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbCI+PGcgY2xhc3M9ImxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAwKSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjAiIGhlaWdodD0iMCI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48L2c+PGcgY2xhc3M9Im5vZGVzIj48ZyBjbGFzcz0ibm9kZSBkZWZhdWx0IGRlZmF1bHQgZmxvd2NoYXJ0LWxhYmVsIiBpZD0iZmxvd2NoYXJ0LW1pY3JvaHR0cC0wIiBkYXRhLW5vZGU9InRydWUiIGRhdGEtaWQ9Im1pY3JvaHR0cCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNjIuMDA3ODEyNSwgMTcpIj48cmVjdCBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIiBzdHlsZT0iIiByeD0iMCIgcnk9IjAiIHg9Ii02Mi4wMDc4MTI1IiB5PSItMTciIHdpZHRoPSIxMjQuMDE1NjI1IiBoZWlnaHQ9IjM0Ii8+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNTQuNTA3ODEyNSwgLTkuNSkiPjxyZWN0Lz48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMTA5LjAxNTYyNSIgaGVpZ2h0PSIxOSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPm9yZy5taWNyb2h0dHA8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IGZsb3djaGFydC1sYWJlbCIgaWQ9ImZsb3djaGFydC1taWNyb2h0dHAtaGFuZGxlci0xIiBkYXRhLW5vZGU9InRydWUiIGRhdGEtaWQ9Im1pY3JvaHR0cC1oYW5kbGVyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNDIuMTIxMDkzNzUsIDEwMSkiPjxyZWN0IGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiIHN0eWxlPSIiIHJ4PSIwIiByeT0iMCIgeD0iLTEyNS4yMjY1NjI1IiB5PSItMTciIHdpZHRoPSIyNTAuNDUzMTI1IiBoZWlnaHQ9IjM0Ii8+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTE3LjcyNjU2MjUsIC05LjUpIj48cmVjdC8+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjIzNS40NTMxMjUiIGhlaWdodD0iMTkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj5kZXYubWNjdWUubWljcm9odHRwLmhhbmRsZXI8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IGZsb3djaGFydC1sYWJlbCIgaWQ9ImZsb3djaGFydC1yZWFzb25waHJhc2UtNCIgZGF0YS1ub2RlPSJ0cnVlIiBkYXRhLWlkPSJyZWFzb25waHJhc2UiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQyNS4xMjg5MDYyNSwgMTAxKSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjAiIHJ5PSIwIiB4PSItMTA3Ljc4MTI1IiB5PSItMTciIHdpZHRoPSIyMTUuNTYyNSIgaGVpZ2h0PSIzNCIvPjxnIGNsYXNzPSJsYWJlbCIgc3R5bGU9IiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTEwMC4yODEyNSwgLTkuNSkiPjxyZWN0Lz48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMjAwLjU2MjUiIGhlaWdodD0iMTkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj5kZXYubWNjdWUucmVhc29ucGhyYXNlPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZGVmYXVsdCBmbG93Y2hhcnQtbGFiZWwiIGlkPSJmbG93Y2hhcnQtaHRtbC01IiBkYXRhLW5vZGU9InRydWUiIGRhdGEtaWQ9Imh0bWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDY1NC40MTc5Njg3NSwgMTAxKSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjAiIHJ5PSIwIiB4PSItNzEuNTA3ODEyNSIgeT0iLTE3IiB3aWR0aD0iMTQzLjAxNTYyNSIgaGVpZ2h0PSIzNCIvPjxnIGNsYXNzPSJsYWJlbCIgc3R5bGU9IiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTY0LjAwNzgxMjUsIC05LjUpIj48cmVjdC8+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjEyOC4wMTU2MjUiIGhlaWdodD0iMTkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj5kZXYubWNjdWUuaHRtbDwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0ibm9kZSBkZWZhdWx0IGdyZWVuIGZsb3djaGFydC1sYWJlbCIgaWQ9ImZsb3djaGFydC1taWNyb2h0dHAtaHRtbC02IiBkYXRhLW5vZGU9InRydWUiIGRhdGEtaWQ9Im1pY3JvaHR0cC1odG1sIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyODMuNjI1LCAxODUpIj48cmVjdCBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIiBzdHlsZT0iIiByeD0iMCIgcnk9IjAiIHg9Ii0xMTIuODkwNjI1IiB5PSItMTciIHdpZHRoPSIyMjUuNzgxMjUiIGhlaWdodD0iMzQiLz48ZyBjbGFzcz0ibGFiZWwiIHN0eWxlPSIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xMDUuMzkwNjI1LCAtOS41KSI+PHJlY3QvPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIyMTAuNzgxMjUiIGhlaWdodD0iMTkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj5kZXYubWNjdWUubWljcm9odHRwLmh0bWw8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjwvZz48L2c+PC9zdmc+" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>microhttp-html</code> provides <code>HtmlResponse</code>, a class which implements <code>IntoResponse</code> and thus can be used alongside <code>microhttp</code> and <code>microhttp-handler</code> to produce responses which contain html.</p>
<p>It automatically adds the appropriate <code>Content-Type</code> header, determines the HTTP reason phrase with <code>reasonphrase</code>, and accepts the <code>Html</code> type provided by <code>html</code>.</p>
<h2 id="why-use-it">Why use it</h2>
<p>If you are using <code>microhttp</code> with <code>microhttp-handler</code>, it boxes up the logic needed in order to return html responses. This would otherwise be cumbersome to write at every needed location</p>
<h2 id="getting-started">Getting Started</h2>
<p>At time of writing template processors are a preview-feature, so you will need to use the latest version of the library and the latest JDK.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">handler</span><span class="op">.</span><span class="im">RouteHandler</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">html</span><span class="op">.</span><span class="im">HtmlResponse</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">Properties</span><span class="op">;</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">regex</span><span class="op">.</span><span class="im">Pattern</span><span class="op">;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">regex</span><span class="op">.</span><span class="im">Matcher</span><span class="op">;</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">static</span><span class="im"> dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">html</span><span class="op">.</span><span class="im">Html</span><span class="op">.</span><span class="im">HTML</span><span class="op">;</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> IndexHandler <span class="kw">extends</span> RouteHandler <span class="op">{</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>    <span class="fu">IndexHandler</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">(</span><span class="st">&quot;GET&quot;</span><span class="op">,</span> <span class="bu">Pattern</span><span class="op">.</span><span class="fu">compile</span><span class="op">(</span><span class="st">&quot;/&quot;</span><span class="op">));</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> HtmlResponse <span class="fu">handleRoute</span><span class="op">(</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Matcher</span> matcher<span class="op">,</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Request</span> request</span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>        var name <span class="op">=</span> <span class="st">&quot;bob&quot;</span><span class="op">;</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">HtmlResponse</span><span class="op">(</span><span class="bu">HTML</span><span class="op">.</span><span class="st">&quot;&quot;&quot;</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>                <span class="op">&lt;</span>html<span class="op">&gt;</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>                  <span class="op">&lt;</span>body<span class="op">&gt;</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>                    <span class="op">&lt;</span>h1<span class="op">&gt;</span> Hello \<span class="op">{</span>name<span class="op">}</span> <span class="op">&lt;/</span>h1<span class="op">&gt;</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>                  <span class="op">&lt;/</span>body<span class="op">&gt;</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>                <span class="op">&lt;/</span>html<span class="op">&gt;</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;&quot;&quot;);</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>dev.mccue.html</title><link>https://mccue.dev/pages/12-9-23-java-library-of-the-day-9</link><description></description><pubDate>Sat, 09 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>dev.mccue.html</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">dev.mccue.html</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/dev.mccue/html"><code>dev.mccue/html</code></a></li>
<li>Module Name: <code>dev.mccue.html</code></li>
<li>GitHub: <a href="https://github.com/bowbahdoe/html"><code>bowbahdoe/html</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogMTU5LjAxNnB4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii04IC04IDE1OS4wMTU2MjUgNTAiIHJvbGU9ImdyYXBoaWNzLWRvY3VtZW50IGRvY3VtZW50IiBhcmlhLXJvbGVkZXNjcmlwdGlvbj0iZmxvd2NoYXJ0LXYyIj48c3R5bGU+I215LXN2Z3tmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjE2cHg7ZmlsbDojMzMzO30jbXktc3ZnIC5lcnJvci1pY29ue2ZpbGw6IzU1MjIyMjt9I215LXN2ZyAuZXJyb3ItdGV4dHtmaWxsOiM1NTIyMjI7c3Ryb2tlOiM1NTIyMjI7fSNteS1zdmcgLmVkZ2UtdGhpY2tuZXNzLW5vcm1hbHtzdHJva2Utd2lkdGg6MnB4O30jbXktc3ZnIC5lZGdlLXRoaWNrbmVzcy10aGlja3tzdHJva2Utd2lkdGg6My41cHg7fSNteS1zdmcgLmVkZ2UtcGF0dGVybi1zb2xpZHtzdHJva2UtZGFzaGFycmF5OjA7fSNteS1zdmcgLmVkZ2UtcGF0dGVybi1kYXNoZWR7c3Ryb2tlLWRhc2hhcnJheTozO30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tZG90dGVke3N0cm9rZS1kYXNoYXJyYXk6Mjt9I215LXN2ZyAubWFya2Vye2ZpbGw6IzMzMzMzMztzdHJva2U6IzMzMzMzMzt9I215LXN2ZyAubWFya2VyLmNyb3Nze3N0cm9rZTojMzMzMzMzO30jbXktc3ZnIHN2Z3tmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjE2cHg7fSNteS1zdmcgLmxhYmVse2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtjb2xvcjojMzMzO30jbXktc3ZnIC5jbHVzdGVyLWxhYmVsIHRleHR7ZmlsbDojMzMzO30jbXktc3ZnIC5jbHVzdGVyLWxhYmVsIHNwYW4sI215LXN2ZyBwe2NvbG9yOiMzMzM7fSNteS1zdmcgLmxhYmVsIHRleHQsI215LXN2ZyBzcGFuLCNteS1zdmcgcHtmaWxsOiMzMzM7Y29sb3I6IzMzMzt9I215LXN2ZyAubm9kZSByZWN0LCNteS1zdmcgLm5vZGUgY2lyY2xlLCNteS1zdmcgLm5vZGUgZWxsaXBzZSwjbXktc3ZnIC5ub2RlIHBvbHlnb24sI215LXN2ZyAubm9kZSBwYXRoe2ZpbGw6I0VDRUNGRjtzdHJva2U6IzkzNzBEQjtzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5mbG93Y2hhcnQtbGFiZWwgdGV4dHt0ZXh0LWFuY2hvcjptaWRkbGU7fSNteS1zdmcgLm5vZGUgLmthdGV4IHBhdGh7ZmlsbDojMDAwO3N0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxcHg7fSNteS1zdmcgLm5vZGUgLmxhYmVse3RleHQtYWxpZ246Y2VudGVyO30jbXktc3ZnIC5ub2RlLmNsaWNrYWJsZXtjdXJzb3I6cG9pbnRlcjt9I215LXN2ZyAuYXJyb3doZWFkUGF0aHtmaWxsOiMzMzMzMzM7fSNteS1zdmcgLmVkZ2VQYXRoIC5wYXRoe3N0cm9rZTojMzMzMzMzO3N0cm9rZS13aWR0aDoyLjBweDt9I215LXN2ZyAuZmxvd2NoYXJ0LWxpbmt7c3Ryb2tlOiMzMzMzMzM7ZmlsbDpub25lO30jbXktc3ZnIC5lZGdlTGFiZWx7YmFja2dyb3VuZC1jb2xvcjojZThlOGU4O3RleHQtYWxpZ246Y2VudGVyO30jbXktc3ZnIC5lZGdlTGFiZWwgcmVjdHtvcGFjaXR5OjAuNTtiYWNrZ3JvdW5kLWNvbG9yOiNlOGU4ZTg7ZmlsbDojZThlOGU4O30jbXktc3ZnIC5sYWJlbEJrZ3tiYWNrZ3JvdW5kLWNvbG9yOnJnYmEoMjMyLCAyMzIsIDIzMiwgMC41KTt9I215LXN2ZyAuY2x1c3RlciByZWN0e2ZpbGw6I2ZmZmZkZTtzdHJva2U6I2FhYWEzMztzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5jbHVzdGVyIHRleHR7ZmlsbDojMzMzO30jbXktc3ZnIC5jbHVzdGVyIHNwYW4sI215LXN2ZyBwe2NvbG9yOiMzMzM7fSNteS1zdmcgZGl2Lm1lcm1haWRUb29sdGlwe3Bvc2l0aW9uOmFic29sdXRlO3RleHQtYWxpZ246Y2VudGVyO21heC13aWR0aDoyMDBweDtwYWRkaW5nOjJweDtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjEycHg7YmFja2dyb3VuZDpoc2woODAsIDEwMCUsIDk2LjI3NDUwOTgwMzklKTtib3JkZXI6MXB4IHNvbGlkICNhYWFhMzM7Ym9yZGVyLXJhZGl1czoycHg7cG9pbnRlci1ldmVudHM6bm9uZTt6LWluZGV4OjEwMDt9I215LXN2ZyAuZmxvd2NoYXJ0VGl0bGVUZXh0e3RleHQtYW5jaG9yOm1pZGRsZTtmb250LXNpemU6MThweDtmaWxsOiMzMzM7fSNteS1zdmcgOnJvb3R7LS1tZXJtYWlkLWZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjt9I215LXN2ZyAuZ3JlZW4mZ3Q7KntzdHJva2U6cmdiKDI1NSwgMCwgMCkhaW1wb3J0YW50O30jbXktc3ZnIC5ncmVlbiBzcGFue3N0cm9rZTpyZ2IoMjU1LCAwLCAwKSFpbXBvcnRhbnQ7fTwvc3R5bGU+PGc+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1wb2ludEVuZCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iNiIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTIiIG1hcmtlckhlaWdodD0iMTIiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAwIDAgTCAxMCA1IEwgMCAxMCB6IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtcG9pbnRTdGFydCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iNC41IiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMiIgbWFya2VySGVpZ2h0PSIxMiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDAgNSBMIDEwIDEwIEwgMTAgMCB6IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY2lyY2xlRW5kIiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSIxMSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PGNpcmNsZSBjeD0iNSIgY3k9IjUiIHI9IjUiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jaXJjbGVTdGFydCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iLTEiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxjaXJjbGUgY3g9IjUiIGN5PSI1IiByPSI1IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY3Jvc3NFbmQiIGNsYXNzPSJtYXJrZXIgY3Jvc3MgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTEgMTEiIHJlZlg9IjEyIiByZWZZPSI1LjIiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMSwxIGwgOSw5IE0gMTAsMSBsIC05LDkiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDI7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jcm9zc1N0YXJ0IiBjbGFzcz0ibWFya2VyIGNyb3NzIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDExIDExIiByZWZYPSItMSIgcmVmWT0iNS4yIiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDEsMSBsIDksOSBNIDEwLDEgbCAtOSw5IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAyOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxnIGNsYXNzPSJyb290Ij48ZyBjbGFzcz0iY2x1c3RlcnMiLz48ZyBjbGFzcz0iZWRnZVBhdGhzIi8+PGcgY2xhc3M9ImVkZ2VMYWJlbHMiLz48ZyBjbGFzcz0ibm9kZXMiPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZ3JlZW4gZmxvd2NoYXJ0LWxhYmVsIiBpZD0iZmxvd2NoYXJ0LWh0bWwtMCIgZGF0YS1ub2RlPSJ0cnVlIiBkYXRhLWlkPSJodG1sIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg3MS41MDc4MTI1LCAxNykiPjxyZWN0IGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiIHN0eWxlPSIiIHJ4PSIwIiByeT0iMCIgeD0iLTcxLjUwNzgxMjUiIHk9Ii0xNyIgd2lkdGg9IjE0My4wMTU2MjUiIGhlaWdodD0iMzQiLz48ZyBjbGFzcz0ibGFiZWwiIHN0eWxlPSIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC02NC4wMDc4MTI1LCAtOS41KSI+PHJlY3QvPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIxMjguMDE1NjI1IiBoZWlnaHQ9IjE5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+ZGV2Lm1jY3VlLmh0bWw8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjwvZz48L2c+PC9zdmc+" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>html</code> provides an <code>Html</code> type and a template processor which produces <code>Html</code> and auto-escapes any embedded values.</p>
<h2 id="why-use-it">Why use it</h2>
<p>Before template processors, your options for producing html were to</p>
<ul>
<li>Keep the HTML in a template - usually, but not always, in a separate file</li>
<li>Generate HTML with a programattic API.</li>
</ul>
<p>The first option is the most widespread, but means that your logic for filling in the template won't be co-located with the contents of the template itself. It also gives a damp and dimly-lit surface for "template languages" to grow. These are often full programming languages in their own right and require special IDE support.</p>
<p>The second option isn't as popular because you effectively lose the ability to apply the expertise of designers, who are generally familiar with HTML and are used to seeing page layout expressed in HTML. It also puts a lot of pressure on the programmatic API, since you need to make sure every HTML idiom you need to express is expressible. A difficult feat with an evolving standard.</p>
<p>Template processors are a middle ground of sorts.</p>
<p>They are a templating language but, because they will be an official part of Java, you can count on IDE support and will be able to collocate them with the code for filling in values.</p>
<p>They are a programmatic API but, because you write HTML directly, every idiom is expressible. It should be familiar to most designers as well.</p>
<p>You could reasonably draw a parallels between this approach and <code>JSX</code> from the JavaScript world.</p>
<h2 id="getting-started">Getting Started</h2>
<p>At time of writing template processors are a preview-feature, so you will need to use the latest version of the library and the latest JDK.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">List</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">ArrayList</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">html</span><span class="op">.</span><span class="im">Html</span><span class="op">;</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">static</span><span class="im"> dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">html</span><span class="op">.</span><span class="im">Html</span><span class="op">.</span><span class="im">HTML</span><span class="op">;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    <span class="bu">String</span> name <span class="op">=</span> <span class="st">&quot;joe&quot;</span><span class="op">;</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>    var pets <span class="op">=</span> <span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;snoopy&quot;</span><span class="op">,</span> <span class="st">&quot;Yellow Bird&quot;</span><span class="op">);</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>    var petHtml <span class="op">=</span> <span class="kw">new</span> <span class="bu">ArrayList</span><span class="op">&lt;</span>Html<span class="op">&gt;();</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span>var pet <span class="op">:</span> pets<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>        petHtml<span class="op">.</span><span class="fu">add</span><span class="op">(</span><span class="bu">HTML</span><span class="op">.</span><span class="st">&quot;&lt;li&gt; </span><span class="er">\{</span><span class="st">pet} &lt;/li&gt;&quot;</span><span class="op">);</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>    var page <span class="op">=</span> <span class="bu">HTML</span><span class="op">.</span><span class="st">&quot;&quot;&quot;</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>        <span class="op">&lt;</span>html<span class="op">&gt;</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>          <span class="op">&lt;</span>body<span class="op">&gt;</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>            <span class="op">&lt;</span>h1<span class="op">&gt;</span> Hello \<span class="op">{</span>name<span class="op">}</span> <span class="op">&lt;/</span>h1<span class="op">&gt;</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>            <span class="op">&lt;</span>ul<span class="op">&gt;</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>              \<span class="op">{</span>petHtml<span class="op">}</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>            <span class="op">&lt;/</span>ul<span class="op">&gt;</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>          <span class="op">&lt;/</span>body<span class="op">&gt;</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>        <span class="op">&lt;/</span>html<span class="op">&gt;</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;&quot;&quot;;</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>org.slf4j.simple</title><link>https://mccue.dev/pages/12-8-23-java-library-of-the-day-8</link><description></description><pubDate>Fri, 08 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>org.slf4j.simple</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">org.slf4j.simple</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/org.slf4j/slf4j-simple"><code>org.slf4j/slf4j-simple</code></a></li>
<li>Module Name: <code>org.slf4j.simple</code></li>
<li>GitHub: <a href="https://github.com/qos-ch/slf4j"><code>qos-ch/slf4j</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogMTUzLjI2NnB4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii04IC04IDE1My4yNjU2MjUgMTM0IiByb2xlPSJncmFwaGljcy1kb2N1bWVudCBkb2N1bWVudCIgYXJpYS1yb2xlZGVzY3JpcHRpb249ImZsb3djaGFydC12MiI+PHN0eWxlPiNteS1zdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O2ZpbGw6IzMzMzt9I215LXN2ZyAuZXJyb3ItaWNvbntmaWxsOiM1NTIyMjI7fSNteS1zdmcgLmVycm9yLXRleHR7ZmlsbDojNTUyMjIyO3N0cm9rZTojNTUyMjIyO30jbXktc3ZnIC5lZGdlLXRoaWNrbmVzcy1ub3JtYWx7c3Ryb2tlLXdpZHRoOjJweDt9I215LXN2ZyAuZWRnZS10aGlja25lc3MtdGhpY2t7c3Ryb2tlLXdpZHRoOjMuNXB4O30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tc29saWR7c3Ryb2tlLWRhc2hhcnJheTowO30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tZGFzaGVke3N0cm9rZS1kYXNoYXJyYXk6Mzt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLWRvdHRlZHtzdHJva2UtZGFzaGFycmF5OjI7fSNteS1zdmcgLm1hcmtlcntmaWxsOiMzMzMzMzM7c3Ryb2tlOiMzMzMzMzM7fSNteS1zdmcgLm1hcmtlci5jcm9zc3tzdHJva2U6IzMzMzMzMzt9I215LXN2ZyBzdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O30jbXktc3ZnIC5sYWJlbHtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Y29sb3I6IzMzMzt9I215LXN2ZyAuY2x1c3Rlci1sYWJlbCB0ZXh0e2ZpbGw6IzMzMzt9I215LXN2ZyAuY2x1c3Rlci1sYWJlbCBzcGFuLCNteS1zdmcgcHtjb2xvcjojMzMzO30jbXktc3ZnIC5sYWJlbCB0ZXh0LCNteS1zdmcgc3BhbiwjbXktc3ZnIHB7ZmlsbDojMzMzO2NvbG9yOiMzMzM7fSNteS1zdmcgLm5vZGUgcmVjdCwjbXktc3ZnIC5ub2RlIGNpcmNsZSwjbXktc3ZnIC5ub2RlIGVsbGlwc2UsI215LXN2ZyAubm9kZSBwb2x5Z29uLCNteS1zdmcgLm5vZGUgcGF0aHtmaWxsOiNFQ0VDRkY7c3Ryb2tlOiM5MzcwREI7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAuZmxvd2NoYXJ0LWxhYmVsIHRleHR7dGV4dC1hbmNob3I6bWlkZGxlO30jbXktc3ZnIC5ub2RlIC5rYXRleCBwYXRoe2ZpbGw6IzAwMDtzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5ub2RlIC5sYWJlbHt0ZXh0LWFsaWduOmNlbnRlcjt9I215LXN2ZyAubm9kZS5jbGlja2FibGV7Y3Vyc29yOnBvaW50ZXI7fSNteS1zdmcgLmFycm93aGVhZFBhdGh7ZmlsbDojMzMzMzMzO30jbXktc3ZnIC5lZGdlUGF0aCAucGF0aHtzdHJva2U6IzMzMzMzMztzdHJva2Utd2lkdGg6Mi4wcHg7fSNteS1zdmcgLmZsb3djaGFydC1saW5re3N0cm9rZTojMzMzMzMzO2ZpbGw6bm9uZTt9I215LXN2ZyAuZWRnZUxhYmVse2JhY2tncm91bmQtY29sb3I6I2U4ZThlODt0ZXh0LWFsaWduOmNlbnRlcjt9I215LXN2ZyAuZWRnZUxhYmVsIHJlY3R7b3BhY2l0eTowLjU7YmFja2dyb3VuZC1jb2xvcjojZThlOGU4O2ZpbGw6I2U4ZThlODt9I215LXN2ZyAubGFiZWxCa2d7YmFja2dyb3VuZC1jb2xvcjpyZ2JhKDIzMiwgMjMyLCAyMzIsIDAuNSk7fSNteS1zdmcgLmNsdXN0ZXIgcmVjdHtmaWxsOiNmZmZmZGU7c3Ryb2tlOiNhYWFhMzM7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAuY2x1c3RlciB0ZXh0e2ZpbGw6IzMzMzt9I215LXN2ZyAuY2x1c3RlciBzcGFuLCNteS1zdmcgcHtjb2xvcjojMzMzO30jbXktc3ZnIGRpdi5tZXJtYWlkVG9vbHRpcHtwb3NpdGlvbjphYnNvbHV0ZTt0ZXh0LWFsaWduOmNlbnRlcjttYXgtd2lkdGg6MjAwcHg7cGFkZGluZzoycHg7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxMnB4O2JhY2tncm91bmQ6aHNsKDgwLCAxMDAlLCA5Ni4yNzQ1MDk4MDM5JSk7Ym9yZGVyOjFweCBzb2xpZCAjYWFhYTMzO2JvcmRlci1yYWRpdXM6MnB4O3BvaW50ZXItZXZlbnRzOm5vbmU7ei1pbmRleDoxMDA7fSNteS1zdmcgLmZsb3djaGFydFRpdGxlVGV4dHt0ZXh0LWFuY2hvcjptaWRkbGU7Zm9udC1zaXplOjE4cHg7ZmlsbDojMzMzO30jbXktc3ZnIDpyb290ey0tbWVybWFpZC1mb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7fSNteS1zdmcgLmdyZWVuJmd0Oyp7c3Ryb2tlOnJnYigyNTUsIDAsIDApIWltcG9ydGFudDt9I215LXN2ZyAuZ3JlZW4gc3BhbntzdHJva2U6cmdiKDI1NSwgMCwgMCkhaW1wb3J0YW50O308L3N0eWxlPjxnPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtcG9pbnRFbmQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjYiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjEyIiBtYXJrZXJIZWlnaHQ9IjEyIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMCAwIEwgMTAgNSBMIDAgMTAgeiIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LXBvaW50U3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjQuNSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTIiIG1hcmtlckhlaWdodD0iMTIiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAwIDUgTCAxMCAxMCBMIDEwIDAgeiIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNpcmNsZUVuZCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iMTEiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxjaXJjbGUgY3g9IjUiIGN5PSI1IiByPSI1IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY2lyY2xlU3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9Ii0xIiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48Y2lyY2xlIGN4PSI1IiBjeT0iNSIgcj0iNSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNyb3NzRW5kIiBjbGFzcz0ibWFya2VyIGNyb3NzIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDExIDExIiByZWZYPSIxMiIgcmVmWT0iNS4yIiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDEsMSBsIDksOSBNIDEwLDEgbCAtOSw5IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAyOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY3Jvc3NTdGFydCIgY2xhc3M9Im1hcmtlciBjcm9zcyBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMSAxMSIgcmVmWD0iLTEiIHJlZlk9IjUuMiIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAxLDEgbCA5LDkgTSAxMCwxIGwgLTksOSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMjsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48ZyBjbGFzcz0icm9vdCI+PGcgY2xhc3M9ImNsdXN0ZXJzIi8+PGcgY2xhc3M9ImVkZ2VQYXRocyI+PHBhdGggZD0iTTY4LjYzMywzNEw2OC42MzMsMzguMTY3QzY4LjYzMyw0Mi4zMzMsNjguNjMzLDUwLjY2Nyw2OC42MzMsNTguMTE3QzY4LjYzMyw2NS41NjcsNjguNjMzLDcyLjEzMyw2OC42MzMsNzUuNDE3TDY4LjYzMyw3OC43IiBpZD0iTC1zbGY0ai1zbGY0ai1zaW1wbGUtMCIgY2xhc3M9ImVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtc2xmNGogTEUtc2xmNGotc2ltcGxlIiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLWVuZD0idXJsKCNteS1zdmdfZmxvd2NoYXJ0LXBvaW50RW5kKSIvPjwvZz48ZyBjbGFzcz0iZWRnZUxhYmVscyI+PGcgY2xhc3M9ImVkZ2VMYWJlbCI+PGcgY2xhc3M9ImxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAwKSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjAiIGhlaWdodD0iMCI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48L2c+PGcgY2xhc3M9Im5vZGVzIj48ZyBjbGFzcz0ibm9kZSBkZWZhdWx0IGRlZmF1bHQgZmxvd2NoYXJ0LWxhYmVsIiBpZD0iZmxvd2NoYXJ0LXNsZjRqLTAiIGRhdGEtbm9kZT0idHJ1ZSIgZGF0YS1pZD0ic2xmNGoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDY4LjYzMjgxMjUsIDE3KSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjAiIHJ5PSIwIiB4PSItMzkuNjg3NSIgeT0iLTE3IiB3aWR0aD0iNzkuMzc1IiBoZWlnaHQ9IjM0Ii8+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMzIuMTg3NSwgLTkuNSkiPjxyZWN0Lz48Zm9yZWlnbk9iamVjdCB3aWR0aD0iNjQuMzc1IiBoZWlnaHQ9IjE5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+b3JnLnNsZjRqPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZ3JlZW4gZmxvd2NoYXJ0LWxhYmVsIiBpZD0iZmxvd2NoYXJ0LXNsZjRqLXNpbXBsZS0xIiBkYXRhLW5vZGU9InRydWUiIGRhdGEtaWQ9InNsZjRqLXNpbXBsZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNjguNjMyODEyNSwgMTAxKSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjAiIHJ5PSIwIiB4PSItNjguNjMyODEyNSIgeT0iLTE3IiB3aWR0aD0iMTM3LjI2NTYyNSIgaGVpZ2h0PSIzNCIvPjxnIGNsYXNzPSJsYWJlbCIgc3R5bGU9IiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTYxLjEzMjgxMjUsIC05LjUpIj48cmVjdC8+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjEyMi4yNjU2MjUiIGhlaWdodD0iMTkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj5vcmcuc2xmNGouc2ltcGxlPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjwvZz48L2c+PC9nPjwvc3ZnPg==" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>slf4j-simple</code> is a logging implementation for <code>slf4j-api</code>.</p>
<p>It prints log message emitted at a level of <code>INFO</code> or above to <code>System.err</code>.</p>
<h2 id="why-use-it">Why use it</h2>
<p>If any dependency you have uses <code>slf4j-api</code> you will get errors at startup about not having a logging implementation.</p>
<p><code>slf4j-simple</code> is not flexible or "powerful" by any definition but, depending on how you deploy your application, it might be all you need.</p>
<h2 id="getting-started">Getting Started</h2>
<p>You need to have both <code>slf4j-api</code> and <code>slf4j-simple</code> available to your program, then you should see output from logging statements.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">slf4j</span><span class="op">.</span><span class="im">Logger</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">slf4j</span><span class="op">.</span><span class="im">LoggerFactory</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Logger</span> logger <span class="op">=</span> LoggerFactory<span class="op">.</span><span class="fu">getLogger</span><span class="op">(</span><span class="fu">getClass</span><span class="op">());</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    logger<span class="op">.</span><span class="fu">info</span><span class="op">(</span><span class="st">&quot;Hello World&quot;</span><span class="op">);</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>org.slf4j</title><link>https://mccue.dev/pages/12-7-23-java-library-of-the-day-7</link><description></description><pubDate>Thu, 07 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>org.slf4j</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">org.slf4j</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/org.slf4j/slf4j-api"><code>org.slf4j/slf4j-api</code></a></li>
<li>Module Name: <code>org.slf4j</code></li>
<li>GitHub: <a href="https://github.com/qos-ch/slf4j"><code>qos-ch/slf4j</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogOTUuMzc1cHg7IGJhY2tncm91bmQtY29sb3I6IHdoaXRlOyIgdmlld0JveD0iLTggLTggOTUuMzc1IDUwIiByb2xlPSJncmFwaGljcy1kb2N1bWVudCBkb2N1bWVudCIgYXJpYS1yb2xlZGVzY3JpcHRpb249ImZsb3djaGFydC12MiI+PHN0eWxlPiNteS1zdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O2ZpbGw6IzMzMzt9I215LXN2ZyAuZXJyb3ItaWNvbntmaWxsOiM1NTIyMjI7fSNteS1zdmcgLmVycm9yLXRleHR7ZmlsbDojNTUyMjIyO3N0cm9rZTojNTUyMjIyO30jbXktc3ZnIC5lZGdlLXRoaWNrbmVzcy1ub3JtYWx7c3Ryb2tlLXdpZHRoOjJweDt9I215LXN2ZyAuZWRnZS10aGlja25lc3MtdGhpY2t7c3Ryb2tlLXdpZHRoOjMuNXB4O30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tc29saWR7c3Ryb2tlLWRhc2hhcnJheTowO30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tZGFzaGVke3N0cm9rZS1kYXNoYXJyYXk6Mzt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLWRvdHRlZHtzdHJva2UtZGFzaGFycmF5OjI7fSNteS1zdmcgLm1hcmtlcntmaWxsOiMzMzMzMzM7c3Ryb2tlOiMzMzMzMzM7fSNteS1zdmcgLm1hcmtlci5jcm9zc3tzdHJva2U6IzMzMzMzMzt9I215LXN2ZyBzdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O30jbXktc3ZnIC5sYWJlbHtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Y29sb3I6IzMzMzt9I215LXN2ZyAuY2x1c3Rlci1sYWJlbCB0ZXh0e2ZpbGw6IzMzMzt9I215LXN2ZyAuY2x1c3Rlci1sYWJlbCBzcGFuLCNteS1zdmcgcHtjb2xvcjojMzMzO30jbXktc3ZnIC5sYWJlbCB0ZXh0LCNteS1zdmcgc3BhbiwjbXktc3ZnIHB7ZmlsbDojMzMzO2NvbG9yOiMzMzM7fSNteS1zdmcgLm5vZGUgcmVjdCwjbXktc3ZnIC5ub2RlIGNpcmNsZSwjbXktc3ZnIC5ub2RlIGVsbGlwc2UsI215LXN2ZyAubm9kZSBwb2x5Z29uLCNteS1zdmcgLm5vZGUgcGF0aHtmaWxsOiNFQ0VDRkY7c3Ryb2tlOiM5MzcwREI7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAuZmxvd2NoYXJ0LWxhYmVsIHRleHR7dGV4dC1hbmNob3I6bWlkZGxlO30jbXktc3ZnIC5ub2RlIC5rYXRleCBwYXRoe2ZpbGw6IzAwMDtzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5ub2RlIC5sYWJlbHt0ZXh0LWFsaWduOmNlbnRlcjt9I215LXN2ZyAubm9kZS5jbGlja2FibGV7Y3Vyc29yOnBvaW50ZXI7fSNteS1zdmcgLmFycm93aGVhZFBhdGh7ZmlsbDojMzMzMzMzO30jbXktc3ZnIC5lZGdlUGF0aCAucGF0aHtzdHJva2U6IzMzMzMzMztzdHJva2Utd2lkdGg6Mi4wcHg7fSNteS1zdmcgLmZsb3djaGFydC1saW5re3N0cm9rZTojMzMzMzMzO2ZpbGw6bm9uZTt9I215LXN2ZyAuZWRnZUxhYmVse2JhY2tncm91bmQtY29sb3I6I2U4ZThlODt0ZXh0LWFsaWduOmNlbnRlcjt9I215LXN2ZyAuZWRnZUxhYmVsIHJlY3R7b3BhY2l0eTowLjU7YmFja2dyb3VuZC1jb2xvcjojZThlOGU4O2ZpbGw6I2U4ZThlODt9I215LXN2ZyAubGFiZWxCa2d7YmFja2dyb3VuZC1jb2xvcjpyZ2JhKDIzMiwgMjMyLCAyMzIsIDAuNSk7fSNteS1zdmcgLmNsdXN0ZXIgcmVjdHtmaWxsOiNmZmZmZGU7c3Ryb2tlOiNhYWFhMzM7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAuY2x1c3RlciB0ZXh0e2ZpbGw6IzMzMzt9I215LXN2ZyAuY2x1c3RlciBzcGFuLCNteS1zdmcgcHtjb2xvcjojMzMzO30jbXktc3ZnIGRpdi5tZXJtYWlkVG9vbHRpcHtwb3NpdGlvbjphYnNvbHV0ZTt0ZXh0LWFsaWduOmNlbnRlcjttYXgtd2lkdGg6MjAwcHg7cGFkZGluZzoycHg7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxMnB4O2JhY2tncm91bmQ6aHNsKDgwLCAxMDAlLCA5Ni4yNzQ1MDk4MDM5JSk7Ym9yZGVyOjFweCBzb2xpZCAjYWFhYTMzO2JvcmRlci1yYWRpdXM6MnB4O3BvaW50ZXItZXZlbnRzOm5vbmU7ei1pbmRleDoxMDA7fSNteS1zdmcgLmZsb3djaGFydFRpdGxlVGV4dHt0ZXh0LWFuY2hvcjptaWRkbGU7Zm9udC1zaXplOjE4cHg7ZmlsbDojMzMzO30jbXktc3ZnIDpyb290ey0tbWVybWFpZC1mb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7fSNteS1zdmcgLmdyZWVuJmd0Oyp7c3Ryb2tlOnJnYigyNTUsIDAsIDApIWltcG9ydGFudDt9I215LXN2ZyAuZ3JlZW4gc3BhbntzdHJva2U6cmdiKDI1NSwgMCwgMCkhaW1wb3J0YW50O308L3N0eWxlPjxnPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtcG9pbnRFbmQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjYiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjEyIiBtYXJrZXJIZWlnaHQ9IjEyIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMCAwIEwgMTAgNSBMIDAgMTAgeiIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LXBvaW50U3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjQuNSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTIiIG1hcmtlckhlaWdodD0iMTIiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAwIDUgTCAxMCAxMCBMIDEwIDAgeiIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNpcmNsZUVuZCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iMTEiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxjaXJjbGUgY3g9IjUiIGN5PSI1IiByPSI1IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY2lyY2xlU3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9Ii0xIiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48Y2lyY2xlIGN4PSI1IiBjeT0iNSIgcj0iNSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNyb3NzRW5kIiBjbGFzcz0ibWFya2VyIGNyb3NzIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDExIDExIiByZWZYPSIxMiIgcmVmWT0iNS4yIiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDEsMSBsIDksOSBNIDEwLDEgbCAtOSw5IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAyOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY3Jvc3NTdGFydCIgY2xhc3M9Im1hcmtlciBjcm9zcyBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMSAxMSIgcmVmWD0iLTEiIHJlZlk9IjUuMiIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAxLDEgbCA5LDkgTSAxMCwxIGwgLTksOSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMjsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48ZyBjbGFzcz0icm9vdCI+PGcgY2xhc3M9ImNsdXN0ZXJzIi8+PGcgY2xhc3M9ImVkZ2VQYXRocyIvPjxnIGNsYXNzPSJlZGdlTGFiZWxzIi8+PGcgY2xhc3M9Im5vZGVzIj48ZyBjbGFzcz0ibm9kZSBkZWZhdWx0IGdyZWVuIGZsb3djaGFydC1sYWJlbCIgaWQ9ImZsb3djaGFydC1zbGY0ai0wIiBkYXRhLW5vZGU9InRydWUiIGRhdGEtaWQ9InNsZjRqIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzOS42ODc1LCAxNykiPjxyZWN0IGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiIHN0eWxlPSIiIHJ4PSIwIiByeT0iMCIgeD0iLTM5LjY4NzUiIHk9Ii0xNyIgd2lkdGg9Ijc5LjM3NSIgaGVpZ2h0PSIzNCIvPjxnIGNsYXNzPSJsYWJlbCIgc3R5bGU9IiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTMyLjE4NzUsIC05LjUpIj48cmVjdC8+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjY0LjM3NSIgaGVpZ2h0PSIxOSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPm9yZy5zbGY0ajwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>slf4j-api</code> - "Simple Logging Facade for Java" - is a logging facade. For Java</p>
<h2 id="why-use-it">Why use it</h2>
<p>Logging facades let portions of a larger program emit text based logs without needing to know how those logs will be published.</p>
<p>This means external libraries will often emit logs via <code>slf4j</code> and expect that the application they are included in to publish them with a logging implementation.</p>
<p><code>slf4j-api</code> is the most ubiquitous of these and the winner of the 90s "logging wars."</p>
<h2 id="getting-started">Getting Started</h2>
<p>In order to have the code below emit any output, you need to make sure a logging implementation is included in your project. I'll introduce one of those tomorrow.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">slf4j</span><span class="op">.</span><span class="im">Logger</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">slf4j</span><span class="op">.</span><span class="im">LoggerFactory</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Logger</span> logger <span class="op">=</span> LoggerFactory<span class="op">.</span><span class="fu">getLogger</span><span class="op">(</span><span class="fu">getClass</span><span class="op">());</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    logger<span class="op">.</span><span class="fu">info</span><span class="op">(</span><span class="st">&quot;Hello World&quot;</span><span class="op">);</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>dev.mccue.microhttp.handler</title><link>https://mccue.dev/pages/12-6-23-java-library-of-the-day-6</link><description></description><pubDate>Wed, 06 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>dev.mccue.microhttp.handler</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">dev.mccue.microhttp.handler</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/dev.mccue/microhttp-handler"><code>dev.mccue/microhttp-handler</code></a></li>
<li>Module Name: <code>dev.mccue.microhttp.handler</code></li>
<li>GitHub: <a href="https://github.com/bowbahdoe/microhttp-handler"><code>bowbahdoe/microhttp-handler</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogMjY2LjQ1M3B4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii04IC04IDI2Ni40NTMxMjUgMTM0IiByb2xlPSJncmFwaGljcy1kb2N1bWVudCBkb2N1bWVudCIgYXJpYS1yb2xlZGVzY3JpcHRpb249ImZsb3djaGFydC12MiI+PHN0eWxlPiNteS1zdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O2ZpbGw6IzMzMzt9I215LXN2ZyAuZXJyb3ItaWNvbntmaWxsOiM1NTIyMjI7fSNteS1zdmcgLmVycm9yLXRleHR7ZmlsbDojNTUyMjIyO3N0cm9rZTojNTUyMjIyO30jbXktc3ZnIC5lZGdlLXRoaWNrbmVzcy1ub3JtYWx7c3Ryb2tlLXdpZHRoOjJweDt9I215LXN2ZyAuZWRnZS10aGlja25lc3MtdGhpY2t7c3Ryb2tlLXdpZHRoOjMuNXB4O30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tc29saWR7c3Ryb2tlLWRhc2hhcnJheTowO30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tZGFzaGVke3N0cm9rZS1kYXNoYXJyYXk6Mzt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLWRvdHRlZHtzdHJva2UtZGFzaGFycmF5OjI7fSNteS1zdmcgLm1hcmtlcntmaWxsOiMzMzMzMzM7c3Ryb2tlOiMzMzMzMzM7fSNteS1zdmcgLm1hcmtlci5jcm9zc3tzdHJva2U6IzMzMzMzMzt9I215LXN2ZyBzdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O30jbXktc3ZnIC5sYWJlbHtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Y29sb3I6IzMzMzt9I215LXN2ZyAuY2x1c3Rlci1sYWJlbCB0ZXh0e2ZpbGw6IzMzMzt9I215LXN2ZyAuY2x1c3Rlci1sYWJlbCBzcGFuLCNteS1zdmcgcHtjb2xvcjojMzMzO30jbXktc3ZnIC5sYWJlbCB0ZXh0LCNteS1zdmcgc3BhbiwjbXktc3ZnIHB7ZmlsbDojMzMzO2NvbG9yOiMzMzM7fSNteS1zdmcgLm5vZGUgcmVjdCwjbXktc3ZnIC5ub2RlIGNpcmNsZSwjbXktc3ZnIC5ub2RlIGVsbGlwc2UsI215LXN2ZyAubm9kZSBwb2x5Z29uLCNteS1zdmcgLm5vZGUgcGF0aHtmaWxsOiNFQ0VDRkY7c3Ryb2tlOiM5MzcwREI7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAuZmxvd2NoYXJ0LWxhYmVsIHRleHR7dGV4dC1hbmNob3I6bWlkZGxlO30jbXktc3ZnIC5ub2RlIC5rYXRleCBwYXRoe2ZpbGw6IzAwMDtzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5ub2RlIC5sYWJlbHt0ZXh0LWFsaWduOmNlbnRlcjt9I215LXN2ZyAubm9kZS5jbGlja2FibGV7Y3Vyc29yOnBvaW50ZXI7fSNteS1zdmcgLmFycm93aGVhZFBhdGh7ZmlsbDojMzMzMzMzO30jbXktc3ZnIC5lZGdlUGF0aCAucGF0aHtzdHJva2U6IzMzMzMzMztzdHJva2Utd2lkdGg6Mi4wcHg7fSNteS1zdmcgLmZsb3djaGFydC1saW5re3N0cm9rZTojMzMzMzMzO2ZpbGw6bm9uZTt9I215LXN2ZyAuZWRnZUxhYmVse2JhY2tncm91bmQtY29sb3I6I2U4ZThlODt0ZXh0LWFsaWduOmNlbnRlcjt9I215LXN2ZyAuZWRnZUxhYmVsIHJlY3R7b3BhY2l0eTowLjU7YmFja2dyb3VuZC1jb2xvcjojZThlOGU4O2ZpbGw6I2U4ZThlODt9I215LXN2ZyAubGFiZWxCa2d7YmFja2dyb3VuZC1jb2xvcjpyZ2JhKDIzMiwgMjMyLCAyMzIsIDAuNSk7fSNteS1zdmcgLmNsdXN0ZXIgcmVjdHtmaWxsOiNmZmZmZGU7c3Ryb2tlOiNhYWFhMzM7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAuY2x1c3RlciB0ZXh0e2ZpbGw6IzMzMzt9I215LXN2ZyAuY2x1c3RlciBzcGFuLCNteS1zdmcgcHtjb2xvcjojMzMzO30jbXktc3ZnIGRpdi5tZXJtYWlkVG9vbHRpcHtwb3NpdGlvbjphYnNvbHV0ZTt0ZXh0LWFsaWduOmNlbnRlcjttYXgtd2lkdGg6MjAwcHg7cGFkZGluZzoycHg7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxMnB4O2JhY2tncm91bmQ6aHNsKDgwLCAxMDAlLCA5Ni4yNzQ1MDk4MDM5JSk7Ym9yZGVyOjFweCBzb2xpZCAjYWFhYTMzO2JvcmRlci1yYWRpdXM6MnB4O3BvaW50ZXItZXZlbnRzOm5vbmU7ei1pbmRleDoxMDA7fSNteS1zdmcgLmZsb3djaGFydFRpdGxlVGV4dHt0ZXh0LWFuY2hvcjptaWRkbGU7Zm9udC1zaXplOjE4cHg7ZmlsbDojMzMzO30jbXktc3ZnIDpyb290ey0tbWVybWFpZC1mb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7fSNteS1zdmcgLmdyZWVuJmd0Oyp7c3Ryb2tlOnJnYigyNTUsIDAsIDApIWltcG9ydGFudDt9I215LXN2ZyAuZ3JlZW4gc3BhbntzdHJva2U6cmdiKDI1NSwgMCwgMCkhaW1wb3J0YW50O308L3N0eWxlPjxnPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtcG9pbnRFbmQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjYiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjEyIiBtYXJrZXJIZWlnaHQ9IjEyIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMCAwIEwgMTAgNSBMIDAgMTAgeiIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LXBvaW50U3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjQuNSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTIiIG1hcmtlckhlaWdodD0iMTIiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAwIDUgTCAxMCAxMCBMIDEwIDAgeiIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNpcmNsZUVuZCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iMTEiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxjaXJjbGUgY3g9IjUiIGN5PSI1IiByPSI1IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY2lyY2xlU3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9Ii0xIiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48Y2lyY2xlIGN4PSI1IiBjeT0iNSIgcj0iNSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNyb3NzRW5kIiBjbGFzcz0ibWFya2VyIGNyb3NzIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDExIDExIiByZWZYPSIxMiIgcmVmWT0iNS4yIiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDEsMSBsIDksOSBNIDEwLDEgbCAtOSw5IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAyOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY3Jvc3NTdGFydCIgY2xhc3M9Im1hcmtlciBjcm9zcyBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMSAxMSIgcmVmWD0iLTEiIHJlZlk9IjUuMiIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAxLDEgbCA5LDkgTSAxMCwxIGwgLTksOSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMjsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48ZyBjbGFzcz0icm9vdCI+PGcgY2xhc3M9ImNsdXN0ZXJzIi8+PGcgY2xhc3M9ImVkZ2VQYXRocyI+PHBhdGggZD0iTTEyNS4yMjcsMzRMMTI1LjIyNywzOC4xNjdDMTI1LjIyNyw0Mi4zMzMsMTI1LjIyNyw1MC42NjcsMTI1LjIyNyw1OC4xMTdDMTI1LjIyNyw2NS41NjcsMTI1LjIyNyw3Mi4xMzMsMTI1LjIyNyw3NS40MTdMMTI1LjIyNyw3OC43IiBpZD0iTC1taWNyb2h0dHAtbWljcm9odHRwLWhhbmRsZXItMCIgY2xhc3M9ImVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtbWljcm9odHRwIExFLW1pY3JvaHR0cC1oYW5kbGVyIiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLWVuZD0idXJsKCNteS1zdmdfZmxvd2NoYXJ0LXBvaW50RW5kKSIvPjwvZz48ZyBjbGFzcz0iZWRnZUxhYmVscyI+PGcgY2xhc3M9ImVkZ2VMYWJlbCI+PGcgY2xhc3M9ImxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAwKSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjAiIGhlaWdodD0iMCI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48L2c+PGcgY2xhc3M9Im5vZGVzIj48ZyBjbGFzcz0ibm9kZSBkZWZhdWx0IGRlZmF1bHQgZmxvd2NoYXJ0LWxhYmVsIiBpZD0iZmxvd2NoYXJ0LW1pY3JvaHR0cC0wIiBkYXRhLW5vZGU9InRydWUiIGRhdGEtaWQ9Im1pY3JvaHR0cCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTI1LjIyNjU2MjUsIDE3KSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjAiIHJ5PSIwIiB4PSItNjIuMDA3ODEyNSIgeT0iLTE3IiB3aWR0aD0iMTI0LjAxNTYyNSIgaGVpZ2h0PSIzNCIvPjxnIGNsYXNzPSJsYWJlbCIgc3R5bGU9IiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTU0LjUwNzgxMjUsIC05LjUpIj48cmVjdC8+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjEwOS4wMTU2MjUiIGhlaWdodD0iMTkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj5vcmcubWljcm9odHRwPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZ3JlZW4gZmxvd2NoYXJ0LWxhYmVsIiBpZD0iZmxvd2NoYXJ0LW1pY3JvaHR0cC1oYW5kbGVyLTEiIGRhdGEtbm9kZT0idHJ1ZSIgZGF0YS1pZD0ibWljcm9odHRwLWhhbmRsZXIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEyNS4yMjY1NjI1LCAxMDEpIj48cmVjdCBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIiBzdHlsZT0iIiByeD0iMCIgcnk9IjAiIHg9Ii0xMjUuMjI2NTYyNSIgeT0iLTE3IiB3aWR0aD0iMjUwLjQ1MzEyNSIgaGVpZ2h0PSIzNCIvPjxnIGNsYXNzPSJsYWJlbCIgc3R5bGU9IiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTExNy43MjY1NjI1LCAtOS41KSI+PHJlY3QvPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIyMzUuNDUzMTI1IiBoZWlnaHQ9IjE5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+ZGV2Lm1jY3VlLm1pY3JvaHR0cC5oYW5kbGVyPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjwvZz48L2c+PC9nPjwvc3ZnPg==" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>microhttp-handler</code> provides interfaces for making composable handlers for <code>microhttp</code>.</p>
<p>There are two interfaces in the module, <code>IntoResponse</code> and <code>Handler</code>.</p>
<p><code>IntoResponse</code> is something which can be converted into a <code>Response</code>. <code>Handler</code> is a function which takes a <code>Request</code> and returns something which implements <code>IntoResponse</code>.</p>
<p>There are also two implementations of <code>Handler</code> provided for convenience - <code>RouteHandler</code> and <code>DelegatingHandler</code>.</p>
<p><code>RouteHandler</code> checks the request's method and uri and returns <code>null</code> if it doesn't match a chosen method and regex.</p>
<p><code>DelegatingHandler</code> tries a list of handlers in order, returning the first non-null response or falling back to a default for when no match is found. Combined with <code>RouteHandler</code>, this can act as a very basic request router.</p>
<h2 id="why-use-it">Why use it</h2>
<p>A normal microhttp handler takes a <code>Request</code> and a <code>Consumer&lt;Response&gt;</code> that should be called later.</p>
<p>While this is fine, in the age of virtual threads there isn't much downside to modeling handlers as functions that takes <code>Request</code>s and return <code>Response</code>s and there are many upsides to doing so.</p>
<p>The programming model is simpler to compose, simpler to test, and it provides an opportunity to introduce concepts such as middleware and <code>IntoResponse</code></p>
<p><code>IntoResponse</code> is useful because making the normal <code>Response</code> record requires dealing with reason phrases, content-type headers, and body encoding. <code>IntoResponse</code> provides a seam for custom types to box up much of that logic.</p>
<h2 id="getting-started">Getting Started</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">EventLoop</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">Response</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">Header</span><span class="op">;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">handler</span><span class="op">.</span><span class="im">Handler</span><span class="op">;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">handler</span><span class="op">.</span><span class="im">RouteHandler</span><span class="op">;</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">handler</span><span class="op">.</span><span class="im">DelegatingHandler</span><span class="op">;</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">reasonphrase</span><span class="op">.</span><span class="im">ReasonPhrase</span><span class="op">;</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">List</span><span class="op">;</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">regex</span><span class="op">.</span><span class="im">Pattern</span><span class="op">;</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>record <span class="fu">TextResponse</span><span class="op">(</span><span class="dt">int</span> status<span class="op">,</span> <span class="bu">String</span> value<span class="op">)</span> </span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">implements</span> IntoResponse <span class="op">{</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">Response</span> <span class="fu">intoResponse</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="bu">Response</span><span class="op">(</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>                status<span class="op">,</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>                ReasonPhrase<span class="op">.</span><span class="fu">forStatus</span><span class="op">(</span>status<span class="op">),</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>                <span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="kw">new</span> <span class="fu">Header</span><span class="op">(</span><span class="st">&quot;Content-Type&quot;</span><span class="op">,</span> <span class="st">&quot;text/plain&quot;</span><span class="op">)),</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>                value<span class="op">.</span><span class="fu">getBytes</span><span class="op">()</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="kw">throws</span> <span class="bu">Exception</span> <span class="op">{</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Handler</span> index <span class="op">=</span> RouteHandler<span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;GET&quot;</span><span class="op">,</span> </span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Pattern</span><span class="op">.</span><span class="fu">compile</span><span class="op">(</span><span class="st">&quot;/&quot;</span><span class="op">),</span> </span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a>            request <span class="op">-&gt;</span> <span class="kw">new</span> <span class="fu">TextResponse</span><span class="op">(</span><span class="dv">200</span><span class="op">,</span> <span class="st">&quot;Hello, world&quot;</span><span class="op">)</span></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Handler</span> rootHandler <span class="op">=</span> <span class="kw">new</span> <span class="fu">DelegatingHandler</span><span class="op">(</span></span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a>            <span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>index<span class="op">),</span></span>
<span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="fu">TextResponse</span><span class="op">(</span><span class="dv">404</span><span class="op">,</span> <span class="st">&quot;Not Found&quot;</span><span class="op">)</span></span>
<span id="cb1-37"><a href="#cb1-37" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb1-38"><a href="#cb1-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-39"><a href="#cb1-39" aria-hidden="true" tabindex="-1"></a>    var error <span class="op">=</span> <span class="kw">new</span> <span class="fu">TextResponse</span><span class="op">(</span><span class="dv">500</span><span class="op">,</span> <span class="st">&quot;Internal Error&quot;</span><span class="op">);</span></span>
<span id="cb1-40"><a href="#cb1-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-41"><a href="#cb1-41" aria-hidden="true" tabindex="-1"></a>    var eventLoop <span class="op">=</span> <span class="kw">new</span> <span class="fu">EventLoop</span><span class="op">((</span>request<span class="op">,</span> callback<span class="op">)</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb1-42"><a href="#cb1-42" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Thread</span><span class="op">.</span><span class="fu">startVirtualThread</span><span class="op">(()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb1-43"><a href="#cb1-43" aria-hidden="true" tabindex="-1"></a>            <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb1-44"><a href="#cb1-44" aria-hidden="true" tabindex="-1"></a>                callback<span class="op">.</span><span class="fu">accept</span><span class="op">(</span></span>
<span id="cb1-45"><a href="#cb1-45" aria-hidden="true" tabindex="-1"></a>                        rootHandler<span class="op">.</span><span class="fu">handle</span><span class="op">(</span>request<span class="op">)</span></span>
<span id="cb1-46"><a href="#cb1-46" aria-hidden="true" tabindex="-1"></a>                                <span class="op">.</span><span class="fu">intoResponse</span><span class="op">()</span></span>
<span id="cb1-47"><a href="#cb1-47" aria-hidden="true" tabindex="-1"></a>                <span class="op">);</span></span>
<span id="cb1-48"><a href="#cb1-48" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span><span class="bu">Exception</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-49"><a href="#cb1-49" aria-hidden="true" tabindex="-1"></a>                callback<span class="op">.</span><span class="fu">accept</span><span class="op">(</span>error<span class="op">.</span><span class="fu">intoResponse</span><span class="op">());</span></span>
<span id="cb1-50"><a href="#cb1-50" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb1-51"><a href="#cb1-51" aria-hidden="true" tabindex="-1"></a>        <span class="op">});</span></span>
<span id="cb1-52"><a href="#cb1-52" aria-hidden="true" tabindex="-1"></a>    <span class="op">});</span></span>
<span id="cb1-53"><a href="#cb1-53" aria-hidden="true" tabindex="-1"></a>    eventLoop<span class="op">.</span><span class="fu">start</span><span class="op">();</span></span>
<span id="cb1-54"><a href="#cb1-54" aria-hidden="true" tabindex="-1"></a>    eventLoop<span class="op">.</span><span class="fu">join</span><span class="op">();</span></span>
<span id="cb1-55"><a href="#cb1-55" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>org.pcollections</title><link>https://mccue.dev/pages/12-5-23-java-library-of-the-day-5</link><description></description><pubDate>Tue, 05 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>org.pcollections</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">org.pcollections</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/org.pcollections/pcollections"><code>org.pcollections/pcollections</code></a></li>
<li>Module Name: <code>org.pcollections</code></li>
<li>GitHub: <a href="https://github.com/hrldcpr/pcollections"><code>hrldcpr/pcollections</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogMTU3LjU5NHB4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii04IC04IDE1Ny41OTM3NSA1MCIgcm9sZT0iZ3JhcGhpY3MtZG9jdW1lbnQgZG9jdW1lbnQiIGFyaWEtcm9sZWRlc2NyaXB0aW9uPSJmbG93Y2hhcnQtdjIiPjxzdHlsZT4jbXktc3Zne2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtmb250LXNpemU6MTZweDtmaWxsOiMzMzM7fSNteS1zdmcgLmVycm9yLWljb257ZmlsbDojNTUyMjIyO30jbXktc3ZnIC5lcnJvci10ZXh0e2ZpbGw6IzU1MjIyMjtzdHJva2U6IzU1MjIyMjt9I215LXN2ZyAuZWRnZS10aGlja25lc3Mtbm9ybWFse3N0cm9rZS13aWR0aDoycHg7fSNteS1zdmcgLmVkZ2UtdGhpY2tuZXNzLXRoaWNre3N0cm9rZS13aWR0aDozLjVweDt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLXNvbGlke3N0cm9rZS1kYXNoYXJyYXk6MDt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLWRhc2hlZHtzdHJva2UtZGFzaGFycmF5OjM7fSNteS1zdmcgLmVkZ2UtcGF0dGVybi1kb3R0ZWR7c3Ryb2tlLWRhc2hhcnJheToyO30jbXktc3ZnIC5tYXJrZXJ7ZmlsbDojMzMzMzMzO3N0cm9rZTojMzMzMzMzO30jbXktc3ZnIC5tYXJrZXIuY3Jvc3N7c3Ryb2tlOiMzMzMzMzM7fSNteS1zdmcgc3Zne2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtmb250LXNpemU6MTZweDt9I215LXN2ZyAubGFiZWx7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2NvbG9yOiMzMzM7fSNteS1zdmcgLmNsdXN0ZXItbGFiZWwgdGV4dHtmaWxsOiMzMzM7fSNteS1zdmcgLmNsdXN0ZXItbGFiZWwgc3BhbiwjbXktc3ZnIHB7Y29sb3I6IzMzMzt9I215LXN2ZyAubGFiZWwgdGV4dCwjbXktc3ZnIHNwYW4sI215LXN2ZyBwe2ZpbGw6IzMzMztjb2xvcjojMzMzO30jbXktc3ZnIC5ub2RlIHJlY3QsI215LXN2ZyAubm9kZSBjaXJjbGUsI215LXN2ZyAubm9kZSBlbGxpcHNlLCNteS1zdmcgLm5vZGUgcG9seWdvbiwjbXktc3ZnIC5ub2RlIHBhdGh7ZmlsbDojRUNFQ0ZGO3N0cm9rZTojOTM3MERCO3N0cm9rZS13aWR0aDoxcHg7fSNteS1zdmcgLmZsb3djaGFydC1sYWJlbCB0ZXh0e3RleHQtYW5jaG9yOm1pZGRsZTt9I215LXN2ZyAubm9kZSAua2F0ZXggcGF0aHtmaWxsOiMwMDA7c3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAubm9kZSAubGFiZWx7dGV4dC1hbGlnbjpjZW50ZXI7fSNteS1zdmcgLm5vZGUuY2xpY2thYmxle2N1cnNvcjpwb2ludGVyO30jbXktc3ZnIC5hcnJvd2hlYWRQYXRoe2ZpbGw6IzMzMzMzMzt9I215LXN2ZyAuZWRnZVBhdGggLnBhdGh7c3Ryb2tlOiMzMzMzMzM7c3Ryb2tlLXdpZHRoOjIuMHB4O30jbXktc3ZnIC5mbG93Y2hhcnQtbGlua3tzdHJva2U6IzMzMzMzMztmaWxsOm5vbmU7fSNteS1zdmcgLmVkZ2VMYWJlbHtiYWNrZ3JvdW5kLWNvbG9yOiNlOGU4ZTg7dGV4dC1hbGlnbjpjZW50ZXI7fSNteS1zdmcgLmVkZ2VMYWJlbCByZWN0e29wYWNpdHk6MC41O2JhY2tncm91bmQtY29sb3I6I2U4ZThlODtmaWxsOiNlOGU4ZTg7fSNteS1zdmcgLmxhYmVsQmtne2JhY2tncm91bmQtY29sb3I6cmdiYSgyMzIsIDIzMiwgMjMyLCAwLjUpO30jbXktc3ZnIC5jbHVzdGVyIHJlY3R7ZmlsbDojZmZmZmRlO3N0cm9rZTojYWFhYTMzO3N0cm9rZS13aWR0aDoxcHg7fSNteS1zdmcgLmNsdXN0ZXIgdGV4dHtmaWxsOiMzMzM7fSNteS1zdmcgLmNsdXN0ZXIgc3BhbiwjbXktc3ZnIHB7Y29sb3I6IzMzMzt9I215LXN2ZyBkaXYubWVybWFpZFRvb2x0aXB7cG9zaXRpb246YWJzb2x1dGU7dGV4dC1hbGlnbjpjZW50ZXI7bWF4LXdpZHRoOjIwMHB4O3BhZGRpbmc6MnB4O2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtmb250LXNpemU6MTJweDtiYWNrZ3JvdW5kOmhzbCg4MCwgMTAwJSwgOTYuMjc0NTA5ODAzOSUpO2JvcmRlcjoxcHggc29saWQgI2FhYWEzMztib3JkZXItcmFkaXVzOjJweDtwb2ludGVyLWV2ZW50czpub25lO3otaW5kZXg6MTAwO30jbXktc3ZnIC5mbG93Y2hhcnRUaXRsZVRleHR7dGV4dC1hbmNob3I6bWlkZGxlO2ZvbnQtc2l6ZToxOHB4O2ZpbGw6IzMzMzt9I215LXN2ZyA6cm9vdHstLW1lcm1haWQtZm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO30jbXktc3ZnIC5ncmVlbiZndDsqe3N0cm9rZTpyZ2IoMjU1LCAwLCAwKSFpbXBvcnRhbnQ7fSNteS1zdmcgLmdyZWVuIHNwYW57c3Ryb2tlOnJnYigyNTUsIDAsIDApIWltcG9ydGFudDt9PC9zdHlsZT48Zz48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LXBvaW50RW5kIiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI2IiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMiIgbWFya2VySGVpZ2h0PSIxMiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDAgMCBMIDEwIDUgTCAwIDEwIHoiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1wb2ludFN0YXJ0IiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI0LjUiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjEyIiBtYXJrZXJIZWlnaHQ9IjEyIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMCA1IEwgMTAgMTAgTCAxMCAwIHoiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jaXJjbGVFbmQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjExIiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48Y2lyY2xlIGN4PSI1IiBjeT0iNSIgcj0iNSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNpcmNsZVN0YXJ0IiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSItMSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PGNpcmNsZSBjeD0iNSIgY3k9IjUiIHI9IjUiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jcm9zc0VuZCIgY2xhc3M9Im1hcmtlciBjcm9zcyBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMSAxMSIgcmVmWD0iMTIiIHJlZlk9IjUuMiIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAxLDEgbCA5LDkgTSAxMCwxIGwgLTksOSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMjsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNyb3NzU3RhcnQiIGNsYXNzPSJtYXJrZXIgY3Jvc3MgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTEgMTEiIHJlZlg9Ii0xIiByZWZZPSI1LjIiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMSwxIGwgOSw5IE0gMTAsMSBsIC05LDkiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDI7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PGcgY2xhc3M9InJvb3QiPjxnIGNsYXNzPSJjbHVzdGVycyIvPjxnIGNsYXNzPSJlZGdlUGF0aHMiLz48ZyBjbGFzcz0iZWRnZUxhYmVscyIvPjxnIGNsYXNzPSJub2RlcyI+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBncmVlbiBmbG93Y2hhcnQtbGFiZWwiIGlkPSJmbG93Y2hhcnQtcGNvbGxlY3Rpb25zLTAiIGRhdGEtbm9kZT0idHJ1ZSIgZGF0YS1pZD0icGNvbGxlY3Rpb25zIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg3MC43OTY4NzUsIDE3KSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjAiIHJ5PSIwIiB4PSItNzAuNzk2ODc1IiB5PSItMTciIHdpZHRoPSIxNDEuNTkzNzUiIGhlaWdodD0iMzQiLz48ZyBjbGFzcz0ibGFiZWwiIHN0eWxlPSIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC02My4yOTY4NzUsIC05LjUpIj48cmVjdC8+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjEyNi41OTM3NSIgaGVpZ2h0PSIxOSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPm9yZy5wY29sbGVjdGlvbnM8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjwvZz48L2c+PC9zdmc+" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>pcollections</code> provides <a href="https://en.wikipedia.org/wiki/Persistent_data_structure">Persistent Immutable Collections</a>.</p>
<p>These are collections which cannot be modified, but use structural sharing to make creating updated versions of themselves efficient.</p>
<h2 id="why-use-it">Why use it</h2>
<p>Persistent collections are useful when you want a data aggregate that is immutable but will require multiple updates over the runtime of the program.</p>
<p><code>pcollections</code> is unique in the ecosystem of persistent collection libraries in that its types directly extend the <a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/doc-files/coll-index.html">Java Collections Framework</a>. Its <code>PVector</code> is a subtype of <code>java.util.List</code>, its <code>PMap</code> is a subtype of <code>java.util.Map</code>, and so on.</p>
<p>There are definite cons to that - having a <code>remove</code> method that does nothing is unideal - but there are also pros. There is no conversion cost when interacting with the numerous APIs that expect <code>java.util.*</code> types.</p>
<h2 id="getting-started">Getting Started</h2>
<h3 id="basic-usage">Basic Usage</h3>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">pcollections</span><span class="op">.</span><span class="im">PVector</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">pcollections</span><span class="op">.</span><span class="im">TreePVector</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    var names <span class="op">=</span> TreePVector<span class="op">.</span><span class="fu">empty</span><span class="op">();</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    var names2 <span class="op">=</span> names<span class="op">.</span><span class="fu">plus</span><span class="op">(</span><span class="st">&quot;Mumenstallu&quot;</span><span class="op">);</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    var names3 <span class="op">=</span> names2<span class="op">.</span><span class="fu">plus</span><span class="op">(</span><span class="st">&quot;Snufkin&quot;</span><span class="op">);</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>names<span class="op">);</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>names2<span class="op">);</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>names3<span class="op">);</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="many-updated-versions">Many updated versions</h3>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">pcollections</span><span class="op">.</span><span class="im">PVector</span><span class="op">;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">pcollections</span><span class="op">.</span><span class="im">TreePVector</span><span class="op">;</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    PVector<span class="op">&lt;</span>PVector<span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;&gt;</span> allVersions <span class="op">=</span> TreePVector<span class="op">.</span><span class="fu">empty</span><span class="op">();</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>    PVector<span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;</span> numbers <span class="op">=</span> TreePVector<span class="op">.</span><span class="fu">empty</span><span class="op">();</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">10000</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>        numbers <span class="op">=</span> numbers<span class="op">.</span><span class="fu">plus</span><span class="op">(</span>i<span class="op">);</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>        allVersions <span class="op">=</span> allVersions<span class="op">.</span><span class="fu">plus</span><span class="op">(</span>numbers<span class="op">);</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>allVersions<span class="op">.</span><span class="fu">size</span><span class="op">());</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Every version is still valid</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>allVersions<span class="op">.</span><span class="fu">get</span><span class="op">(</span><span class="dv">2</span><span class="op">));</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>allVersions<span class="op">.</span><span class="fu">get</span><span class="op">(</span><span class="dv">4</span><span class="op">));</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>allVersions<span class="op">.</span><span class="fu">get</span><span class="op">(</span><span class="dv">100</span><span class="op">));</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> total <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> n <span class="op">:</span> numbers<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a>        total <span class="op">+=</span> n<span class="op">;</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>total<span class="op">);</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>com.uwyn.urlencoder</title><link>https://mccue.dev/pages/12-4-23-java-library-of-the-day-4</link><description></description><pubDate>Mon, 04 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>com.uwyn.urlencoder</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">com.uwyn.urlencoder</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/dev.mccue/urlparameters"><code>dev.mccue/urlparameters</code></a></li>
<li>Module Name: <code>dev.mccue.urlparameters</code></li>
<li>GitHub: <a href="https://github.com/bowbahdoe/urlparameters"><code>bowbahdoe/urlparameters</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogMjM2LjUzMXB4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii04IC04IDIzNi41MzEyNSAxMzQiIHJvbGU9ImdyYXBoaWNzLWRvY3VtZW50IGRvY3VtZW50IiBhcmlhLXJvbGVkZXNjcmlwdGlvbj0iZmxvd2NoYXJ0LXYyIj48c3R5bGU+I215LXN2Z3tmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjE2cHg7ZmlsbDojMzMzO30jbXktc3ZnIC5lcnJvci1pY29ue2ZpbGw6IzU1MjIyMjt9I215LXN2ZyAuZXJyb3ItdGV4dHtmaWxsOiM1NTIyMjI7c3Ryb2tlOiM1NTIyMjI7fSNteS1zdmcgLmVkZ2UtdGhpY2tuZXNzLW5vcm1hbHtzdHJva2Utd2lkdGg6MnB4O30jbXktc3ZnIC5lZGdlLXRoaWNrbmVzcy10aGlja3tzdHJva2Utd2lkdGg6My41cHg7fSNteS1zdmcgLmVkZ2UtcGF0dGVybi1zb2xpZHtzdHJva2UtZGFzaGFycmF5OjA7fSNteS1zdmcgLmVkZ2UtcGF0dGVybi1kYXNoZWR7c3Ryb2tlLWRhc2hhcnJheTozO30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tZG90dGVke3N0cm9rZS1kYXNoYXJyYXk6Mjt9I215LXN2ZyAubWFya2Vye2ZpbGw6IzMzMzMzMztzdHJva2U6IzMzMzMzMzt9I215LXN2ZyAubWFya2VyLmNyb3Nze3N0cm9rZTojMzMzMzMzO30jbXktc3ZnIHN2Z3tmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjE2cHg7fSNteS1zdmcgLmxhYmVse2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtjb2xvcjojMzMzO30jbXktc3ZnIC5jbHVzdGVyLWxhYmVsIHRleHR7ZmlsbDojMzMzO30jbXktc3ZnIC5jbHVzdGVyLWxhYmVsIHNwYW4sI215LXN2ZyBwe2NvbG9yOiMzMzM7fSNteS1zdmcgLmxhYmVsIHRleHQsI215LXN2ZyBzcGFuLCNteS1zdmcgcHtmaWxsOiMzMzM7Y29sb3I6IzMzMzt9I215LXN2ZyAubm9kZSByZWN0LCNteS1zdmcgLm5vZGUgY2lyY2xlLCNteS1zdmcgLm5vZGUgZWxsaXBzZSwjbXktc3ZnIC5ub2RlIHBvbHlnb24sI215LXN2ZyAubm9kZSBwYXRoe2ZpbGw6I0VDRUNGRjtzdHJva2U6IzkzNzBEQjtzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5mbG93Y2hhcnQtbGFiZWwgdGV4dHt0ZXh0LWFuY2hvcjptaWRkbGU7fSNteS1zdmcgLm5vZGUgLmthdGV4IHBhdGh7ZmlsbDojMDAwO3N0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxcHg7fSNteS1zdmcgLm5vZGUgLmxhYmVse3RleHQtYWxpZ246Y2VudGVyO30jbXktc3ZnIC5ub2RlLmNsaWNrYWJsZXtjdXJzb3I6cG9pbnRlcjt9I215LXN2ZyAuYXJyb3doZWFkUGF0aHtmaWxsOiMzMzMzMzM7fSNteS1zdmcgLmVkZ2VQYXRoIC5wYXRoe3N0cm9rZTojMzMzMzMzO3N0cm9rZS13aWR0aDoyLjBweDt9I215LXN2ZyAuZmxvd2NoYXJ0LWxpbmt7c3Ryb2tlOiMzMzMzMzM7ZmlsbDpub25lO30jbXktc3ZnIC5lZGdlTGFiZWx7YmFja2dyb3VuZC1jb2xvcjojZThlOGU4O3RleHQtYWxpZ246Y2VudGVyO30jbXktc3ZnIC5lZGdlTGFiZWwgcmVjdHtvcGFjaXR5OjAuNTtiYWNrZ3JvdW5kLWNvbG9yOiNlOGU4ZTg7ZmlsbDojZThlOGU4O30jbXktc3ZnIC5sYWJlbEJrZ3tiYWNrZ3JvdW5kLWNvbG9yOnJnYmEoMjMyLCAyMzIsIDIzMiwgMC41KTt9I215LXN2ZyAuY2x1c3RlciByZWN0e2ZpbGw6I2ZmZmZkZTtzdHJva2U6I2FhYWEzMztzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5jbHVzdGVyIHRleHR7ZmlsbDojMzMzO30jbXktc3ZnIC5jbHVzdGVyIHNwYW4sI215LXN2ZyBwe2NvbG9yOiMzMzM7fSNteS1zdmcgZGl2Lm1lcm1haWRUb29sdGlwe3Bvc2l0aW9uOmFic29sdXRlO3RleHQtYWxpZ246Y2VudGVyO21heC13aWR0aDoyMDBweDtwYWRkaW5nOjJweDtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjEycHg7YmFja2dyb3VuZDpoc2woODAsIDEwMCUsIDk2LjI3NDUwOTgwMzklKTtib3JkZXI6MXB4IHNvbGlkICNhYWFhMzM7Ym9yZGVyLXJhZGl1czoycHg7cG9pbnRlci1ldmVudHM6bm9uZTt6LWluZGV4OjEwMDt9I215LXN2ZyAuZmxvd2NoYXJ0VGl0bGVUZXh0e3RleHQtYW5jaG9yOm1pZGRsZTtmb250LXNpemU6MThweDtmaWxsOiMzMzM7fSNteS1zdmcgOnJvb3R7LS1tZXJtYWlkLWZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjt9I215LXN2ZyAuZ3JlZW4mZ3Q7KntzdHJva2U6cmdiKDI1NSwgMCwgMCkhaW1wb3J0YW50O30jbXktc3ZnIC5ncmVlbiBzcGFue3N0cm9rZTpyZ2IoMjU1LCAwLCAwKSFpbXBvcnRhbnQ7fTwvc3R5bGU+PGc+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1wb2ludEVuZCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iNiIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTIiIG1hcmtlckhlaWdodD0iMTIiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAwIDAgTCAxMCA1IEwgMCAxMCB6IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtcG9pbnRTdGFydCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iNC41IiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMiIgbWFya2VySGVpZ2h0PSIxMiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDAgNSBMIDEwIDEwIEwgMTAgMCB6IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY2lyY2xlRW5kIiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSIxMSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PGNpcmNsZSBjeD0iNSIgY3k9IjUiIHI9IjUiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jaXJjbGVTdGFydCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iLTEiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxjaXJjbGUgY3g9IjUiIGN5PSI1IiByPSI1IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY3Jvc3NFbmQiIGNsYXNzPSJtYXJrZXIgY3Jvc3MgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTEgMTEiIHJlZlg9IjEyIiByZWZZPSI1LjIiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMSwxIGwgOSw5IE0gMTAsMSBsIC05LDkiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDI7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jcm9zc1N0YXJ0IiBjbGFzcz0ibWFya2VyIGNyb3NzIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDExIDExIiByZWZYPSItMSIgcmVmWT0iNS4yIiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDEsMSBsIDksOSBNIDEwLDEgbCAtOSw5IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAyOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxnIGNsYXNzPSJyb290Ij48ZyBjbGFzcz0iY2x1c3RlcnMiLz48ZyBjbGFzcz0iZWRnZVBhdGhzIj48cGF0aCBkPSJNMTEwLjI2NiwzNEwxMTAuMjY2LDM4LjE2N0MxMTAuMjY2LDQyLjMzMywxMTAuMjY2LDUwLjY2NywxMTAuMjY2LDU4LjExN0MxMTAuMjY2LDY1LjU2NywxMTAuMjY2LDcyLjEzMywxMTAuMjY2LDc1LjQxN0wxMTAuMjY2LDc4LjciIGlkPSJMLXVybGVuY29kZXItdXJscGFyYW1ldGVycy0wIiBjbGFzcz0iZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy11cmxlbmNvZGVyIExFLXVybHBhcmFtZXRlcnMiIHN0eWxlPSJmaWxsOm5vbmU7IiBtYXJrZXItZW5kPSJ1cmwoI215LXN2Z19mbG93Y2hhcnQtcG9pbnRFbmQpIi8+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWxzIj48ZyBjbGFzcz0iZWRnZUxhYmVsIj48ZyBjbGFzcz0ibGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsIDApIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMCIgaGVpZ2h0PSIwIj48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9ImVkZ2VMYWJlbCI+PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjwvZz48ZyBjbGFzcz0ibm9kZXMiPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZGVmYXVsdCBmbG93Y2hhcnQtbGFiZWwiIGlkPSJmbG93Y2hhcnQtdXJsZW5jb2Rlci0wIiBkYXRhLW5vZGU9InRydWUiIGRhdGEtaWQ9InVybGVuY29kZXIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDExMC4yNjU2MjUsIDE3KSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjAiIHJ5PSIwIiB4PSItOTQuMjUiIHk9Ii0xNyIgd2lkdGg9IjE4OC41IiBoZWlnaHQ9IjM0Ii8+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtODYuNzUsIC05LjUpIj48cmVjdC8+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjE3My41IiBoZWlnaHQ9IjE5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+Y29tLnV3eW4udXJsZW5jb2Rlcjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0ibm9kZSBkZWZhdWx0IGdyZWVuIGZsb3djaGFydC1sYWJlbCIgaWQ9ImZsb3djaGFydC11cmxwYXJhbWV0ZXJzLTEiIGRhdGEtbm9kZT0idHJ1ZSIgZGF0YS1pZD0idXJscGFyYW1ldGVycyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTEwLjI2NTYyNSwgMTAxKSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjAiIHJ5PSIwIiB4PSItMTEwLjI2NTYyNSIgeT0iLTE3IiB3aWR0aD0iMjIwLjUzMTI1IiBoZWlnaHQ9IjM0Ii8+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTAyLjc2NTYyNSwgLTkuNSkiPjxyZWN0Lz48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMjA1LjUzMTI1IiBoZWlnaHQ9IjE5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+ZGV2Lm1jY3VlLnVybHBhcmFtZXRlcnM8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjwvZz48L2c+PC9zdmc+" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>urlparameters</code> provides the logic needed to read and write "URL parameters."</p>
<p>This covers both query parameters, often seen at the end of a URL (<code>google.com?q=apples&amp;track_id=123</code>), and the bodies of html form submissions (<code>name=bob&amp;age=98</code>).</p>
<p>It uses <code>com.uwyn.urlencoder</code> to properly encode parameters for both situations.</p>
<h2 id="why-use-it">Why use it</h2>
<p>Most websites eventually encode some information as query parameters inside a URL. <code>urlparameters</code> lets you extract that information as well as produce such URLs.</p>
<p>It is also common for websites to accept information from a user via a form submission - more so if you server-side render HTML. Processing those form submissions means parsing those request bodies.</p>
<h2 id="getting-started">Getting Started</h2>
<h3 id="parse-query-params-from-a-url">Parse Query Params from a URL</h3>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">net</span><span class="op">.</span><span class="im">URI</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">urlparameters</span><span class="op">.</span><span class="im">UrlParameters</span><span class="op">;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>   var url <span class="op">=</span> <span class="bu">URI</span><span class="op">.</span><span class="fu">create</span><span class="op">(</span><span class="st">&quot;https://google.com?q=pear&quot;</span><span class="op">);</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>   var params <span class="op">=</span> UrlParameters<span class="op">.</span><span class="fu">parse</span><span class="op">(</span>url<span class="op">);</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>   </span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>   <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>params<span class="op">.</span><span class="fu">firstValue</span><span class="op">(</span><span class="st">&quot;q&quot;</span><span class="op">).</span><span class="fu">orElseThrow</span><span class="op">());</span>    </span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>(<a href="https://java-playground.com/?runtime=latest&amp;release=21&amp;preview=enabled&amp;gist=2271404ce30f6b9f029637a3f17667bd">Playground Link</a>)</p>
<h3 id="parse-form-submission-bodies">Parse Form Submission bodies</h3>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">urlparameters</span><span class="op">.</span><span class="im">UrlParameters</span><span class="op">;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>   var body <span class="op">=</span> <span class="st">&quot;name=jack&amp;title=squire&quot;</span><span class="op">;</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>   var params <span class="op">=</span> UrlParameters<span class="op">.</span><span class="fu">parse</span><span class="op">(</span>body<span class="op">);</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>   </span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>   <span class="co">// squire</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>   <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>params<span class="op">.</span><span class="fu">firstValue</span><span class="op">(</span><span class="st">&quot;title&quot;</span><span class="op">).</span><span class="fu">orElseThrow</span><span class="op">());</span>    </span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="generate-a-url-with-query-params">Generate a URL with Query Params</h3>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">List</span><span class="op">;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">net</span><span class="op">.</span><span class="im">URI</span><span class="op">;</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">urlparameters</span><span class="op">.</span><span class="im">UrlParameters</span><span class="op">;</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">urlparameters</span><span class="op">.</span><span class="im">UrlParameter</span><span class="op">;</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>   var params <span class="op">=</span> <span class="kw">new</span> <span class="fu">UrlParameters</span><span class="op">(</span><span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>       <span class="kw">new</span> <span class="fu">UrlParameter</span><span class="op">(</span><span class="st">&quot;pokemon&quot;</span><span class="op">,</span> <span class="st">&quot;stantler&quot;</span><span class="op">),</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>       <span class="kw">new</span> <span class="fu">UrlParameter</span><span class="op">(</span><span class="st">&quot;caught_in&quot;</span><span class="op">,</span> <span class="st">&quot;Pokemon Colosseum&quot;</span><span class="op">)</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>   <span class="op">));</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>   </span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>   var url <span class="op">=</span> <span class="bu">URI</span><span class="op">.</span><span class="fu">create</span><span class="op">(</span><span class="st">&quot;https://example.com?&quot;</span> <span class="op">+</span> params<span class="op">);</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>   </span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>   <span class="co">// https://example.com?pokemon=stantler&amp;caught_in=Pokemon%20Colosseum</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>   <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>url<span class="op">);</span>    </span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>com.uwyn.urlencoder</title><link>https://mccue.dev/pages/12-3-23-java-library-of-the-day-3</link><description></description><pubDate>Sun, 03 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>com.uwyn.urlencoder</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">com.uwyn.urlencoder</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/com.uwyn/urlencoder"><code>com.uwyn/urlencoder</code></a></li>
<li>Module Name: <code>com.uwyn.urlencoder</code></li>
<li>GitHub: <a href="https://github.com/gbevin/urlencoder"><code>gbevin/urlencoder</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogMjA0LjVweDsgYmFja2dyb3VuZC1jb2xvcjogd2hpdGU7IiB2aWV3Qm94PSItOCAtOCAyMDQuNSA1MCIgcm9sZT0iZ3JhcGhpY3MtZG9jdW1lbnQgZG9jdW1lbnQiIGFyaWEtcm9sZWRlc2NyaXB0aW9uPSJmbG93Y2hhcnQtdjIiPjxzdHlsZT4jbXktc3Zne2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtmb250LXNpemU6MTZweDtmaWxsOiMzMzM7fSNteS1zdmcgLmVycm9yLWljb257ZmlsbDojNTUyMjIyO30jbXktc3ZnIC5lcnJvci10ZXh0e2ZpbGw6IzU1MjIyMjtzdHJva2U6IzU1MjIyMjt9I215LXN2ZyAuZWRnZS10aGlja25lc3Mtbm9ybWFse3N0cm9rZS13aWR0aDoycHg7fSNteS1zdmcgLmVkZ2UtdGhpY2tuZXNzLXRoaWNre3N0cm9rZS13aWR0aDozLjVweDt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLXNvbGlke3N0cm9rZS1kYXNoYXJyYXk6MDt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLWRhc2hlZHtzdHJva2UtZGFzaGFycmF5OjM7fSNteS1zdmcgLmVkZ2UtcGF0dGVybi1kb3R0ZWR7c3Ryb2tlLWRhc2hhcnJheToyO30jbXktc3ZnIC5tYXJrZXJ7ZmlsbDojMzMzMzMzO3N0cm9rZTojMzMzMzMzO30jbXktc3ZnIC5tYXJrZXIuY3Jvc3N7c3Ryb2tlOiMzMzMzMzM7fSNteS1zdmcgc3Zne2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtmb250LXNpemU6MTZweDt9I215LXN2ZyAubGFiZWx7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2NvbG9yOiMzMzM7fSNteS1zdmcgLmNsdXN0ZXItbGFiZWwgdGV4dHtmaWxsOiMzMzM7fSNteS1zdmcgLmNsdXN0ZXItbGFiZWwgc3BhbiwjbXktc3ZnIHB7Y29sb3I6IzMzMzt9I215LXN2ZyAubGFiZWwgdGV4dCwjbXktc3ZnIHNwYW4sI215LXN2ZyBwe2ZpbGw6IzMzMztjb2xvcjojMzMzO30jbXktc3ZnIC5ub2RlIHJlY3QsI215LXN2ZyAubm9kZSBjaXJjbGUsI215LXN2ZyAubm9kZSBlbGxpcHNlLCNteS1zdmcgLm5vZGUgcG9seWdvbiwjbXktc3ZnIC5ub2RlIHBhdGh7ZmlsbDojRUNFQ0ZGO3N0cm9rZTojOTM3MERCO3N0cm9rZS13aWR0aDoxcHg7fSNteS1zdmcgLmZsb3djaGFydC1sYWJlbCB0ZXh0e3RleHQtYW5jaG9yOm1pZGRsZTt9I215LXN2ZyAubm9kZSAua2F0ZXggcGF0aHtmaWxsOiMwMDA7c3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAubm9kZSAubGFiZWx7dGV4dC1hbGlnbjpjZW50ZXI7fSNteS1zdmcgLm5vZGUuY2xpY2thYmxle2N1cnNvcjpwb2ludGVyO30jbXktc3ZnIC5hcnJvd2hlYWRQYXRoe2ZpbGw6IzMzMzMzMzt9I215LXN2ZyAuZWRnZVBhdGggLnBhdGh7c3Ryb2tlOiMzMzMzMzM7c3Ryb2tlLXdpZHRoOjIuMHB4O30jbXktc3ZnIC5mbG93Y2hhcnQtbGlua3tzdHJva2U6IzMzMzMzMztmaWxsOm5vbmU7fSNteS1zdmcgLmVkZ2VMYWJlbHtiYWNrZ3JvdW5kLWNvbG9yOiNlOGU4ZTg7dGV4dC1hbGlnbjpjZW50ZXI7fSNteS1zdmcgLmVkZ2VMYWJlbCByZWN0e29wYWNpdHk6MC41O2JhY2tncm91bmQtY29sb3I6I2U4ZThlODtmaWxsOiNlOGU4ZTg7fSNteS1zdmcgLmxhYmVsQmtne2JhY2tncm91bmQtY29sb3I6cmdiYSgyMzIsIDIzMiwgMjMyLCAwLjUpO30jbXktc3ZnIC5jbHVzdGVyIHJlY3R7ZmlsbDojZmZmZmRlO3N0cm9rZTojYWFhYTMzO3N0cm9rZS13aWR0aDoxcHg7fSNteS1zdmcgLmNsdXN0ZXIgdGV4dHtmaWxsOiMzMzM7fSNteS1zdmcgLmNsdXN0ZXIgc3BhbiwjbXktc3ZnIHB7Y29sb3I6IzMzMzt9I215LXN2ZyBkaXYubWVybWFpZFRvb2x0aXB7cG9zaXRpb246YWJzb2x1dGU7dGV4dC1hbGlnbjpjZW50ZXI7bWF4LXdpZHRoOjIwMHB4O3BhZGRpbmc6MnB4O2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtmb250LXNpemU6MTJweDtiYWNrZ3JvdW5kOmhzbCg4MCwgMTAwJSwgOTYuMjc0NTA5ODAzOSUpO2JvcmRlcjoxcHggc29saWQgI2FhYWEzMztib3JkZXItcmFkaXVzOjJweDtwb2ludGVyLWV2ZW50czpub25lO3otaW5kZXg6MTAwO30jbXktc3ZnIC5mbG93Y2hhcnRUaXRsZVRleHR7dGV4dC1hbmNob3I6bWlkZGxlO2ZvbnQtc2l6ZToxOHB4O2ZpbGw6IzMzMzt9I215LXN2ZyA6cm9vdHstLW1lcm1haWQtZm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO30jbXktc3ZnIC5ncmVlbiZndDsqe3N0cm9rZTpyZ2IoMjU1LCAwLCAwKSFpbXBvcnRhbnQ7fSNteS1zdmcgLmdyZWVuIHNwYW57c3Ryb2tlOnJnYigyNTUsIDAsIDApIWltcG9ydGFudDt9PC9zdHlsZT48Zz48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LXBvaW50RW5kIiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI2IiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMiIgbWFya2VySGVpZ2h0PSIxMiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDAgMCBMIDEwIDUgTCAwIDEwIHoiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1wb2ludFN0YXJ0IiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI0LjUiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjEyIiBtYXJrZXJIZWlnaHQ9IjEyIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMCA1IEwgMTAgMTAgTCAxMCAwIHoiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jaXJjbGVFbmQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjExIiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48Y2lyY2xlIGN4PSI1IiBjeT0iNSIgcj0iNSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNpcmNsZVN0YXJ0IiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSItMSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PGNpcmNsZSBjeD0iNSIgY3k9IjUiIHI9IjUiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jcm9zc0VuZCIgY2xhc3M9Im1hcmtlciBjcm9zcyBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMSAxMSIgcmVmWD0iMTIiIHJlZlk9IjUuMiIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAxLDEgbCA5LDkgTSAxMCwxIGwgLTksOSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMjsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNyb3NzU3RhcnQiIGNsYXNzPSJtYXJrZXIgY3Jvc3MgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTEgMTEiIHJlZlg9Ii0xIiByZWZZPSI1LjIiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMSwxIGwgOSw5IE0gMTAsMSBsIC05LDkiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDI7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PGcgY2xhc3M9InJvb3QiPjxnIGNsYXNzPSJjbHVzdGVycyIvPjxnIGNsYXNzPSJlZGdlUGF0aHMiLz48ZyBjbGFzcz0iZWRnZUxhYmVscyIvPjxnIGNsYXNzPSJub2RlcyI+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBncmVlbiBmbG93Y2hhcnQtbGFiZWwiIGlkPSJmbG93Y2hhcnQtdXJsZW5jb2Rlci0wIiBkYXRhLW5vZGU9InRydWUiIGRhdGEtaWQ9InVybGVuY29kZXIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDk0LjI1LCAxNykiPjxyZWN0IGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiIHN0eWxlPSIiIHJ4PSIwIiByeT0iMCIgeD0iLTk0LjI1IiB5PSItMTciIHdpZHRoPSIxODguNSIgaGVpZ2h0PSIzNCIvPjxnIGNsYXNzPSJsYWJlbCIgc3R5bGU9IiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTg2Ljc1LCAtOS41KSI+PHJlY3QvPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIxNzMuNSIgaGVpZ2h0PSIxOSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPmNvbS51d3luLnVybGVuY29kZXI8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjwvZz48L2c+PC9zdmc+" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>urlencoder</code> encodes URL components using rules determined by combining the unreserved character set from <a href="https://www.rfc-editor.org/rfc/rfc3986#page-13">RFC 3986</a> with the percent-encode set from <a href="https://url.spec.whatwg.org/#application-x-www-form-urlencoded-percent-encode-set">application/x-www-form-urlencoded</a>.</p>
<h2 id="why-use-it">Why use it</h2>
<p>The built-in <a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/net/URLEncoder.html"><code>java.net.URLEncoder</code></a> encodes strings into the "HTML form encoding."</p>
<p>This is very slightly different from the form of encoding that should be used for URLs. In the specifications for URIs (<a href="https://www.rfc-editor.org/rfc/rfc3986#section-1.1.3">URLs are a subset of URIs</a>), spaces are encoded as <code>%20</code>. In <code>application/x-www-form-urlencoded</code>, spaces are usually encoded as <code>+</code>, though <code>%20</code> would also be valid.</p>
<p>Because <a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/net/URLEncoder.html"><code>java.net.URLEncoder</code></a> uses <code>+</code> for spaces, <a href="https://github.com/gbevin/urlencoder#why-not-simply-use-javaneturlencoder">other libraries can fail to decode data properly</a>.</p>
<p>The <a href="https://github.com/gbevin/urlencoder/blob/main/src/main/java/com/uwyn/urlencoder/UrlEncoder.java"><code>UrlEncoder</code></a> class in this library uses <code>%20</code> for spaces and is also <a href="https://github.com/gbevin/urlencoder/tree/main#url-encoder-for-java">reportedly more efficient</a> than <a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/net/URLEncoder.html"><code>java.net.URLEncoder</code></a>.</p>
<h2 id="getting-started">Getting Started</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">uwyn</span><span class="op">.</span><span class="im">urlencoder</span><span class="op">.</span><span class="im">UrlEncoder</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    var string <span class="op">=</span> <span class="st">&quot;Hello world&quot;</span><span class="op">;</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    var encoded <span class="op">=</span> UrlEncoder<span class="op">.</span><span class="fu">encode</span><span class="op">(</span>string<span class="op">);</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>encoded<span class="op">);</span> <span class="co">// Hello%20world</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    var decoded <span class="op">=</span> UrlEncoder<span class="op">.</span><span class="fu">decode</span><span class="op">(</span>encoded<span class="op">);</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>decoded<span class="op">);</span> <span class="co">// Hello world</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>dev.mccue.reasonphrase</title><link>https://mccue.dev/pages/12-2-23-java-library-of-the-day-2</link><description></description><pubDate>Sat, 02 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>dev.mccue.reasonphrase</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">dev.mccue.reasonphrase</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/dev.mccue/reasonphrase"><code>dev.mccue/reasonphrase</code></a></li>
<li>Module Name: <code>dev.mccue.reasonphrase</code></li>
<li>GitHub: <a href="https://github.com/bowbahdoe/reasonphrase"><code>bowbahdoe/reasonphrase</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogMjMxLjU2MnB4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii04IC04IDIzMS41NjI1IDUwIiByb2xlPSJncmFwaGljcy1kb2N1bWVudCBkb2N1bWVudCIgYXJpYS1yb2xlZGVzY3JpcHRpb249ImZsb3djaGFydC12MiI+PHN0eWxlPiNteS1zdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O2ZpbGw6IzMzMzt9I215LXN2ZyAuZXJyb3ItaWNvbntmaWxsOiM1NTIyMjI7fSNteS1zdmcgLmVycm9yLXRleHR7ZmlsbDojNTUyMjIyO3N0cm9rZTojNTUyMjIyO30jbXktc3ZnIC5lZGdlLXRoaWNrbmVzcy1ub3JtYWx7c3Ryb2tlLXdpZHRoOjJweDt9I215LXN2ZyAuZWRnZS10aGlja25lc3MtdGhpY2t7c3Ryb2tlLXdpZHRoOjMuNXB4O30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tc29saWR7c3Ryb2tlLWRhc2hhcnJheTowO30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tZGFzaGVke3N0cm9rZS1kYXNoYXJyYXk6Mzt9I215LXN2ZyAuZWRnZS1wYXR0ZXJuLWRvdHRlZHtzdHJva2UtZGFzaGFycmF5OjI7fSNteS1zdmcgLm1hcmtlcntmaWxsOiMzMzMzMzM7c3Ryb2tlOiMzMzMzMzM7fSNteS1zdmcgLm1hcmtlci5jcm9zc3tzdHJva2U6IzMzMzMzMzt9I215LXN2ZyBzdmd7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxNnB4O30jbXktc3ZnIC5sYWJlbHtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Y29sb3I6IzMzMzt9I215LXN2ZyAuY2x1c3Rlci1sYWJlbCB0ZXh0e2ZpbGw6IzMzMzt9I215LXN2ZyAuY2x1c3Rlci1sYWJlbCBzcGFuLCNteS1zdmcgcHtjb2xvcjojMzMzO30jbXktc3ZnIC5sYWJlbCB0ZXh0LCNteS1zdmcgc3BhbiwjbXktc3ZnIHB7ZmlsbDojMzMzO2NvbG9yOiMzMzM7fSNteS1zdmcgLm5vZGUgcmVjdCwjbXktc3ZnIC5ub2RlIGNpcmNsZSwjbXktc3ZnIC5ub2RlIGVsbGlwc2UsI215LXN2ZyAubm9kZSBwb2x5Z29uLCNteS1zdmcgLm5vZGUgcGF0aHtmaWxsOiNFQ0VDRkY7c3Ryb2tlOiM5MzcwREI7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAuZmxvd2NoYXJ0LWxhYmVsIHRleHR7dGV4dC1hbmNob3I6bWlkZGxlO30jbXktc3ZnIC5ub2RlIC5rYXRleCBwYXRoe2ZpbGw6IzAwMDtzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5ub2RlIC5sYWJlbHt0ZXh0LWFsaWduOmNlbnRlcjt9I215LXN2ZyAubm9kZS5jbGlja2FibGV7Y3Vyc29yOnBvaW50ZXI7fSNteS1zdmcgLmFycm93aGVhZFBhdGh7ZmlsbDojMzMzMzMzO30jbXktc3ZnIC5lZGdlUGF0aCAucGF0aHtzdHJva2U6IzMzMzMzMztzdHJva2Utd2lkdGg6Mi4wcHg7fSNteS1zdmcgLmZsb3djaGFydC1saW5re3N0cm9rZTojMzMzMzMzO2ZpbGw6bm9uZTt9I215LXN2ZyAuZWRnZUxhYmVse2JhY2tncm91bmQtY29sb3I6I2U4ZThlODt0ZXh0LWFsaWduOmNlbnRlcjt9I215LXN2ZyAuZWRnZUxhYmVsIHJlY3R7b3BhY2l0eTowLjU7YmFja2dyb3VuZC1jb2xvcjojZThlOGU4O2ZpbGw6I2U4ZThlODt9I215LXN2ZyAubGFiZWxCa2d7YmFja2dyb3VuZC1jb2xvcjpyZ2JhKDIzMiwgMjMyLCAyMzIsIDAuNSk7fSNteS1zdmcgLmNsdXN0ZXIgcmVjdHtmaWxsOiNmZmZmZGU7c3Ryb2tlOiNhYWFhMzM7c3Ryb2tlLXdpZHRoOjFweDt9I215LXN2ZyAuY2x1c3RlciB0ZXh0e2ZpbGw6IzMzMzt9I215LXN2ZyAuY2x1c3RlciBzcGFuLCNteS1zdmcgcHtjb2xvcjojMzMzO30jbXktc3ZnIGRpdi5tZXJtYWlkVG9vbHRpcHtwb3NpdGlvbjphYnNvbHV0ZTt0ZXh0LWFsaWduOmNlbnRlcjttYXgtd2lkdGg6MjAwcHg7cGFkZGluZzoycHg7Zm9udC1mYW1pbHk6InRyZWJ1Y2hldCBtcyIsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxMnB4O2JhY2tncm91bmQ6aHNsKDgwLCAxMDAlLCA5Ni4yNzQ1MDk4MDM5JSk7Ym9yZGVyOjFweCBzb2xpZCAjYWFhYTMzO2JvcmRlci1yYWRpdXM6MnB4O3BvaW50ZXItZXZlbnRzOm5vbmU7ei1pbmRleDoxMDA7fSNteS1zdmcgLmZsb3djaGFydFRpdGxlVGV4dHt0ZXh0LWFuY2hvcjptaWRkbGU7Zm9udC1zaXplOjE4cHg7ZmlsbDojMzMzO30jbXktc3ZnIDpyb290ey0tbWVybWFpZC1mb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7fSNteS1zdmcgLmdyZWVuJmd0Oyp7c3Ryb2tlOnJnYigyNTUsIDAsIDApIWltcG9ydGFudDt9I215LXN2ZyAuZ3JlZW4gc3BhbntzdHJva2U6cmdiKDI1NSwgMCwgMCkhaW1wb3J0YW50O308L3N0eWxlPjxnPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtcG9pbnRFbmQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjYiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjEyIiBtYXJrZXJIZWlnaHQ9IjEyIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMCAwIEwgMTAgNSBMIDAgMTAgeiIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LXBvaW50U3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjQuNSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTIiIG1hcmtlckhlaWdodD0iMTIiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAwIDUgTCAxMCAxMCBMIDEwIDAgeiIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNpcmNsZUVuZCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iMTEiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxjaXJjbGUgY3g9IjUiIGN5PSI1IiByPSI1IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY2lyY2xlU3RhcnQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9Ii0xIiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48Y2lyY2xlIGN4PSI1IiBjeT0iNSIgcj0iNSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNyb3NzRW5kIiBjbGFzcz0ibWFya2VyIGNyb3NzIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDExIDExIiByZWZYPSIxMiIgcmVmWT0iNS4yIiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDEsMSBsIDksOSBNIDEwLDEgbCAtOSw5IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAyOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY3Jvc3NTdGFydCIgY2xhc3M9Im1hcmtlciBjcm9zcyBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMSAxMSIgcmVmWD0iLTEiIHJlZlk9IjUuMiIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAxLDEgbCA5LDkgTSAxMCwxIGwgLTksOSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMjsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48ZyBjbGFzcz0icm9vdCI+PGcgY2xhc3M9ImNsdXN0ZXJzIi8+PGcgY2xhc3M9ImVkZ2VQYXRocyIvPjxnIGNsYXNzPSJlZGdlTGFiZWxzIi8+PGcgY2xhc3M9Im5vZGVzIj48ZyBjbGFzcz0ibm9kZSBkZWZhdWx0IGdyZWVuIGZsb3djaGFydC1sYWJlbCIgaWQ9ImZsb3djaGFydC1yZWFzb25waHJhc2UtMCIgZGF0YS1ub2RlPSJ0cnVlIiBkYXRhLWlkPSJyZWFzb25waHJhc2UiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEwNy43ODEyNSwgMTcpIj48cmVjdCBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIiBzdHlsZT0iIiByeD0iMCIgcnk9IjAiIHg9Ii0xMDcuNzgxMjUiIHk9Ii0xNyIgd2lkdGg9IjIxNS41NjI1IiBoZWlnaHQ9IjM0Ii8+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTAwLjI4MTI1LCAtOS41KSI+PHJlY3QvPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIyMDAuNTYyNSIgaGVpZ2h0PSIxOSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPmRldi5tY2N1ZS5yZWFzb25waHJhc2U8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PC9nPjwvZz48L2c+PC9zdmc+" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p><code>reasonphrase</code> is a library that provides a lookup from an <a href="https://www.rfc-editor.org/rfc/rfc9110.html#name-overview-of-status-codes">HTTP Status Code</a> (like <code>200</code>) to an <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html">HTTP Reason Phrase</a> (like <code>OK</code>).</p>
<p>Reason phrases are a mostly unused part of the HTTP protocol but, if you need to pick one anyway, you might as well pick a standard one.</p>
<h2 id="why-use-it">Why use it</h2>
<p>In most situations, your web server will automatically pick a reason phrase based on the status code of a response.</p>
<p>A notable exception to this is Microhttp, which exposes the reason phrase directly in its <code>Response</code> record.</p>
<p>So if you are using Microhttp, or some other minimal server, then this library will be of use.</p>
<h2 id="getting-started">Getting Started</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">EventLoop</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">Response</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">Header</span><span class="op">;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">reasonphrase</span><span class="op">.</span><span class="im">ReasonPhrase</span><span class="op">;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="kw">throws</span> <span class="bu">Exception</span> <span class="op">{</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    var eventLoop <span class="op">=</span> <span class="kw">new</span> <span class="fu">EventLoop</span><span class="op">((</span>request<span class="op">,</span> callback<span class="op">)</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>        callback<span class="op">.</span><span class="fu">accept</span><span class="op">(</span><span class="kw">new</span> <span class="bu">Response</span><span class="op">(</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>            <span class="dv">200</span><span class="op">,</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>            ReasonPhrase<span class="op">.</span><span class="fu">forStatus</span><span class="op">(</span><span class="dv">200</span><span class="op">),</span> </span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>            <span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="kw">new</span> <span class="fu">Header</span><span class="op">(</span><span class="st">&quot;Content-Type&quot;</span><span class="op">,</span> <span class="st">&quot;text/plain&quot;</span><span class="op">)),</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;Hello, world&quot;</span><span class="op">.</span><span class="fu">getBytes</span><span class="op">()</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">));</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">});</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>    eventLoop<span class="op">.</span><span class="fu">start</span><span class="op">();</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>    eventLoop<span class="op">.</span><span class="fu">join</span><span class="op">();</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>org.microhttp</title><link>https://mccue.dev/pages/12-1-23-java-library-of-the-day-1</link><description></description><pubDate>Fri, 01 Dec 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>org.microhttp</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">org.microhttp</h1>
</header>
<ul>
<li>Maven: <a href="https://central.sonatype.com/artifact/org.microhttp/microhttp"><code>org.microhttp/microhttp</code></a></li>
<li>Module Name: <code>org.microhttp</code></li>
<li>GitHub: <a href="https://github.com/ebarlas/microhttp"><code>ebarlas/microhttp</code></a></li>
</ul>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogMTQwLjAxNnB4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii04IC04IDE0MC4wMTU2MjUgNTAiIHJvbGU9ImdyYXBoaWNzLWRvY3VtZW50IGRvY3VtZW50IiBhcmlhLXJvbGVkZXNjcmlwdGlvbj0iZmxvd2NoYXJ0LXYyIj48c3R5bGU+I215LXN2Z3tmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjE2cHg7ZmlsbDojMzMzO30jbXktc3ZnIC5lcnJvci1pY29ue2ZpbGw6IzU1MjIyMjt9I215LXN2ZyAuZXJyb3ItdGV4dHtmaWxsOiM1NTIyMjI7c3Ryb2tlOiM1NTIyMjI7fSNteS1zdmcgLmVkZ2UtdGhpY2tuZXNzLW5vcm1hbHtzdHJva2Utd2lkdGg6MnB4O30jbXktc3ZnIC5lZGdlLXRoaWNrbmVzcy10aGlja3tzdHJva2Utd2lkdGg6My41cHg7fSNteS1zdmcgLmVkZ2UtcGF0dGVybi1zb2xpZHtzdHJva2UtZGFzaGFycmF5OjA7fSNteS1zdmcgLmVkZ2UtcGF0dGVybi1kYXNoZWR7c3Ryb2tlLWRhc2hhcnJheTozO30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tZG90dGVke3N0cm9rZS1kYXNoYXJyYXk6Mjt9I215LXN2ZyAubWFya2Vye2ZpbGw6IzMzMzMzMztzdHJva2U6IzMzMzMzMzt9I215LXN2ZyAubWFya2VyLmNyb3Nze3N0cm9rZTojMzMzMzMzO30jbXktc3ZnIHN2Z3tmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjE2cHg7fSNteS1zdmcgLmxhYmVse2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtjb2xvcjojMzMzO30jbXktc3ZnIC5jbHVzdGVyLWxhYmVsIHRleHR7ZmlsbDojMzMzO30jbXktc3ZnIC5jbHVzdGVyLWxhYmVsIHNwYW4sI215LXN2ZyBwe2NvbG9yOiMzMzM7fSNteS1zdmcgLmxhYmVsIHRleHQsI215LXN2ZyBzcGFuLCNteS1zdmcgcHtmaWxsOiMzMzM7Y29sb3I6IzMzMzt9I215LXN2ZyAubm9kZSByZWN0LCNteS1zdmcgLm5vZGUgY2lyY2xlLCNteS1zdmcgLm5vZGUgZWxsaXBzZSwjbXktc3ZnIC5ub2RlIHBvbHlnb24sI215LXN2ZyAubm9kZSBwYXRoe2ZpbGw6I0VDRUNGRjtzdHJva2U6IzkzNzBEQjtzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5mbG93Y2hhcnQtbGFiZWwgdGV4dHt0ZXh0LWFuY2hvcjptaWRkbGU7fSNteS1zdmcgLm5vZGUgLmthdGV4IHBhdGh7ZmlsbDojMDAwO3N0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxcHg7fSNteS1zdmcgLm5vZGUgLmxhYmVse3RleHQtYWxpZ246Y2VudGVyO30jbXktc3ZnIC5ub2RlLmNsaWNrYWJsZXtjdXJzb3I6cG9pbnRlcjt9I215LXN2ZyAuYXJyb3doZWFkUGF0aHtmaWxsOiMzMzMzMzM7fSNteS1zdmcgLmVkZ2VQYXRoIC5wYXRoe3N0cm9rZTojMzMzMzMzO3N0cm9rZS13aWR0aDoyLjBweDt9I215LXN2ZyAuZmxvd2NoYXJ0LWxpbmt7c3Ryb2tlOiMzMzMzMzM7ZmlsbDpub25lO30jbXktc3ZnIC5lZGdlTGFiZWx7YmFja2dyb3VuZC1jb2xvcjojZThlOGU4O3RleHQtYWxpZ246Y2VudGVyO30jbXktc3ZnIC5lZGdlTGFiZWwgcmVjdHtvcGFjaXR5OjAuNTtiYWNrZ3JvdW5kLWNvbG9yOiNlOGU4ZTg7ZmlsbDojZThlOGU4O30jbXktc3ZnIC5sYWJlbEJrZ3tiYWNrZ3JvdW5kLWNvbG9yOnJnYmEoMjMyLCAyMzIsIDIzMiwgMC41KTt9I215LXN2ZyAuY2x1c3RlciByZWN0e2ZpbGw6I2ZmZmZkZTtzdHJva2U6I2FhYWEzMztzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5jbHVzdGVyIHRleHR7ZmlsbDojMzMzO30jbXktc3ZnIC5jbHVzdGVyIHNwYW4sI215LXN2ZyBwe2NvbG9yOiMzMzM7fSNteS1zdmcgZGl2Lm1lcm1haWRUb29sdGlwe3Bvc2l0aW9uOmFic29sdXRlO3RleHQtYWxpZ246Y2VudGVyO21heC13aWR0aDoyMDBweDtwYWRkaW5nOjJweDtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjEycHg7YmFja2dyb3VuZDpoc2woODAsIDEwMCUsIDk2LjI3NDUwOTgwMzklKTtib3JkZXI6MXB4IHNvbGlkICNhYWFhMzM7Ym9yZGVyLXJhZGl1czoycHg7cG9pbnRlci1ldmVudHM6bm9uZTt6LWluZGV4OjEwMDt9I215LXN2ZyAuZmxvd2NoYXJ0VGl0bGVUZXh0e3RleHQtYW5jaG9yOm1pZGRsZTtmb250LXNpemU6MThweDtmaWxsOiMzMzM7fSNteS1zdmcgOnJvb3R7LS1tZXJtYWlkLWZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjt9I215LXN2ZyAuZ3JlZW4mZ3Q7KntzdHJva2U6cmdiKDI1NSwgMCwgMCkhaW1wb3J0YW50O30jbXktc3ZnIC5ncmVlbiBzcGFue3N0cm9rZTpyZ2IoMjU1LCAwLCAwKSFpbXBvcnRhbnQ7fTwvc3R5bGU+PGc+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1wb2ludEVuZCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iNiIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTIiIG1hcmtlckhlaWdodD0iMTIiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAwIDAgTCAxMCA1IEwgMCAxMCB6IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtcG9pbnRTdGFydCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iNC41IiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMiIgbWFya2VySGVpZ2h0PSIxMiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDAgNSBMIDEwIDEwIEwgMTAgMCB6IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY2lyY2xlRW5kIiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSIxMSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PGNpcmNsZSBjeD0iNSIgY3k9IjUiIHI9IjUiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jaXJjbGVTdGFydCIgY2xhc3M9Im1hcmtlciBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iLTEiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxjaXJjbGUgY3g9IjUiIGN5PSI1IiByPSI1IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9Im15LXN2Z19mbG93Y2hhcnQtY3Jvc3NFbmQiIGNsYXNzPSJtYXJrZXIgY3Jvc3MgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTEgMTEiIHJlZlg9IjEyIiByZWZZPSI1LjIiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMSwxIGwgOSw5IE0gMTAsMSBsIC05LDkiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDI7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jcm9zc1N0YXJ0IiBjbGFzcz0ibWFya2VyIGNyb3NzIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDExIDExIiByZWZYPSItMSIgcmVmWT0iNS4yIiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDEsMSBsIDksOSBNIDEwLDEgbCAtOSw5IiBjbGFzcz0iYXJyb3dNYXJrZXJQYXRoIiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAyOyBzdHJva2UtZGFzaGFycmF5OiAxLCAwOyIvPjwvbWFya2VyPjxnIGNsYXNzPSJyb290Ij48ZyBjbGFzcz0iY2x1c3RlcnMiLz48ZyBjbGFzcz0iZWRnZVBhdGhzIi8+PGcgY2xhc3M9ImVkZ2VMYWJlbHMiLz48ZyBjbGFzcz0ibm9kZXMiPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZ3JlZW4gZmxvd2NoYXJ0LWxhYmVsIiBpZD0iZmxvd2NoYXJ0LUEtMCIgZGF0YS1ub2RlPSJ0cnVlIiBkYXRhLWlkPSJBIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg2Mi4wMDc4MTI1LCAxNykiPjxyZWN0IGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiIHN0eWxlPSIiIHJ4PSIwIiByeT0iMCIgeD0iLTYyLjAwNzgxMjUiIHk9Ii0xNyIgd2lkdGg9IjEyNC4wMTU2MjUiIGhlaWdodD0iMzQiLz48ZyBjbGFzcz0ibGFiZWwiIHN0eWxlPSIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC01NC41MDc4MTI1LCAtOS41KSI+PHJlY3QvPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIxMDkuMDE1NjI1IiBoZWlnaHQ9IjE5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+b3JnLm1pY3JvaHR0cDwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=" alt="" /></p>
<h2 id="what-is-it">What is it</h2>
<p>Microhttp is an implementation of an HTTP/1.1 server.</p>
<p>This means that it can handle things like <code>GET</code> and <code>POST</code> requests, but not securing a connection with SSL or websocket connections.</p>
<h2 id="why-use-it">Why use it</h2>
<p>It is <a href="https://www.reddit.com/r/java/comments/w7uqcl/latest_version_of_microhttp_an_eventdriven/">very fast</a> and, as a result of eschewing support for most convenience features and other protocols, it has a codebase that can be <a href="https://github.com/ebarlas/microhttp/blob/main/src/main/java/org/microhttp/ConnectionEventLoop.java">reasonably read and understood fully</a> in a day or two at most.</p>
<p>It discretizes requests and responses, which is a problem if you were expecting to handle file uploads or other such tasks directly, but a non-issue if you only intend to send and receive payloads of reasonable size.</p>
<p>In order to publish to the wider internet, you will need to have SSL. That Microhttp doesn't handle this natively isn't that much of an issue since most platforms as a service like <a href="https://www.heroku.com/">Heroku</a>, <a href="https://railway.app/">Railway</a>, and <a href="https://render.com/">Render</a> provide this by default. As will any load balancer or properly configured <a href="https://www.nginx.com/blog/using-free-ssltls-certificates-from-lets-encrypt-with-nginx/"><code>nginix</code></a>.</p>
<h2 id="getting-started">Getting Started</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">EventLoop</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">Response</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">microhttp</span><span class="op">.</span><span class="im">Header</span><span class="op">;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span><span class="op">()</span> <span class="kw">throws</span> <span class="bu">Exception</span> <span class="op">{</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    var eventLoop <span class="op">=</span> <span class="kw">new</span> <span class="fu">EventLoop</span><span class="op">((</span>request<span class="op">,</span> callback<span class="op">)</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>        callback<span class="op">.</span><span class="fu">accept</span><span class="op">(</span><span class="kw">new</span> <span class="bu">Response</span><span class="op">(</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>            <span class="dv">200</span><span class="op">,</span> </span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;OK&quot;</span><span class="op">,</span> </span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>            <span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="kw">new</span> <span class="fu">Header</span><span class="op">(</span><span class="st">&quot;Content-Type&quot;</span><span class="op">,</span> <span class="st">&quot;text/plain&quot;</span><span class="op">)),</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;Hello, world&quot;</span><span class="op">.</span><span class="fu">getBytes</span><span class="op">()</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">));</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">});</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>    eventLoop<span class="op">.</span><span class="fu">start</span><span class="op">();</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    eventLoop<span class="op">.</span><span class="fu">join</span><span class="op">();</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Better Java Compiler Error Messages</title><link>https://mccue.dev/pages/8-13-23-java-compiler-error-messages</link><description></description><pubDate>Sun, 13 Aug 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Better Java Compiler Error Messages</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Better Java Compiler Error Messages</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
This post represents almost a year of work from [Andrew Arnold](https://github.com/aarnold314), [Ataberk Cirikci](https://github.com/AtaberkCirikci),
[Noah Jamison](https://github.com/NJamison1), and [Thalia La Pommeray](https://github.com/ThaliaLaPommeray)<sup><a href="#1">1</a></sup>.

<p>Every part of this that you agree with, they deserve all the credit for. Every part that you do not can be blamed on me.</p>
<p>Also, this is about Java. We'll take a bit of a winding road to get there, but we will get there.</p>
<h2 id="background">Background</h2>
<p>A compiler's job is to take code - usually from text files - and produce some usable artifact from it. For Java that means taking <code>*.java</code> files and producing <code>*.class</code> files that can be fed into a JVM.<sup><a href="#2">2</a></sup></p>
<p>The first and most important priority of a compiler is to be correct. If the class files produced by the Java compiler do not function in the way specified by the <a href="https://docs.oracle.com/javase/specs/">Java Language Specification</a> then it would not be a Java compiler.</p>
<!-- 
    [It would be a compiler for a different language](https://www.reddit.com/r/java/comments/13mp9g0/comment/jl9yu0n/?utm_source=share&utm_medium=web2x&context=3).
-->

<p>The second priority of a compiler has historically been to be fast and resource efficient. In the 90s, CPU and RAM were far more scarce resources. If a language couldn't be compiled efficiently then it would be impractical to use. <sup><a href="#3">3</a></sup></p>
<p>What has historically not been a focus, and has seen a renaissance in modern times, is error messages.</p>
<h3 id="elm">Elm</h3>
<p>Elm is a very small and very focused language. It is built specifically for making frontend web apps and has a very restricted set of features.<sup><a href="#4">4</a></sup></p>
<div class="sourceCode" id="cb1"><pre class="sourceCode elm"><code class="sourceCode elm"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Html</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="fu">main</span> <span class="op">=</span> </span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Html</span><span class="op">.</span><span class="fu">h1</span> <span class="st">&quot;Hello, world&quot;</span></span></code></pre></div>
<p>It's pretty cool. <a href="https://elm-lang.org/try">Check it out</a> if you have some time.</p>
<p>Due to its relatively small surface area<sup><a href="#5">5</a></sup>, the language designer was <a href="https://elm-lang.org/news/compiler-errors-for-humans">able to dedicate time to the user experience (UX) of its compiler errors</a>.</p>
<p>And by <a href="https://twitter.com/TartanLlama/status/978285498430119937">most</a> <a href="https://twitter.com/Mastapegs/status/1492173070529871884">accounts</a><sup><a href="#6">6</a></sup>, that work has paid off.</p>
<p>When a programmer makes a mistake with their Elm code, the Elm compiler will</p>
<ul>
<li>always have a friendly tone</li>
<li>do its best to show the relevant areas of the code</li>
<li>provide a hint as to how to resolve the error</li>
</ul>
<p>Say we took the example from above and tried to use a fictional <code>h7</code> tag.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode elm"><code class="sourceCode elm"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Html</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- There is no h7 tag</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="fu">main</span> <span class="op">=</span> </span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Html</span><span class="op">.</span><span class="fu">h7</span> <span class="st">&quot;Hello, world&quot;</span></span></code></pre></div>
<p>The error you would get is the following.</p>
<pre><code>I cannot find a `Html.h7` variable:

5|     Html.h7 &quot;Hello, world&quot;
       ^^^^^^^
The `Html` module does not expose a `h7` variable. These names seem close
though:

    Html.h1
    Html.h2
    Html.h3
    Html.h4

Hint: Read &lt;https://elm-lang.org/0.19.1/imports&gt; to see how `import`
declarations work in Elm.</code></pre>
<p>First to note is the personification of the compiler as an entity. When it says "<em>I</em> cannot find a variable" it subtly, but importantly, primes the user to think about the compiler as an entity unto itself. Its small stuff like that gives our monkey brains the hooks it needs to anthropomorphize.</p>
<p>And that is useful, because the only time a compiler talks to you is when something is wrong. Which would you prefer</p>
<ul>
<li>"You have cancer"</li>
<li>"I have your test results, and unfortunately you have cancer."</li>
</ul>
<p>The first one is a game over screen in a <a href="https://www.youtube.com/watch?v=oUKyFPMZ2_g">FromSoft game</a>, the second is a human being with some bedside manner.<sup><a href="#7">7</a></sup></p>
<p>Another aspect about this that is cool is that it points to the exact place in the code that is at issue. Not just the line, but specifically the <code>Html.h7</code> expression.</p>
<pre class="text"><code>5|     Html.h7 &quot;Hello, world&quot;
       ^^^^^^^</code></pre>
<blockquote>
<p>Before you can resolve an error, you need to find the code causing it. Seems pretty obvious.</p>
<p>With many compilers you get a location like program.x:43:22 that you have to decipher. Where is that file? Which one is the line? Which is the column? Okay, let me scan through my code. You also often get a pretty-printed version of the problematic code, but it looks nothing like the code you wrote. You again need to do a mental transformation to find it. So a lot of time is lost:</p>
<ul>
<li>converting row and column numbers into an actual file position</li>
<li>converting pretty-printed code onto actual code to verify that position</li>
</ul>
</blockquote>
<p>And don't forget that hint! It's a pretty basic analysis<sup><a href="#8">8</a></sup>, but being able to suggest functions that the user might have meant is big. Even if we disregard the exact contents of the hint, that there is a dedicated place to give hints and for users to look for hints is great.</p>
<p>It is hard to show in this format<sup><a href="#9">9</a></sup>, but in addition to the layout of the message things like the <code>^^^^^^^</code> are colored red to draw our attention.</p>
<code>
<pre>
5|     Html.h7 "Hello, world"
       <span style="color: red">^^^^^^^</span>
</pre>
</code>

<p>Say we constructed a similar situation in Java.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Html <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="bu">Object</span> <span class="fu">h1</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>       <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span> </span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="bu">Object</span> <span class="fu">h2</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="bu">Object</span> <span class="fu">h3</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="bu">Object</span> <span class="fu">h4</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="bu">Object</span> <span class="fu">h5</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="bu">Object</span> <span class="fu">h6</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>Html<span class="op">.</span><span class="fu">h7</span><span class="op">());</span></span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-26"><a href="#cb5-26" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The error message we get is <a href="https://www.youtube.com/watch?v=gCktKQKXNWg">streets behind</a>.</p>
<pre><code>/Main.java:24: error: cannot find symbol
        System.out.println(Html.h7());
                               ^
  symbol:   method h7()
  location: class Html
1 error</code></pre>
<blockquote>
<p>It is kind of shocking how much better things get when you focus on the user. I mean, on some level, it is not shocking at all though. Most terminal tools came into existence well before our industry really started focusing on making apps and websites feel great for their users. We all collectively realized that a hard to use app or website is bad for business, but the same lessons have not really percolated down to tools like compilers and build tools yet. Hopefully I have demonstrated that we can do better!</p>
</blockquote>
<h3 id="rust">Rust</h3>
<p>Rust is a systems programming language. That means that it targets the same use-cases as C and C++ where speed and predictable latency are hard requirements.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Position <span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>    x<span class="op">:</span> <span class="dt">u32</span><span class="op">,</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>    y<span class="op">:</span> <span class="dt">u32</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> position <span class="op">=</span> Position <span class="op">{</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>        x<span class="op">:</span> <span class="dv">0</span><span class="op">,</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>        y<span class="op">:</span> <span class="dv">1</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>    <span class="pp">println!</span>(<span class="st">&quot;x: {}, y: {}&quot;</span><span class="op">,</span> position<span class="op">.</span>x<span class="op">,</span> position<span class="op">.</span>y)<span class="op">;</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Rust's most famous feature is its borrow checker. This is what lets it compete in ergonomics with languages like Python and Java without automatic garbage collection at runtime.<sup><a href="#10">10</a></sup></p>
<p>It does this by tracking the "lifetime" of individual variables and fields, putting some rules in place for when those lifetimes end, and what to do when they end and the variable is "dropped".<sup><a href="#11">11</a></sup></p>
<div class="sourceCode" id="cb8"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Position <span class="op">{</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>    x<span class="op">:</span> <span class="dt">u32</span><span class="op">,</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>    y<span class="op">:</span> <span class="dt">u32</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Lifetime of the position starts here</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> position <span class="op">=</span> Position <span class="op">{</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>        x<span class="op">:</span> <span class="dv">0</span><span class="op">,</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>        y<span class="op">:</span> <span class="dv">1</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>    <span class="pp">println!</span>(<span class="st">&quot;x: {}, y: {}&quot;</span><span class="op">,</span> position<span class="op">.</span>x<span class="op">,</span> position<span class="op">.</span>y)<span class="op">;</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a>    <span class="co">// At this point the position variable is no longer &quot;alive&quot;</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>    <span class="co">// and all the memory allocated for it will be freed.</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The tradeoff here is that the complexity of tracking lifetimes is pushed into the type system. This <a href="https://practice.rs/generics-traits/const-generics.html">and other advanced features</a> make Rust one of the most complicated languages out there. <a href="https://web.mit.edu/rust-lang_v1.25/arch/amd64_ubuntu1404/share/doc/rust/html/book/first-edition/references-and-borrowing.html">"Fighting the Borrow Checker"</a> is a very common occurrence.</p>
<p>Despite this, <a href="https://survey.stackoverflow.co/2022#technology-most-loved-dreaded-and-wanted">it is overwhelmingly loved</a> by those who have used it.</p>
<p>My hypothesis for why this is the case<sup><a href="#12">12</a></sup> is it is because very early on its development, there <a href="https://blog.rust-lang.org/2016/08/10/Shape-of-errors-to-come.html">was dedicated focus given to the error messages its compiler produced</a>.<sup><a href="#13">13</a></sup> Even though people tend to produce malformed programs far more often<sup><a href="#14">14</a></sup>, the experience of the compiler being "helpful" offset that.<sup><a href="#15">15</a></sup></p>
<blockquote>
<p>With the importance of addressing Rust's learning curve a key theme in the Rust survey we're as motivated as ever to find any confusing or distracting part of the Rust experience and give it a healthy amount of polish. Errors are one area where we're applying that polish helps us improve the learning curve bit by bit, and we're looking forward to seeing how far we can go.</p>
</blockquote>
<p>All error messages in Rust have a specific structure. There is a place for saying where an error occurred, why it occurred, what the error was, and potentially a hint as to how to resolve it.</p>
<p>For example, this code is malformed because enum variants need to be prefixed with the name of the enum.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> Ex <span class="op">{</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>    A<span class="op">,</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>    B</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">fn</span> main() <span class="op">{</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> ex <span class="op">=</span> A<span class="op">;</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The error message that the compiler produces reflects that.</p>
<pre><code>error[E0425]: cannot find value `A` in this scope
 --&gt; src/main.rs:7:14
  |
7 |     let ex = A;
  |              ^ not found in this scope
  |
help: consider importing this unit variant
  |
1 | use crate::Ex::A;
  |

For more information about this error, try `rustc --explain E0425`.</code></pre>
<p>It says that the problem is that the value <code>A</code> could not be found in scope, shows exactly where in the code the problem is, and offers a hint as to how to resolve it.</p>
<p>Just like the Elm errors there is a dedicated section for giving hints, the exact place in the code where a problem happens is shown, and the message is written in a friendly tone.</p>
<pre><code>error[E0425]: WHAT
 --&gt; WHERE
  |
7 |     let ex = A;
  |              ^ WHY + (arrow gives implicit WHERE)
  |
help: HINT (can have many)
  |
1 | HINT
  |</code></pre>
<p>Compare and contrast that to the error you get with similarly malformed Java code.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">List</span><span class="op">;</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> Ex <span class="op">{</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>    A<span class="op">,</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>    B</span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> MyClass <span class="op">{</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span> args<span class="op">[])</span> <span class="op">{</span></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>        var ex <span class="op">=</span> B<span class="op">;</span></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<pre><code>/MyClass.java:10: error: cannot find symbol
        var ex = B;
                 ^
  symbol:   variable B
  location: class MyClass</code></pre>
<p>It still shows where the problem happened, but it offers no assistance for fixing it and uses a fittingly robotic tone.<sup><a href="#16">16</a></sup></p>
<h2 id="scala">Scala</h2>
<p>Scala is another language for the JVM like Java. I won't go that deep into an explanation because I am not qualified to do so, but as part of the work on Scala 3 they <a href="https://www.scala-lang.org/blog/2016/10/14/dotty-errors.html">worked to improve their error messages in similar ways as Elm and Rust</a></p>
<blockquote>
<p>We’ve looked at how other modern languages like Elm and Rust handle compiler warnings and error messages, and come to realize that Dotty is actually in great shape to provide comprehensive and easy to understand error messages in the same spirit.</p>
</blockquote>
<p><a href="https://github.com/lampepfl/dotty/issues/1589#issuecomment-593879892">That work is still ongoing</a>, but the focus was there.</p>
<p>That doesn't mean anything by itself, but I choose to take it as social proof that I'm not crazy.</p>
<h2 id="ides">IDEs</h2>
<p>It is tempting to say that it doesn't really matter what errors the compiler spits out because IDEs are in a better position to give feedback anyway.</p>
<p>To an extent, this makes sense. IDEs like <a href="https://www.jetbrains.com/idea/download/?section=mac">IntelliJ</a> are able to provide feedback in ways that a compiler cannot.</p>
<ul>
<li>If something is wrong, they can highlight it in red.</li>
<li>If something is questionable, they can highlight it in yellow.</li>
<li>If the IDE has a suggestion on how to fix something they can show that through other visual cues.<sup><a href="#17">17</a></sup></li>
</ul>
<p>That's all great, but unfortunately I don't think it is enough.</p>
<p>It's easy to forget when my M1 Mac is running <a href="https://baldursgate3.game/">Baldurs Gate 3</a> at 60 fps, but hardware powerful enough to run an IDE smoothly is a privilege. <a href="https://www.jetbrains.com/idea/download/?section=mac">IntelliJ</a> cannot run on a chromebook or whatever commodity hardware a <a href="https://www.cnn.com/2022/09/18/us/school-conditions-2022/index.html#:~:text=The%20school%20funding%20gap%20keeps%20getting%20worse&amp;text=And%20the%20gap%20is%20widening,had%20grown%20by%20%2425%20billion">chronically underfunded school system</a> can afford.<sup><a href="#18">18</a></sup></p>
<p>This is partly why many curriculums use online platforms like <a href="https://repl.it">repl.it</a> that are hosted remotely or rely on a student's workflow to be through the command line and a basic text editor.</p>
<p>In those cases especially, compiler errors are front and center in a student's learning.</p>
<p>This is likely going to become more true when the JEPs for <a href="https://openjdk.org/jeps/445">Unnamed Classes, Instance Main Methods</a>, and <a href="https://openjdk.org/jeps/8304400">Multi-File Source-Code Programs</a> are integrated and the ergonomics of teaching from the command line become more in line with that of other languages.</p>
<p>And while I can't demonstrate it in as strong a way, I maintain that the error messages matter when you are using an IDE as well. Not everyone sees the red squiggles, some students actively ignore them, and they will see the original compiler message when they try to run their code regardless.</p>
<p>If what they see is vague and unhelpful, that matters.<sup><a href="#19">19</a></sup></p>
<h2 id="research">Research</h2>
<p>There was, to my knowledge, exactly one overview study done on compiler error messages. <a href="https://www.researchgate.net/publication/339039595_Compiler_Error_Messages_Considered_Unhelpful_The_Landscape_of_Text-Based_Programming_Error_Message_Research">"Compiler Error Messages Considered Unhelpful: The Landscape of Text-Based Programming Error Message Research"</a>.</p>
<p>To those unfamiliar, an overview study is research that looks at existing research within a field and draws conclusions from the body of work in totality. You don't get to make claims like "studies consistently show X, Y, and Z" without looking at all the studies.</p>
<p>There are a few things from that study I think are worthy of note.</p>
<p>First is that there is very little actual research on error messages.</p>
<blockquote>
<p>One of our most striking observations was that there was relatively little literature on the effect of programming error messages on students and their learning.</p>
</blockquote>
<p>Which at the very least makes me feel better about "going with my gut." Everyone has to be.</p>
<p>Second is that the research that <em>does</em> exist does not produce any strong conclusions</p>
<blockquote>
<p>While there have been many guidelines for programming error message design proposed and implemented, no coherent picture has emerged to answer even simple questions such as: What does a good programming error message look like?</p>
</blockquote>
<p>But in the summation of the literature there are a few general guidelines that emerged.</p>
<ul>
<li>Increase Readability</li>
<li>Reduce Cognitive Load</li>
<li>Provide Context</li>
<li>Use a Positive Tone</li>
<li>Show Examples</li>
<li>Show Solutions or Hints</li>
<li>Allow Dynamic Interaction</li>
<li>Provide Scaffolding</li>
<li>Use logical argumentation</li>
<li>Report errors at the right time</li>
</ul>
<p>So while I would <em>love</em> to say "I'm right and science agrees with me"<sup><a href="#21">21</a></sup>, the best I can say is that all the properties of Elm and Rust compiler messages that I have noted are at least represented in the list of things that research suggests "might help."</p>
<p>That is</p>
<ul>
<li>Provide Context</li>
<li>Use a Positive Tone</li>
<li>Show Solutions or Hints</li>
</ul>
<p>There are individual studies <a href="https://www.brettbecker.com/wp-content/uploads/2016/06/Becker-Effective-2016-SIGCSE.pdf">like this one</a> that more directly support my claims, but I've heard of enough horrible <a href="https://www.iheart.com/podcast/105-behind-the-bastards-29236323/episode/part-one-dr-oz-why-americas-81426004/">Dr. Oz</a> segments like "Chocolate - the new a superfood?!" to know that it's disingenuous to use single studies like that.</p>
<p>So yeah, best I can say is "I am not obviously wrong."</p>
<h2 id="the-structure-of-javac">The Structure of <code>javac</code></h2>
<p>The reference compiler for Java is <code>javac</code>. It comes with every <a href="https://www.youtube.com/watch?v=3bfR22iv8Pc">OpenJDK build,</a> and it's what most people use to compile their java.<sup><a href="#25">25</a></sup></p>
<p>I will briefly explain some of its internal workings so that you have some context on what we changed and why.</p>
<h3 id="compilerproperties">compiler.properties</h3>
<p>All the error message text for <code>javac</code> lives inside a set of <a href="https://github.com/openjdk/jdk/blob/master/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties"><code>compiler.properties</code></a> files. There is one file for each language that has translations. German text is in <code>compiler_de.properties</code>, Japanese in <code>compiler_ja.properties</code>, and so on.</p>
<pre class="properties"><code>compiler.err.abstract.meth.cant.have.body=\
    abstract methods cannot have a body</code></pre>
<p>Each message is keyed in a way that indicates its purpose. <code>compiler.err.*</code> are for error messages, <code>compiler.warn.*</code> for warnings, and <code>compiler.misc.*</code> for <a href="https://www.youtube.com/watch?v=PaFSkWfFhO0">potpourri</a>.</p>
<p>There are comments above messages with placeholders to indicate the type of data that needs to be filled in.</p>
<pre class="properties"><code># 0: name
compiler.err.call.must.be.first.stmt.in.ctor=\
    call to {0} must be first statement in constructor

# 0: symbol kind, 1: name, 2: symbol kind, 3: type, 4: message segment
compiler.err.cant.apply.symbol.noargs=\
    {0} {1} in {2} {3} cannot be applied to given types;\n\
    reason: {4}</code></pre>
<p>These files get processed into Java classes by <a href="https://github.com/openjdk/jdk/blob/master/make/langtools/tools/propertiesparser/gen/ClassGenerator.java">this tooling</a>.</p>
<p>The classes that get generated are subclasses of <a href="https://github.com/openjdk/jdk/blob/ec0cc6300a02dd92b25d9072b8b3859dab583bbd/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JCDiagnostic.java#L52"><code>JCDiagnostic.DiagnosticInfo</code></a>, where <code>compiler.err.*</code> properties are turned into instances of <a href="https://github.com/openjdk/jdk/blob/ec0cc6300a02dd92b25d9072b8b3859dab583bbd/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JCDiagnostic.java#L576"><code>JCDiagnostic.Error</code></a>, <code>compiler.warn.*</code> into <a href="https://github.com/openjdk/jdk/blob/ec0cc6300a02dd92b25d9072b8b3859dab583bbd/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JCDiagnostic.java#L585C31-L585C38"><code>JCDiagnostic.Warning</code></a>, and so on.</p>
<p>The class <a href="https://gist.github.com/bowbahdoe/3f6270a96260daa841329d7ef4a998d7"><code>CompilerProperties</code></a> holds constants for each of these messages as well as static methods for the messages that had those special comments indicating that they need placeholders.</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="co">/**</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a> <span class="co">*</span> compiler<span class="co">.</span>err<span class="co">.</span>anonymous<span class="co">.</span>diamond<span class="co">.</span>method<span class="co">.</span>does<span class="co">.</span>not<span class="co">.</span>override<span class="co">.</span>superclass<span class="co">=\</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a> <span class="co">*</span>    method does not override or implement a method from a supertype<span class="co">\</span>n<span class="co">\</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a> <span class="co">*</span>    <span class="co">{0}</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a> <span class="co">*/</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">static</span> <span class="bu">Error</span> <span class="fu">AnonymousDiamondMethodDoesNotOverrideSuperclass</span><span class="op">(</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>        Fragment arg0</span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="kw">new</span> <span class="bu">Error</span><span class="op">(</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;compiler&quot;</span><span class="op">,</span> </span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;anonymous.diamond.method.does.not.override.superclass&quot;</span><span class="op">,</span> </span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>        arg0</span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a><span class="co">/**</span></span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a> <span class="co">*</span> compiler<span class="co">.</span>err<span class="co">.</span>array<span class="co">.</span>and<span class="co">.</span>receiver <span class="co">=\</span></span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a> <span class="co">*</span>    legacy array notation not allowed on receiver parameter</span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a> <span class="co">*/</span></span>
<span id="cb16-20"><a href="#cb16-20" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">static</span> <span class="dt">final</span> <span class="bu">Error</span> ArrayAndReceiver </span>
<span id="cb16-21"><a href="#cb16-21" aria-hidden="true" tabindex="-1"></a>        <span class="op">=</span> <span class="kw">new</span> <span class="bu">Error</span><span class="op">(</span><span class="st">&quot;compiler&quot;</span><span class="op">,</span> <span class="st">&quot;array.and.receiver&quot;</span><span class="op">);</span></span>
<span id="cb16-22"><a href="#cb16-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-23"><a href="#cb16-23" aria-hidden="true" tabindex="-1"></a><span class="co">// And so on</span></span></code></pre></div>
<h3 id="jcdiagnostic">JCDiagnostic</h3>
<p>I've been mostly talking about "error messages," but they are ontologically just one kind of "diagnostic".</p>
<p><code>JCDiagnostic</code> - short for java compiler diagnostic I'm pretty sure - is the representation <code>javac</code> has for diagnostic messages.</p>
<p>It stores references to all the information needed to construct a message shown to the user. This includes the <code>source</code> which the diagnostic references, the <code>position</code> in that source being referenced, as well as <a href="https://github.com/openjdk/jdk/blob/ec0cc6300a02dd92b25d9072b8b3859dab583bbd/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JCDiagnostic.java#L462">other miscellaneous metadata</a>.</p>
<p>A pointer to some text from the <code>compiler.properties</code> as well as the arguments needed for any placeholders in said text are stored in a sub-object under <code>diagnosticInfo</code>. These <code>DiagnosticInfo</code> objects come from what was generated in <a href="https://gist.github.com/bowbahdoe/3f6270a96260daa841329d7ef4a998d7"><code>CompilerProperties</code></a>.</p>
<p>The whole structure implements the <a href="https://docs.oracle.com/en/java/javase/20/docs/api/java.compiler/javax/tools/Diagnostic.html"><code>Diagnostic</code></a> interface, which is part of Java's public API.<sup><a href="#26">26</a></sup></p>
<h3 id="context">Context</h3>
<p>One of the more interesting concepts in <code>javac</code> is its <code>Context</code> mechanism.</p>
<p>In "regular" code that wants a singleton, you generally hide the constructor for your class and expose a single instance in some way.</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="dt">final</span> <span class="kw">class</span> Apple <span class="op">{</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Apple</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">final</span> Apple INSTANCE <span class="op">=</span> <span class="kw">new</span> <span class="fu">Apple</span><span class="op">();</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The other option is to make your class "normal" but rely on some dependency injection framework to automatically create, manage, and provide singular instances of that class.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="dt">final</span> <span class="kw">class</span> Apple <span class="op">{</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> UsageSite <span class="op">{</span></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> Apple apple<span class="op">;</span></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Inject</span></span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a>    <span class="fu">UsageSite</span><span class="op">(</span>Apple apple<span class="op">)</span> <span class="op">{</span></span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">apple</span> <span class="op">=</span> apple<span class="op">;</span></span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> </span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><code>javac</code> wants only single instances of many of its classes, but it also wants to allow for multiple instances of the compiler to run in parallel on the same JVM.</p>
<p>The solution they use is to have one class, <a href="https://github.com/openjdk/jdk/blob/master/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Context.java"><code>Context</code></a>, which holds a map of <code>Context.Key</code> to <code>Object</code>s.</p>
<p>Classes like <a href="https://github.com/openjdk/jdk/blob/master/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JCDiagnostic.java#L56"><code>JCDiagnostic.Factory</code></a> have factory methods that do a get-or-create with their own constant <code>Context.Key</code>s.</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">static</span> <span class="kw">class</span> Factory <span class="op">{</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">/**</span> The context key for the diagnostic factory<span class="co">. */</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">protected</span> <span class="dt">static</span> <span class="dt">final</span> <span class="bu">Context</span><span class="op">.</span><span class="fu">Key</span><span class="op">&lt;</span>JCDiagnostic<span class="op">.</span><span class="fu">Factory</span><span class="op">&gt;</span> diagnosticFactoryKey </span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>            <span class="op">=</span> <span class="kw">new</span> <span class="bu">Context</span><span class="op">.</span><span class="fu">Key</span><span class="op">&lt;&gt;();</span></span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>    <span class="co">/**</span> Get the Factory instance for this context<span class="co">. */</span></span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> Factory <span class="fu">instance</span><span class="op">(</span><span class="bu">Context</span> context<span class="op">)</span> <span class="op">{</span></span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a>        Factory instance <span class="op">=</span> context<span class="op">.</span><span class="fu">get</span><span class="op">(</span>diagnosticFactoryKey<span class="op">);</span></span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>instance <span class="op">==</span> <span class="kw">null</span><span class="op">)</span></span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a>            instance <span class="op">=</span> <span class="kw">new</span> <span class="fu">Factory</span><span class="op">(</span>context<span class="op">);</span></span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> instance<span class="op">;</span></span>
<span id="cb19-12"><a href="#cb19-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb19-13"><a href="#cb19-13" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb19-14"><a href="#cb19-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And then this <code>Context</code> is threaded to every class in the compiler that wants to get instances of those "contextual singletons" or themselves participate in the mechanism.</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">protected</span> <span class="fu">Flow</span><span class="op">(</span><span class="bu">Context</span> context<span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>    context<span class="op">.</span><span class="fu">put</span><span class="op">(</span>flowKey<span class="op">,</span> <span class="kw">this</span><span class="op">);</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>    names <span class="op">=</span> Names<span class="op">.</span><span class="fu">instance</span><span class="op">(</span>context<span class="op">);</span></span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>    log <span class="op">=</span> Log<span class="op">.</span><span class="fu">instance</span><span class="op">(</span>context<span class="op">);</span></span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a>    syms <span class="op">=</span> Symtab<span class="op">.</span><span class="fu">instance</span><span class="op">(</span>context<span class="op">);</span></span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a>    types <span class="op">=</span> <span class="bu">Types</span><span class="op">.</span><span class="fu">instance</span><span class="op">(</span>context<span class="op">);</span></span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a>    chk <span class="op">=</span> Check<span class="op">.</span><span class="fu">instance</span><span class="op">(</span>context<span class="op">);</span></span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a>    lint <span class="op">=</span> Lint<span class="op">.</span><span class="fu">instance</span><span class="op">(</span>context<span class="op">);</span></span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a>    rs <span class="op">=</span> Resolve<span class="op">.</span><span class="fu">instance</span><span class="op">(</span>context<span class="op">);</span></span>
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a>    diags <span class="op">=</span> JCDiagnostic<span class="op">.</span><span class="fu">Factory</span><span class="op">.</span><span class="fu">instance</span><span class="op">(</span>context<span class="op">);</span></span>
<span id="cb20-11"><a href="#cb20-11" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Source</span> source <span class="op">=</span> <span class="bu">Source</span><span class="op">.</span><span class="fu">instance</span><span class="op">(</span>context<span class="op">);</span></span>
<span id="cb20-12"><a href="#cb20-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="log">Log</h3>
<p>During compilation, if a problem is encountered anywhere, the compiler constructs and "emits" a diagnostic.</p>
<p>It does this by getting an instance of the <code>Log</code> contextual singleton and using the generated constants from <a href="https://gist.github.com/bowbahdoe/3f6270a96260daa841329d7ef4a998d7"><code>CompilerProperties</code></a>.</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Operators <span class="op">{</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">protected</span> <span class="fu">Operators</span><span class="op">(</span><span class="bu">Context</span> context<span class="op">)</span> <span class="op">{</span></span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>        context<span class="op">.</span><span class="fu">put</span><span class="op">(</span>operatorsKey<span class="op">,</span> <span class="kw">this</span><span class="op">);</span></span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>        syms <span class="op">=</span> Symtab<span class="op">.</span><span class="fu">instance</span><span class="op">(</span>context<span class="op">);</span></span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a>        names <span class="op">=</span> Names<span class="op">.</span><span class="fu">instance</span><span class="op">(</span>context<span class="op">);</span></span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a>        log <span class="op">=</span> Log<span class="op">.</span><span class="fu">instance</span><span class="op">(</span>context<span class="op">);</span></span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a>        types <span class="op">=</span> <span class="bu">Types</span><span class="op">.</span><span class="fu">instance</span><span class="op">(</span>context<span class="op">);</span></span>
<span id="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a>        noOpSymbol <span class="op">=</span> <span class="kw">new</span> <span class="fu">OperatorSymbol</span><span class="op">(</span></span>
<span id="cb21-11"><a href="#cb21-11" aria-hidden="true" tabindex="-1"></a>                names<span class="op">.</span><span class="fu">empty</span><span class="op">,</span> <span class="bu">Type</span><span class="op">.</span><span class="fu">noType</span><span class="op">,</span> <span class="op">-</span><span class="dv">1</span><span class="op">,</span> syms<span class="op">.</span><span class="fu">noSymbol</span></span>
<span id="cb21-12"><a href="#cb21-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb21-13"><a href="#cb21-13" aria-hidden="true" tabindex="-1"></a>        <span class="fu">initOperatorNames</span><span class="op">();</span></span>
<span id="cb21-14"><a href="#cb21-14" aria-hidden="true" tabindex="-1"></a>        <span class="fu">initUnaryOperators</span><span class="op">();</span></span>
<span id="cb21-15"><a href="#cb21-15" aria-hidden="true" tabindex="-1"></a>        <span class="fu">initBinaryOperators</span><span class="op">();</span></span>
<span id="cb21-16"><a href="#cb21-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb21-17"><a href="#cb21-17" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb21-18"><a href="#cb21-18" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb21-19"><a href="#cb21-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-20"><a href="#cb21-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-21"><a href="#cb21-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> OperatorSymbol <span class="fu">reportErrorIfNeeded</span><span class="op">(</span></span>
<span id="cb21-22"><a href="#cb21-22" aria-hidden="true" tabindex="-1"></a>            DiagnosticPosition pos<span class="op">,</span> </span>
<span id="cb21-23"><a href="#cb21-23" aria-hidden="true" tabindex="-1"></a>            Tag tag<span class="op">,</span> </span>
<span id="cb21-24"><a href="#cb21-24" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Type</span><span class="kw">...</span> args</span>
<span id="cb21-25"><a href="#cb21-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb21-26"><a href="#cb21-26" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>Stream<span class="op">.</span><span class="fu">of</span><span class="op">(</span>args<span class="op">).</span><span class="fu">noneMatch</span><span class="op">(</span>t <span class="op">-&gt;</span> </span>
<span id="cb21-27"><a href="#cb21-27" aria-hidden="true" tabindex="-1"></a>                t<span class="op">.</span><span class="fu">isErroneous</span><span class="op">()</span> <span class="op">||</span> t<span class="op">.</span><span class="fu">hasTag</span><span class="op">(</span>TypeTag<span class="op">.</span><span class="fu">NONE</span><span class="op">)</span></span>
<span id="cb21-28"><a href="#cb21-28" aria-hidden="true" tabindex="-1"></a>        <span class="op">))</span> <span class="op">{</span></span>
<span id="cb21-29"><a href="#cb21-29" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Name</span> opName <span class="op">=</span> <span class="fu">operatorName</span><span class="op">(</span>tag<span class="op">);</span></span>
<span id="cb21-30"><a href="#cb21-30" aria-hidden="true" tabindex="-1"></a>            JCDiagnostic<span class="op">.</span><span class="fu">Error</span> opError <span class="op">=</span> <span class="op">(</span>args<span class="op">.</span><span class="fu">length</span><span class="op">)</span> <span class="op">==</span> <span class="dv">1</span> <span class="op">?</span></span>
<span id="cb21-31"><a href="#cb21-31" aria-hidden="true" tabindex="-1"></a>                    Errors<span class="op">.</span><span class="fu">OperatorCantBeApplied</span><span class="op">(</span></span>
<span id="cb21-32"><a href="#cb21-32" aria-hidden="true" tabindex="-1"></a>                            opName<span class="op">,</span> args<span class="op">[</span><span class="dv">0</span><span class="op">]</span></span>
<span id="cb21-33"><a href="#cb21-33" aria-hidden="true" tabindex="-1"></a>                    <span class="op">)</span> <span class="op">:</span></span>
<span id="cb21-34"><a href="#cb21-34" aria-hidden="true" tabindex="-1"></a>                    Errors<span class="op">.</span><span class="fu">OperatorCantBeApplied1</span><span class="op">(</span></span>
<span id="cb21-35"><a href="#cb21-35" aria-hidden="true" tabindex="-1"></a>                            opName<span class="op">,</span> args<span class="op">[</span><span class="dv">0</span><span class="op">],</span> args<span class="op">[</span><span class="dv">1</span><span class="op">]</span></span>
<span id="cb21-36"><a href="#cb21-36" aria-hidden="true" tabindex="-1"></a>                    <span class="op">);</span></span>
<span id="cb21-37"><a href="#cb21-37" aria-hidden="true" tabindex="-1"></a>            log<span class="op">.</span><span class="fu">error</span><span class="op">(</span>pos<span class="op">,</span> opError<span class="op">);</span></span>
<span id="cb21-38"><a href="#cb21-38" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb21-39"><a href="#cb21-39" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> noOpSymbol<span class="op">;</span></span>
<span id="cb21-40"><a href="#cb21-40" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb21-41"><a href="#cb21-41" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb21-42"><a href="#cb21-42" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb21-43"><a href="#cb21-43" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><code>Log</code> internally holds onto the <code>JCDiagnostic.Factory</code> contextual singleton in order to construct <code>JCDiagnostic</code>s from <code>DiagnosticInfo</code>s like <code>JCDiagnostic.Error</code>.<sup><a href="#27">27</a></sup></p>
<div class="sourceCode" id="cb22"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Log <span class="kw">extends</span> AbstractLog <span class="op">{</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Log</span><span class="op">(</span></span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Context</span> context<span class="op">,</span> </span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Map</span><span class="op">&lt;</span>WriterKind<span class="op">,</span> <span class="bu">PrintWriter</span><span class="op">&gt;</span> writers</span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">(</span>JCDiagnostic<span class="op">.</span><span class="fu">Factory</span><span class="op">.</span><span class="fu">instance</span><span class="op">(</span>context<span class="op">));</span></span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a>        context<span class="op">.</span><span class="fu">put</span><span class="op">(</span>logKey<span class="op">,</span> <span class="kw">this</span><span class="op">);</span></span>
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">writers</span> <span class="op">=</span> writers<span class="op">;</span></span>
<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a>        <span class="at">@SuppressWarnings</span><span class="op">(</span><span class="st">&quot;unchecked&quot;</span><span class="op">)</span> <span class="co">// </span><span class="al">FIXME</span></span>
<span id="cb22-13"><a href="#cb22-13" aria-hidden="true" tabindex="-1"></a>        <span class="bu">DiagnosticListener</span><span class="op">&lt;?</span> <span class="kw">super</span> <span class="bu">JavaFileObject</span><span class="op">&gt;</span> dl <span class="op">=</span></span>
<span id="cb22-14"><a href="#cb22-14" aria-hidden="true" tabindex="-1"></a>                context<span class="op">.</span><span class="fu">get</span><span class="op">(</span><span class="bu">DiagnosticListener</span><span class="op">.</span><span class="fu">class</span><span class="op">);</span></span>
<span id="cb22-15"><a href="#cb22-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">diagListener</span> <span class="op">=</span> dl<span class="op">;</span></span>
<span id="cb22-16"><a href="#cb22-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-17"><a href="#cb22-17" aria-hidden="true" tabindex="-1"></a>        diagnosticHandler <span class="op">=</span> <span class="kw">new</span> <span class="fu">DefaultDiagnosticHandler</span><span class="op">();</span></span>
<span id="cb22-18"><a href="#cb22-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-19"><a href="#cb22-19" aria-hidden="true" tabindex="-1"></a>        messages <span class="op">=</span> JavacMessages<span class="op">.</span><span class="fu">instance</span><span class="op">(</span>context<span class="op">);</span></span>
<span id="cb22-20"><a href="#cb22-20" aria-hidden="true" tabindex="-1"></a>        messages<span class="op">.</span><span class="fu">add</span><span class="op">(</span>Main<span class="op">.</span><span class="fu">javacBundleName</span><span class="op">);</span></span>
<span id="cb22-21"><a href="#cb22-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-22"><a href="#cb22-22" aria-hidden="true" tabindex="-1"></a>        <span class="dt">final</span> Options options <span class="op">=</span> Options<span class="op">.</span><span class="fu">instance</span><span class="op">(</span>context<span class="op">);</span></span>
<span id="cb22-23"><a href="#cb22-23" aria-hidden="true" tabindex="-1"></a>        <span class="fu">initOptions</span><span class="op">(</span>options<span class="op">);</span></span>
<span id="cb22-24"><a href="#cb22-24" aria-hidden="true" tabindex="-1"></a>        options<span class="op">.</span><span class="fu">addListener</span><span class="op">(()</span> <span class="op">-&gt;</span> <span class="fu">initOptions</span><span class="op">(</span>options<span class="op">));</span></span>
<span id="cb22-25"><a href="#cb22-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb22-26"><a href="#cb22-26" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb22-27"><a href="#cb22-27" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb22-28"><a href="#cb22-28" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>All the diagnostics are then reported to a <code>DiagnosticHandler</code>.</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Log <span class="kw">extends</span> AbstractLog <span class="op">{</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">report</span><span class="op">(</span>JCDiagnostic diagnostic<span class="op">)</span> <span class="op">{</span></span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a>        diagnosticHandler<span class="op">.</span><span class="fu">report</span><span class="op">(</span>diagnostic<span class="op">);</span></span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-9"><a href="#cb23-9" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb23-10"><a href="#cb23-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="diagnosticformatter">DiagnosticFormatter</h3>
<p>There are some steps I am skipping, but eventually diagnostics flow from <code>DiagnosticHandler</code>s to a <code>DiagnosticFormatter</code> which is responsible for formatting the diagnostic for display.</p>
<p>There are a few implementations of <code>DiagnosticFormatter</code>, but the most relevant is <a href="https://github.com/openjdk/jdk/blob/ec0cc6300a02dd92b25d9072b8b3859dab583bbd/src/jdk.compiler/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java"><code>BasicDiagnosticFormatter</code></a>.</p>
<p>BasicDiagnosticFormatter has three formats that it recognizes. Diagnostics with a position, diagnostics without a position, and diagnostics originating in a class file for which the source is not available. It uses custom format strings that describe how it should display each of those diagnostics.</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span> <span class="dt">void</span> <span class="fu">initFormat</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>    <span class="fu">initFormats</span><span class="op">(</span><span class="st">&quot;%f:%l:%_%p%L%m&quot;</span><span class="op">,</span> <span class="st">&quot;%p%L%m&quot;</span><span class="op">,</span> <span class="st">&quot;%f:%_%p%L%m&quot;</span><span class="op">);</span></span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>For backwards compatibility reasons, <code>javac</code> also maintains an "old style" diagnostics format and a "normal" format. The old style diagnostics format can be enabled with compiler flags.</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">static</span> <span class="kw">class</span> BasicConfiguration </span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a>        <span class="kw">extends</span> SimpleConfiguration <span class="op">{</span></span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">BasicConfiguration</span><span class="op">(</span>Options options<span class="op">)</span> <span class="op">{</span></span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a>        <span class="fu">initIndentation</span><span class="op">();</span></span>
<span id="cb25-7"><a href="#cb25-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>options<span class="op">.</span><span class="fu">isSet</span><span class="op">(</span><span class="st">&quot;diags.legacy&quot;</span><span class="op">))</span></span>
<span id="cb25-8"><a href="#cb25-8" aria-hidden="true" tabindex="-1"></a>            <span class="fu">initOldFormat</span><span class="op">();</span></span>
<span id="cb25-9"><a href="#cb25-9" aria-hidden="true" tabindex="-1"></a>        <span class="bu">String</span> fmt <span class="op">=</span> options<span class="op">.</span><span class="fu">get</span><span class="op">(</span><span class="st">&quot;diags.layout&quot;</span><span class="op">);</span></span>
<span id="cb25-10"><a href="#cb25-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>fmt <span class="op">!=</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb25-11"><a href="#cb25-11" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>fmt<span class="op">.</span><span class="fu">equals</span><span class="op">(</span><span class="st">&quot;OLD&quot;</span><span class="op">))</span></span>
<span id="cb25-12"><a href="#cb25-12" aria-hidden="true" tabindex="-1"></a>                <span class="fu">initOldFormat</span><span class="op">();</span></span>
<span id="cb25-13"><a href="#cb25-13" aria-hidden="true" tabindex="-1"></a>            <span class="cf">else</span></span>
<span id="cb25-14"><a href="#cb25-14" aria-hidden="true" tabindex="-1"></a>                <span class="fu">initFormats</span><span class="op">(</span>fmt<span class="op">);</span></span>
<span id="cb25-15"><a href="#cb25-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb25-16"><a href="#cb25-16" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb25-17"><a href="#cb25-17" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb25-18"><a href="#cb25-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb25-19"><a href="#cb25-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The format strings consist of "meta characters" that represent different components of the diagnostic.<br />
The meta characters and other components are formatted independently and then concatenated.</p>
<p>For the normal format diagnostics with a position, each section of the string has a meaning as follows:</p>
<table>
<thead>
<tr class="header">
<th>Component</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>%f</td>
<td>Source file name</td>
</tr>
<tr class="even">
<td>:</td>
<td>A literal ":" character (U+003A)</td>
</tr>
<tr class="odd">
<td>%l</td>
<td>Line number for the diagnostic</td>
</tr>
<tr class="even">
<td>:</td>
<td>A literal ":" character (U+003A)</td>
</tr>
<tr class="odd">
<td>%_</td>
<td>A space character (U+0020)</td>
</tr>
<tr class="even">
<td>%p</td>
<td>The prefix for the diagnostic type: one of "Note: ", "warning: ", or "error: "</td>
</tr>
<tr class="odd">
<td>%L</td>
<td>The lint category for this diagnostic, if it is a lint</td>
</tr>
<tr class="even">
<td>%m</td>
<td>The localized message for the diagnostic</td>
</tr>
</tbody>
</table>
<p>After these components, the source code at the position of the diagnostic is inserted.</p>
<p>The source code is inserted at the end of the diagnostic if the diagnostic message is a single line, or the source code is inserted after the first line of the diagnostic message if it is multiline.<sup><a href="#28">28</a></sup></p>
<h2 id="structural-problems">Structural Problems</h2>
<p>If we want errors closer to what Rust has, the most important structural deficiency to tackle is <code>javac</code>'s message oriented-ness.</p>
<p>By that I am referring to the fact that every kind of diagnostic is "just a message." There is no clearly delineated place to put hints or other context.<sup><a href="#29">29</a></sup></p>
<p>This is something that has already had to be worked around. Take the following program.</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Object</span> o <span class="op">=</span> <span class="dv">123</span><span class="op">;</span></span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a>        <span class="cf">switch</span> <span class="op">(</span>o<span class="op">)</span> <span class="op">{</span></span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> <span class="bu">Integer</span> i <span class="op">-&gt;</span> <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>i<span class="op">);</span></span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a>            <span class="kw">default</span> <span class="op">-&gt;</span> <span class="op">{}</span></span>
<span id="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">};</span></span>
<span id="cb26-8"><a href="#cb26-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb26-9"><a href="#cb26-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This program uses pattern switches, which are a preview feature. This is the error you would get if you tried to compile it.</p>
<pre><code>Main.java:5: error: patterns in switch statements are a preview feature and are disabled by default.
          case Integer i -&gt; System.out.println(i);
               ^
  (use --enable-preview to enable patterns in switch statements)
1 error</code></pre>
<p>While you might look at this and think that there is already a dedicated place for hints, you would be wrong.</p>
<p>This message come from this entry in the <code>compiler.properties</code> file.</p>
<pre class="properties"><code># 0: message segment (feature)
compiler.err.preview.feature.disabled.plural=\
   {0} are a preview feature and are disabled by default.\n\
   (use --enable-preview to enable {0})</code></pre>
<p>You will notice that the only thing separating the hint to use the <code>--enable-preview</code> flag from the initial message is a newline.</p>
<p><a href="https://github.com/openjdk/jdk/blob/master/src/jdk.compiler/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java#L108"><code>BasicDiagnosticFormatter</code></a> just has a heuristic where it assumes that any newline in a message means that the lines following it should be displayed below the code that is the source of the issue.</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> BasicDiagnosticFormatter </span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>        <span class="kw">extends</span> AbstractDiagnosticFormatter <span class="op">{</span></span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">String</span> <span class="fu">formatMessage</span><span class="op">(</span>JCDiagnostic d<span class="op">,</span> <span class="bu">Locale</span> l<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb29-6"><a href="#cb29-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-7"><a href="#cb29-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>lines<span class="op">.</span><span class="fu">length</span> <span class="op">&gt;</span> <span class="dv">1</span></span>
<span id="cb29-8"><a href="#cb29-8" aria-hidden="true" tabindex="-1"></a>                <span class="op">&amp;&amp;</span> <span class="fu">getConfiguration</span><span class="op">()</span></span>
<span id="cb29-9"><a href="#cb29-9" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">getVisible</span><span class="op">()</span></span>
<span id="cb29-10"><a href="#cb29-10" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">contains</span><span class="op">(</span>DiagnosticPart<span class="op">.</span><span class="fu">DETAILS</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb29-11"><a href="#cb29-11" aria-hidden="true" tabindex="-1"></a>            currentIndentation <span class="op">+=</span> <span class="fu">getConfiguration</span><span class="op">()</span></span>
<span id="cb29-12"><a href="#cb29-12" aria-hidden="true" tabindex="-1"></a>                    <span class="op">.</span><span class="fu">getIndentation</span><span class="op">(</span>DiagnosticPart<span class="op">.</span><span class="fu">DETAILS</span><span class="op">);</span></span>
<span id="cb29-13"><a href="#cb29-13" aria-hidden="true" tabindex="-1"></a>            <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">1</span><span class="op">;</span> i <span class="op">&lt;</span> lines<span class="op">.</span><span class="fu">length</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb29-14"><a href="#cb29-14" aria-hidden="true" tabindex="-1"></a>                buf<span class="op">.</span><span class="fu">append</span><span class="op">(</span></span>
<span id="cb29-15"><a href="#cb29-15" aria-hidden="true" tabindex="-1"></a>                        <span class="st">&quot;</span><span class="sc">\n</span><span class="st">&quot;</span> <span class="op">+</span> <span class="fu">indent</span><span class="op">(</span>lines<span class="op">[</span>i<span class="op">],</span> currentIndentation<span class="op">)</span></span>
<span id="cb29-16"><a href="#cb29-16" aria-hidden="true" tabindex="-1"></a>                <span class="op">);</span></span>
<span id="cb29-17"><a href="#cb29-17" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb29-18"><a href="#cb29-18" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb29-19"><a href="#cb29-19" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb29-20"><a href="#cb29-20" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb29-21"><a href="#cb29-21" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> buf<span class="op">.</span><span class="fu">toString</span><span class="op">();</span></span>
<span id="cb29-22"><a href="#cb29-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb29-23"><a href="#cb29-23" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb29-24"><a href="#cb29-24" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb29-25"><a href="#cb29-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This causes a problem for diagnostics that have a newline that is not accounted for in that heuristic like the following.<sup><a href="#30">30</a></sup></p>
<pre class="properties"><code># TODO 308: make a better error message
compiler.err.this.as.identifier=\
    as of release 8, &#39;&#39;this&#39;&#39; is allowed as the parameter name for the receiver type only\n\
    which has to be the first parameter, and cannot be a lambda parameter</code></pre>
<p>If you construct a program that triggers this error like so:</p>
<div class="sourceCode" id="cb31"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> <span class="bu">Math</span> <span class="op">{</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">int</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> a<span class="op">,</span> <span class="dt">int</span> <span class="kw">this</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> a <span class="op">+</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>You will get the following.</p>
<pre><code>Math.java:2: error: as of release 8, &#39;this&#39; is allowed as the parameter name for the receiver type only
    static int add(int a, int this) {
                              ^
  which has to be the first parameter, and cannot be a lambda parameter
1 error</code></pre>
<p>Which feels at the very least unintentional.</p>
<p>There are other places where the pressure to say more than one thing in a message <a href="https://mail.openjdk.org/pipermail/compiler-dev/2022-February/019105.html">leads to larger irreconcilable inconsistencies</a>.<sup><a href="#31">31</a></sup></p>
<p>Every year or so there is someone who complains about <a href="https://mail.openjdk.org/pipermail/compiler-dev/2022-September/020420.html">a specific error on the mailing list</a>. This usually leads to a concrete improvement in whatever error they complain about, but the root problem here is structural.<sup><a href="#32">32</a></sup></p>
<h2 id="structural-solutions">Structural Solutions</h2>
<p>Structural problems always require structural solutions, so that's what we aimed to do.</p>
<p>The way Rust deals with this is with <a href="https://rustc-dev-guide.rust-lang.org/diagnostics.html">structured diagnostics</a>.<sup><a href="#33">33</a></sup> We translated that approach into the existing <code>JCDiagnostic</code> world by introducing two new concepts: <code>Help</code> and <code>Info</code>.</p>
<p>In our prototype all <code>JCDiagnostic</code>s now carry an optional <code>Help</code> and an optional <code>Info</code>.</p>
<div class="sourceCode" id="cb33"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> JCDiagnostic </span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a>        <span class="kw">implements</span> <span class="bu">Diagnostic</span><span class="op">&lt;</span><span class="bu">JavaFileObject</span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-5"><a href="#cb33-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> DiagnosticSource source<span class="op">;</span></span>
<span id="cb33-6"><a href="#cb33-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> DiagnosticPosition position<span class="op">;</span></span>
<span id="cb33-7"><a href="#cb33-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> DiagnosticInfo diagnosticInfo<span class="op">;</span></span>
<span id="cb33-8"><a href="#cb33-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="bu">Set</span><span class="op">&lt;</span>DiagnosticFlag<span class="op">&gt;</span> flags<span class="op">;</span></span>
<span id="cb33-9"><a href="#cb33-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> LintCategory lintCategory<span class="op">;</span></span>
<span id="cb33-10"><a href="#cb33-10" aria-hidden="true" tabindex="-1"></a>  </span>
<span id="cb33-11"><a href="#cb33-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> Info info<span class="op">;</span></span>
<span id="cb33-12"><a href="#cb33-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> Help help<span class="op">;</span></span>
<span id="cb33-13"><a href="#cb33-13" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb33-14"><a href="#cb33-14" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb33-15"><a href="#cb33-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="help">Help</h3>
<p>"Help"s carry two pieces of information.</p>
<div class="sourceCode" id="cb34"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> record <span class="fu">Help</span><span class="op">(</span></span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>        HelpFragment message<span class="op">,</span></span>
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a>        <span class="bu">List</span><span class="op">&lt;</span>SuggestedChange<span class="op">&gt;</span> suggestedChanges</span>
<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb34-5"><a href="#cb34-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb34-6"><a href="#cb34-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>First is a message. This is a fragment of text just like other <code>DiagnosticInfo</code>s and it is where the actual text of "use --enable-preview to enable patterns in switch statements" would come from.</p>
<div class="sourceCode" id="cb35"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">static</span> <span class="dt">final</span> <span class="kw">class</span> HelpFragment <span class="kw">extends</span> DiagnosticInfo <span class="op">{</span></span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">HelpFragment</span><span class="op">(</span><span class="bu">String</span> prefix<span class="op">,</span> <span class="bu">String</span> code<span class="op">,</span> <span class="bu">Object</span><span class="kw">...</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">(</span>HELP<span class="op">,</span> prefix<span class="op">,</span> code<span class="op">,</span> args<span class="op">);</span></span>
<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb35-5"><a href="#cb35-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The second is a list of zero or more suggested changes.</p>
<div class="sourceCode" id="cb36"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> record <span class="fu">SuggestedChange</span><span class="op">(</span></span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a>        DiagnosticSource source<span class="op">,</span></span>
<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a>        RangeDiagnosticPosition position<span class="op">,</span></span>
<span id="cb36-4"><a href="#cb36-4" aria-hidden="true" tabindex="-1"></a>        <span class="bu">String</span> replacement<span class="op">,</span></span>
<span id="cb36-5"><a href="#cb36-5" aria-hidden="true" tabindex="-1"></a>        Applicability applicability</span>
<span id="cb36-6"><a href="#cb36-6" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb36-7"><a href="#cb36-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb36-8"><a href="#cb36-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>These <code>SuggestedChange</code>s all know where in the source they are referring to, what replacements to make in order to apply the suggestion, and to what degree the suggestion is mechanically applicable.</p>
<div class="sourceCode" id="cb37"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">enum</span> Applicability <span class="op">{</span></span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a>    MACHINE_APPLICABLE<span class="op">,</span></span>
<span id="cb37-3"><a href="#cb37-3" aria-hidden="true" tabindex="-1"></a>    HAS_PLACEHOLDERS<span class="op">,</span></span>
<span id="cb37-4"><a href="#cb37-4" aria-hidden="true" tabindex="-1"></a>    <span class="bu">UNKNOWN</span></span>
<span id="cb37-5"><a href="#cb37-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Help messages would include:</p>
<ul>
<li>Suggesting importing a class or enum</li>
<li>Suggesting fixing a misspelled identifier to a similarly named identifier that actually exists</li>
<li>Explaining that an identifier doesn't exist, but it does exist in a class that is accessible</li>
<li>Suggesting changing arguments to a function to satisfy the signature</li>
</ul>
<h3 id="info">Info</h3>
<p><code>Info</code>s are similar in spirit to <code>Help</code>s, but they only provide helpful context. They do not suggest a user change their code in any concrete way.</p>
<div class="sourceCode" id="cb38"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> record <span class="fu">Info</span><span class="op">(</span></span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a>        InfoFragment message<span class="op">,</span></span>
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a>        <span class="bu">List</span><span class="op">&lt;</span>InfoPosition<span class="op">&gt;</span> positions</span>
<span id="cb38-4"><a href="#cb38-4" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb38-5"><a href="#cb38-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>An <code>Info</code> holds a text fragment and a list of all the places in the code that are relevant to that message.</p>
<p>Info messages would include:</p>
<ul>
<li>Displaying related function signatures to show the programmer the expected signature</li>
<li>Displaying the declaration of a class, field, or local variable to show what type was expected</li>
<li>Providing more detailed information as to why something is not allowed, such as <code>assert</code> becoming a keyword in Java 1.4</li>
<li>Displaying supplementary information related to valid values</li>
</ul>
<h3 id="compilerproperties-1">compiler.properties</h3>
<p>In order to get the text for help and info messages in a localization friendly way, we piggybacked on the existing conventions in the <code>compiler.properties</code> files.</p>
<p>We updated the tooling so that properties keyed by <code>compiler.help.*</code> and <code>compiler.info.*</code> are translated into fragments inside <code>CompilerProperties</code> the same as was done for <code>compiler.error.*</code> and company.</p>
<pre class="properties"><code>compiler.info.function.declared.here=\
    function declared here

# ...

# 0: kind name, 1: symbol
compiler.help.similar.symbol=\
    a similarly named {0} exists: {1}</code></pre>
<div class="sourceCode" id="cb40"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> CompilerProperties <span class="op">{</span></span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">public</span> <span class="dt">static</span> <span class="kw">class</span> Infos <span class="op">{</span></span>
<span id="cb40-3"><a href="#cb40-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb40-4"><a href="#cb40-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-5"><a href="#cb40-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">/**</span></span>
<span id="cb40-6"><a href="#cb40-6" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> compiler<span class="co">.</span>info<span class="co">.</span>function<span class="co">.</span>declared<span class="co">.</span>here<span class="co">=\</span></span>
<span id="cb40-7"><a href="#cb40-7" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span>    function declared here</span>
<span id="cb40-8"><a href="#cb40-8" aria-hidden="true" tabindex="-1"></a>     <span class="co">*/</span></span>
<span id="cb40-9"><a href="#cb40-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">final</span> InfoFragment FunctionDeclaredHere</span>
<span id="cb40-10"><a href="#cb40-10" aria-hidden="true" tabindex="-1"></a>            <span class="op">=</span> <span class="kw">new</span> <span class="fu">InfoFragment</span><span class="op">(</span><span class="st">&quot;compiler&quot;</span><span class="op">,</span> <span class="st">&quot;function.declared.here&quot;</span><span class="op">);</span></span>
<span id="cb40-11"><a href="#cb40-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-12"><a href="#cb40-12" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb40-13"><a href="#cb40-13" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb40-14"><a href="#cb40-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">public</span> <span class="dt">static</span> <span class="kw">class</span> Helps <span class="op">{</span></span>
<span id="cb40-15"><a href="#cb40-15" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb40-16"><a href="#cb40-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-17"><a href="#cb40-17" aria-hidden="true" tabindex="-1"></a>    <span class="co">/**</span></span>
<span id="cb40-18"><a href="#cb40-18" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> compiler<span class="co">.</span>help<span class="co">.</span>similar<span class="co">.</span>symbol<span class="co">=\</span></span>
<span id="cb40-19"><a href="#cb40-19" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span>    a similarly named <span class="co">{0}</span> exists<span class="co">:</span> <span class="co">{1}</span></span>
<span id="cb40-20"><a href="#cb40-20" aria-hidden="true" tabindex="-1"></a>     <span class="co">*/</span></span>
<span id="cb40-21"><a href="#cb40-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> HelpFragment <span class="fu">SimilarSymbol</span><span class="op">(</span></span>
<span id="cb40-22"><a href="#cb40-22" aria-hidden="true" tabindex="-1"></a>            KindName arg0<span class="op">,</span> Symbol arg1</span>
<span id="cb40-23"><a href="#cb40-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb40-24"><a href="#cb40-24" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> <span class="kw">new</span> <span class="fu">HelpFragment</span><span class="op">(</span></span>
<span id="cb40-25"><a href="#cb40-25" aria-hidden="true" tabindex="-1"></a>              <span class="st">&quot;compiler&quot;</span><span class="op">,</span> <span class="st">&quot;similar.symbol&quot;</span><span class="op">,</span> arg0<span class="op">,</span> arg1</span>
<span id="cb40-26"><a href="#cb40-26" aria-hidden="true" tabindex="-1"></a>      <span class="op">);</span></span>
<span id="cb40-27"><a href="#cb40-27" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb40-28"><a href="#cb40-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-29"><a href="#cb40-29" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb40-30"><a href="#cb40-30" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb40-31"><a href="#cb40-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>At the sites where diagnostics are emitted, there <code>Help</code>s and <code>Info</code>s can then be attached to a <code>JCDiagnostic</code> by referencing these generated classes and using the <code>withHelp</code> or <code>withInfo</code> methods.</p>
<div class="sourceCode" id="cb41"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> SymbolNotFoundError <span class="kw">extends</span> ResolveError <span class="op">{</span></span>
<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb41-3"><a href="#cb41-3" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb41-4"><a href="#cb41-4" aria-hidden="true" tabindex="-1"></a>    JCDiagnostic <span class="fu">getDiagnostic</span><span class="op">(</span></span>
<span id="cb41-5"><a href="#cb41-5" aria-hidden="true" tabindex="-1"></a>            JCDiagnostic<span class="op">.</span><span class="fu">DiagnosticType</span> dkind<span class="op">,</span></span>
<span id="cb41-6"><a href="#cb41-6" aria-hidden="true" tabindex="-1"></a>            DiagnosticPosition pos<span class="op">,</span></span>
<span id="cb41-7"><a href="#cb41-7" aria-hidden="true" tabindex="-1"></a>            Env<span class="op">&lt;</span>AttrContext<span class="op">&gt;</span> env<span class="op">,</span></span>
<span id="cb41-8"><a href="#cb41-8" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Type</span> site<span class="op">,</span></span>
<span id="cb41-9"><a href="#cb41-9" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Name</span> name<span class="op">,</span></span>
<span id="cb41-10"><a href="#cb41-10" aria-hidden="true" tabindex="-1"></a>            <span class="bu">List</span><span class="op">&lt;</span><span class="bu">Type</span><span class="op">&gt;</span> argtypes<span class="op">,</span></span>
<span id="cb41-11"><a href="#cb41-11" aria-hidden="true" tabindex="-1"></a>            <span class="bu">List</span><span class="op">&lt;</span><span class="bu">Type</span><span class="op">&gt;</span> typeargtypes</span>
<span id="cb41-12"><a href="#cb41-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb41-13"><a href="#cb41-13" aria-hidden="true" tabindex="-1"></a>      <span class="co">// ...</span></span>
<span id="cb41-14"><a href="#cb41-14" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>hasLocation<span class="op">)</span> <span class="op">{</span></span>
<span id="cb41-15"><a href="#cb41-15" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb41-16"><a href="#cb41-16" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>suggestMember <span class="op">!=</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb41-17"><a href="#cb41-17" aria-hidden="true" tabindex="-1"></a>            diag <span class="op">=</span> diag<span class="op">.</span><span class="fu">withHelp</span><span class="op">(</span></span>
<span id="cb41-18"><a href="#cb41-18" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">new</span> <span class="fu">Help</span><span class="op">(</span></span>
<span id="cb41-19"><a href="#cb41-19" aria-hidden="true" tabindex="-1"></a>                            Helps<span class="op">.</span><span class="fu">SimilarSymbol</span><span class="op">(</span></span>
<span id="cb41-20"><a href="#cb41-20" aria-hidden="true" tabindex="-1"></a>                                    Kinds<span class="op">.</span><span class="fu">kindName</span><span class="op">(</span>suggestMember<span class="op">),</span></span>
<span id="cb41-21"><a href="#cb41-21" aria-hidden="true" tabindex="-1"></a>                                    suggestMember</span>
<span id="cb41-22"><a href="#cb41-22" aria-hidden="true" tabindex="-1"></a>                            <span class="op">)</span></span>
<span id="cb41-23"><a href="#cb41-23" aria-hidden="true" tabindex="-1"></a>                    <span class="op">)</span></span>
<span id="cb41-24"><a href="#cb41-24" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb41-25"><a href="#cb41-25" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb41-26"><a href="#cb41-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb41-27"><a href="#cb41-27" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> diag<span class="op">;</span></span>
<span id="cb41-28"><a href="#cb41-28" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb41-29"><a href="#cb41-29" aria-hidden="true" tabindex="-1"></a>            </span>
<span id="cb41-30"><a href="#cb41-30" aria-hidden="true" tabindex="-1"></a>      <span class="co">// ...</span></span>
<span id="cb41-31"><a href="#cb41-31" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb41-32"><a href="#cb41-32" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><a href="https://github.com/McCue-Software-Solutions/jdk/blob/hints/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java">The logic in the code above</a> produces errors like the following.</p>
<pre><code>Test.java:5: error: cannot find symbol
        TetsingMetho();
        ^
  symbol:   method TetsingMetho()
  location: class Test
help: a similarly named method exists: TestingMethod()</code></pre>
<p>What is important here isn't the analysis being performed or how it is displayed exactly. Those are all things that can be disputed by reasonable people. It's that there is now a place to give that sort of advice.</p>
<p>With just that little bit of structure, it suddenly becomes tractable to build a feature like "suggest methods with similar names."</p>
<h3 id="diagnosticformatter-1">DiagnosticFormatter</h3>
<p>In order to retrofit <code>BasicDiagnosticFormatter</code> to display help and info messages, we needed to add some more meta characters to its format strings.</p>
<div class="sourceCode" id="cb43"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb43-1"><a href="#cb43-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> BasicDiagnosticFormatter </span>
<span id="cb43-2"><a href="#cb43-2" aria-hidden="true" tabindex="-1"></a>        <span class="kw">extends</span> AbstractDiagnosticFormatter <span class="op">{</span></span>
<span id="cb43-3"><a href="#cb43-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb43-4"><a href="#cb43-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="kw">class</span> BasicConfiguration </span>
<span id="cb43-5"><a href="#cb43-5" aria-hidden="true" tabindex="-1"></a>            <span class="kw">extends</span> SimpleConfiguration <span class="op">{</span></span>
<span id="cb43-6"><a href="#cb43-6" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb43-7"><a href="#cb43-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">void</span> <span class="fu">initFormatWithInfoAndHelp</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb43-8"><a href="#cb43-8" aria-hidden="true" tabindex="-1"></a>            <span class="fu">initFormats</span><span class="op">(</span></span>
<span id="cb43-9"><a href="#cb43-9" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;%f:%l:%_%p%L%m%i%h&quot;</span><span class="op">,</span></span>
<span id="cb43-10"><a href="#cb43-10" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;%p%L%m%i%h&quot;</span><span class="op">,</span></span>
<span id="cb43-11"><a href="#cb43-11" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;%f:%_%p%L%m%i%h&quot;</span></span>
<span id="cb43-12"><a href="#cb43-12" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb43-13"><a href="#cb43-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb43-14"><a href="#cb43-14" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb43-15"><a href="#cb43-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb43-16"><a href="#cb43-16" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb43-17"><a href="#cb43-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<table>
<thead>
<tr class="header">
<th>Component</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>%h</td>
<td>Help Message</td>
</tr>
<tr class="even">
<td>%i</td>
<td>Info Message</td>
</tr>
</tbody>
</table>
<p>This has the very convenient property that, at least for this design, we can put the new reporting format behind a flag.</p>
<div class="sourceCode" id="cb44"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb44-1"><a href="#cb44-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> BasicDiagnosticFormatter </span>
<span id="cb44-2"><a href="#cb44-2" aria-hidden="true" tabindex="-1"></a>        <span class="kw">extends</span> AbstractDiagnosticFormatter <span class="op">{</span></span>
<span id="cb44-3"><a href="#cb44-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb44-4"><a href="#cb44-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="kw">class</span> BasicConfiguration </span>
<span id="cb44-5"><a href="#cb44-5" aria-hidden="true" tabindex="-1"></a>            <span class="kw">extends</span> SimpleConfiguration <span class="op">{</span></span>
<span id="cb44-6"><a href="#cb44-6" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb44-7"><a href="#cb44-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb44-8"><a href="#cb44-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="fu">BasicConfiguration</span><span class="op">(</span>Options options<span class="op">)</span> <span class="op">{</span></span>
<span id="cb44-9"><a href="#cb44-9" aria-hidden="true" tabindex="-1"></a>            <span class="co">// ...</span></span>
<span id="cb44-10"><a href="#cb44-10" aria-hidden="true" tabindex="-1"></a>          </span>
<span id="cb44-11"><a href="#cb44-11" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>options<span class="op">.</span><span class="fu">isSet</span><span class="op">(</span><span class="co">/* ... */</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb44-12"><a href="#cb44-12" aria-hidden="true" tabindex="-1"></a>                <span class="fu">initFormatWithInfoAndHelp</span><span class="op">();</span></span>
<span id="cb44-13"><a href="#cb44-13" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb44-14"><a href="#cb44-14" aria-hidden="true" tabindex="-1"></a>                <span class="fu">initFormat</span><span class="op">();</span></span>
<span id="cb44-15"><a href="#cb44-15" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb44-16"><a href="#cb44-16" aria-hidden="true" tabindex="-1"></a>            </span>
<span id="cb44-17"><a href="#cb44-17" aria-hidden="true" tabindex="-1"></a>            <span class="co">// ...</span></span>
<span id="cb44-18"><a href="#cb44-18" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb44-19"><a href="#cb44-19" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb44-20"><a href="#cb44-20" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">void</span> <span class="fu">initFormat</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb44-21"><a href="#cb44-21" aria-hidden="true" tabindex="-1"></a>            <span class="fu">initFormats</span><span class="op">(</span></span>
<span id="cb44-22"><a href="#cb44-22" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;%f:%l:%_%p%L%m&quot;</span><span class="op">,</span></span>
<span id="cb44-23"><a href="#cb44-23" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;%p%L%m&quot;</span><span class="op">,</span></span>
<span id="cb44-24"><a href="#cb44-24" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;%f:%_%p%L%m&quot;</span></span>
<span id="cb44-25"><a href="#cb44-25" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb44-26"><a href="#cb44-26" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb44-27"><a href="#cb44-27" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb44-28"><a href="#cb44-28" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">void</span> <span class="fu">initFormatWithInfoAndHelp</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb44-29"><a href="#cb44-29" aria-hidden="true" tabindex="-1"></a>            <span class="fu">initFormats</span><span class="op">(</span></span>
<span id="cb44-30"><a href="#cb44-30" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;%f:%l:%_%p%L%m%i%h&quot;</span><span class="op">,</span></span>
<span id="cb44-31"><a href="#cb44-31" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;%p%L%m%i%h&quot;</span><span class="op">,</span></span>
<span id="cb44-32"><a href="#cb44-32" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;%f:%_%p%L%m%i%h&quot;</span></span>
<span id="cb44-33"><a href="#cb44-33" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb44-34"><a href="#cb44-34" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb44-35"><a href="#cb44-35" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb44-36"><a href="#cb44-36" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb44-37"><a href="#cb44-37" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb44-38"><a href="#cb44-38" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="remaining-work">Remaining Work</h3>
<p>There are many things left unfinished.</p>
<ul>
<li>Some of our modifications show suboptimal positions in particularly complex cases. Fixing this involves passing more context down through the compiler and keeping more positional information.</li>
<li>The wording of our additional info can likely be improved to flow better with the writing style of the existing errors.</li>
<li>The messages that make use of the newline heuristic, especially the <code>--enable-preview</code> ones, can be moved to having an attached <code>Help</code>. Doing so would mean that either the keys for those messages would need to be duplicated or the original messages would be degraded if the flag for this were turned off.</li>
<li>Almost every error and warning could use tone audit.</li>
<li>In general, the compiler tends to drop information between phases. We didn't find a system other than to go case by case. and just thread through the information we need as we need it.</li>
<li><code>compiler.err.cant.apply.symbol</code> is several different errors in a trench-coat.</li>
<li>Ich spreche kein Deutsch.</li>
<li>私は日本語を話しません</li>
<li>我不会说中文</li>
<li>And much, much more</li>
</ul>
<p>But I am satisfied with the progress we made. You can find a bestiary of the specific errors that were tackled <a href="https://docs.google.com/document/d/10QlIIvYKkrxcWs_GMxQMRXhakYWBYiYanbetHEWIji0/edit?usp=sharing">here</a>.</p>
<h2 id="call-to-action">Call to Action</h2>
<p>Submitting a JEP, while technically an open process, in practice seems to be helped by having more free time than is reasonable<sup><a href="#34">34</a></sup>, being paid to work on OpenJDK, or social capital.</p>
<p>If you want this work to continue, you should voice your support on <a href="https://mail.openjdk.org/pipermail/compiler-dev/"><a href="mailto:compiler-dev@openjdk.org">compiler-dev@openjdk.org</a></a> or in whatever forum you think would have the most impact. If you do want to use the mailing lists, take note that you need to sign up for the mailing list yourself in order for your emails to go through.</p>
<p>If you are interested in continuing this work yourself, the current state of this is on the <code>hints</code> branch <a href="https://github.com/mccue-software-solutions/jdk/tree/hints">here</a>. There is quite a bit left to do and a lot of arcane knowledge we picked up along the way, so please reach out if you choose this path. I can at least help you get set up in IntelliJ to build the JDK.<sup><a href="#35">35</a></sup></p>
<p>If you are in a position of authority at of one of the large companies that has dedicated staff working on OpenJDK, hire some or all of us. Failing that, dedicate other person-power to the issue.<sup><a href="#36">36</a></sup><sup><a href="#37">37</a></sup></p>
<h2 id="jep">JEP</h2>
<details>
  <summary>JEP Draft</summary>

<h2 id="summary">Summary</h2>
<p>Enhance the Java compiler with errors that are easier to read and understand.</p>
<h2 id="goals">Goals</h2>
<p>The primary goal is to make the reference Java compiler competitive with the compilers for other languages in terms of the helpfulness of its error messages.</p>
<p>This is proposed to be accomplished by</p>
<ul>
<li>Enhancing the compiler so that it can reliably display hints to the user for how to resolve issues.</li>
<li>Enhancing the compiler so that it can provide information to the user that indicates why an error occurred.</li>
<li>Auditing the tone of th existing set of messages.</li>
</ul>
<h2 id="non-goals">Non-Goals</h2>
<p>It is not a priority to alter the set of warnings and lints that the compiler reports on, though that could feasibly come as a future JEP.</p>
<p>It is also not a priority to give this same treatment to other tools, such as <code>jar</code>, <code>javadoc</code>, or <code>jlink</code>, though that could feasibly come as a future JEP.</p>
<p>It is not a goal to provide an equivalent to the <code>--explain</code> flag present in other compilers or to assign error conditions unique numeric codes, though that could feasibly come as a future JEP.</p>
<p>It is not a goal to provide a structured output for consumption by IDEs or tools, though that could feasibly come as a future JEP.</p>
<p>It is not an explicit goal to enhance the API provided by <code>java.compiler</code> to allow annotation processors and other user code to introspect on any new functionality, though that might fall out of the design process.</p>
<p>It is a non-goal to completely refactor the entire javac diagnostic process or to modify every single error message. Some are fine as they are.</p>
<p>It is not a goal to provide any specific kind of analysis, though it is assumed that some new analyses should be performed.</p>
<h2 id="description">Description</h2>
<p>(The following represents a preliminary design and is subject to change)</p>
<p>We propose modifying the structure of the <code>javac</code>'s diagnostic system by adding <code>Help</code> and <code>Info</code> structures to <code>JCDiagnostic</code>.</p>
<p><code>Help</code>s would provide information to users with suggestions on how to change their code. The localized text for <code>Help</code>s would be provided by properties keyed under <code>compiler.help.*</code>. Information in a help message should be actionable information or ideally a functional code suggestion.</p>
<p>Each code suggestion in a help contains a range in the source code that it applies to, a string to replace the source code with, and an enum representing whether the suggestion can be applied automatically, needs some manual work, or can’t be automatically applied.</p>
<p><code>Info</code>s would provide useful context to users on why they are receiving a given warning or error. The localized text for <code>Info</code>s would be provided by properties keyed under <code>compiler.info.*</code>.</p>
<p>The code to format diagnostics for display will also be updated to support embedding these two pieces of information and existing messages will be updated to make appropriate use of the new structure.</p>
<h2 id="alternatives">Alternatives</h2>
<ul>
<li><p>Do nothing. There is significant opportunity cost in any restructuring, and it might be the case that a restructuring of error messages do not provide enough practical benefit to be worth the effort.</p></li>
<li><p>Wait. It's certainly possible that the ideas currently available represent a local maxima of compiler design and that going toward them would be a misstep.</p></li>
<li><p>Defer to the community. It might be possible to accomplish most of these goals with an alternative compiler implementation. <code>javac</code>'s primary purpose is to be a reference compiler for the JLS. This would limit its exposure though, especially to beginners.</p></li>
<li><p>Leave it to IDEs. Visual feedback is, in some ways, preferable to textual feedback. Not all categories of users, particularly the users for which feedback matters the most (students, beginners, etc.), are able or willing to use IDEs.</p></li>
</ul>
<h2 id="testing">Testing</h2>
<p>The compiler should still give errors in the same situations before changes as after and still emit identical bytecode. The existing set of <code>jtreg</code> tests should be enough to validate that, though they will need to be updated to test for items related the new structure.</p>
<p>Testing for whether errors are actually useful is a social problem.</p>
<h2 id="risks-and-assumptions">Risks and Assumptions</h2>
<p>Localization will likely pose a challenge. The current corpus of error messages is significant and would need to be updated.</p>
<p>There are also undoubtedly tools in the ecosystem that function off of parsing the exact structure emitted by javac. Ultimately either they will need to be broken, the new functionality would have to be hidden behind a compiler flag, or the old functionality will have to be explicitly enabled.</p>
<p>It is possible that keeping track of the information needed to provide a good hint to the user could increase the memory footprint of the compiler during successful runs.</p>
<p>The speed of the compiler could be also affected. Ideally this could be minimized, but it is hard to know in what way until an MVP is in place.</p>
<h2 id="dependencies">Dependencies</h2>
<p>What hints should be given in which scenarios should conceptually be driven by data on what error conditions are actually hit. This can be further stratified by which errors are hit by different groups such as "total beginners", "working developers", etc. If there is not already a corpus of this sort of data then it would be prudent to try to organize a way to gather it.</p>
<p>There are active projects like Valhalla and Amber that will likely result in significant updates to the compiler. It might be necessary to wait for those changes to "blow over" before there is enough stability to do make structural changes. These projects also alter the semantics of the language, so they could feasibly affect what an ideal error messages would be.</p>
</details>

<p id="1" style="font-size: 14px">1: And well over a year of
mental illness from me.</p>
<p id="2" style="font-size: 14px">2: This definition isn't exactly accurate. JITs are compilers
too but they do their work in memory. There is no artifact to speak of, but I think its close enough
to what most people think of when they think of a compiler. The <a href="https://en.wikipedia.org/wiki/Compiler">wikipedia entry for compilers</a>
has a more accurate definition.</p>
<p id="3" style="font-size: 14px">3: Languages like C, C++, Rust, Zig, etc. also care quite a lot about
optimizations. It might be a little disingenuous of me to gloss over that, but this post is about a language
backed by a VM. The real optimizations happen at runtime and dwelling too long on that felt a bit much.</p>
<p id="4" style="font-size: 14px">4: The Elm language is closest in spirit to Haskell. All code needs
to be purely functional, the type system is strong, and the syntax is similar as well. What sets it apart
is that it doesn't have Haskell classic features like type-classes, do-notation, or `IO` monads. Good case study in
addition by subtraction.</p>
<p id="5" style="font-size: 14px">5: I'm attributing causation here, but I don't actually have strong proof that
the better error messages work benefited from Elm being small and focused. At least in my brain it tracks
though. Evan Czaplicki is but one man. Doing what he did but with C++ would have been infeasible.</p>
<p id="6" style="font-size: 14px">6: If twitter dies, just know that these links were to people saying nice things about Elm.</p>
<p id="7" style="font-size: 14px">7: This isn't actually that good of an argument in and of itself. I know that. 
I just find it rhetorically compelling. I love Elden Ring, but I don't want to be playing it at every day at my job
and I wouldn't want to force someone to deal with all the flavors of "lol, get rekt" it entails.</p>
<p id="8" style="font-size: 14px">8: "Basic analysis" is doing a lot of legwork in that sentence. Its basic in
large part because of the simplicity of the Elm language. Libraries, modules, and source files work
in precisely one way. Doing the same kind of analysis with classes on the class-path, modules on the module-path,
and code yet to be compiled might be quite a bit harder for Java.</p>
<p id="9" style="font-size: 14px">9: I'm doing it for the example directly below, but it's hard to get the pandoc
renderer which makes this site to like inline spans with color information. I'll only do that work
when I'm talking about coloring and, because I'm writing these footnotes as I go, I won't rule
out just falling back to images.</p>
<p id="10" style="font-size: 14px">10: This is nowhere near a complete explanation of the borrow checker, how it functions,
or what it accomplishes. For that you should read the Rust book or any of the many good references online.
I'm trusting that most readers will have a passing familiarity.</p>
<p id="11" style="font-size: 14px">11: This explanation conflates a little bit borrow checking and lifetime checking.
There are also no "borrows" that happen in the following code, but I've seen "the borrow checker" used interchangably
with what could be called "the lifetime checker" and at the level of zoom this post is at I think the difference isn't that crucial.
Doesn't help that I'm not exactly sure where lines for these terms are regardless.</p>
<p id="12" style="font-size: 14px">12: I think there is decent evidence for this, but it is really hard to prove.</p>
<p id="#13" style="font-size: 14px">13: The initial design for which seems to have been directly inspired by Elm.</p>
<p id="14" style="font-size: 14px">14: During the aforementioned "fighting the borrow checker" phase.</p>
<p id="15" style="font-size: 14px">15: You could probably make this same argument for any part of the Rust ecosystem like the polish
in Cargo, Clippy, etc.</p>
<p id="16" style="font-size: 14px">16: Compare how "cannot find symbol" sounds versus "cannot find value `A` in this scope".
The difference is subtle, but it matters.</p>
<p id="17" style="font-size: 14px">17: IntelliJ does this with a "light bulb" that appears when you hover over a bit of malformed code
that contains a contextual menu with potential fixes.</p>
<p id="18" style="font-size: 14px">18: I do not remember exactly what they are called, but my old High School had a bunch of machines that
were basically just empty boxes that connected to a shared Windows server.</p>
<p id="19" style="font-size: 14px">19: I hesitate to mention this, but the CS gender ratio is absolutely wack <a href="https://www.smithsonianmag.com/smithsonian-institution/margaret-hamilton-led-nasa-software-team-landed-astronauts-moon-180971575/">when famously it did not start out that way</a>.
There are lots of shitty reasons for this, and I'm not saying that its Java's fault, but it is
worthy of note that Java has been an <a href="https://www.infoworld.com/article/2076867/educators-embrace-java.html">extremely popular first language in education ever since its release</a>
and as a consequence <a href="https://www.aei.org/carpe-diem/chart-of-the-day-the-declining-female-share-of-computer-science-degrees-from-28-to-18/"> has presided over this depressing chart</a>.
I can't prove it<sup><a href="#20">20</a></sup> but I believe
that small frictions like `public static void main` and obtuse error messages filter students down to the demographics
that are willing to deal with that sort of hostility.</p>
<p id="20" style="font-size: 14px">20: I haven't been able to find any meaningful research to back up or refute this claim. That must be because there is none,
I'm bad at searching, or I've unconsciously ignored evidence that refutes my point.</p>
<p id="21" style="font-size: 14px">21: "I'm right and science hasn't caught up to how right I am."</p>
<p id="22" style="font-size: 14px">22: I will later be shown that I was at least somewhat wrong about this.</p>
<p id="23" style="font-size: 14px">23: No relation.</p>
<p id="24" style="font-size: 14px">24:
These are the original <a href="https://docs.google.com/presentation/d/1JnqZwxYHAFI80JjHcoU7e8SI8U-I3CXnA1KM0Ryt4Q8/edit?usp=sharing">PowerPoint</a>
and <a href="https://docs.google.com/document/d/10QlIIvYKkrxcWs_GMxQMRXhakYWBYiYanbetHEWIji0/edit?usp=sharing">Design Document</a> they produced for their class.
</p>
<p id="25" style="font-size: 14px">25: Other compilers like ECJ exist, but being the default means always mean javac is going to be what most people use. That's why the focus was there, it is where changes can do the most good.</p>
<p id="26" style="font-size: 14px">26: Something that is merciful about wanting to change the internals of javac is that things like <code>Diagnostic</code>
are all I need to worry about. If we're not changing the set of programs accepted by the Java compiler and aren't looking
to change supported APIs, then we should be able to avoid sanction by Java's backwards compatibility policies.</p>
<p id="27" style="font-size: 14px">27: The FIXME in this code is from 2011.</p>
<p id="28" style="font-size: 14px">28: This explanation was taken almost verbatim from the students' paper.</p>
<p id="29" style="font-size: 14px">29: Giving the information a dedicated and delineated position.</p>
<p id="30" style="font-size: 14px">30: This FIXME is from 2013.</p>
<p id="31" style="font-size: 14px">31: I'll take "irreconcilable inconsistencies" for $500.</p>
<p id="32" style="font-size: 14px">32: Structural issues like this I don't think are because of incompetence. The goal of `javac`
has always been to be a reference compiler for Java. Everyone wants "good" errors, but the status quo is a result of the
natural trend when a diagnostic ~= a line of output.</p>
<p id="33" style="font-size: 14px">33: Structure, structure, structure.</p>
<p id="34" style="font-size: 14px">34: If you get enough commits into OpenJDK and are a committer you can submit a JEP. That requires fixing a lot of JDK issues and going through a nomination process. I have Hogans Heroes to binge.</p>
<p id="35" style="font-size: 14px">35: That took awhile for us to figure out even with the tutorials that exist.</p>
<p id="36" style="font-size: 14px">36: Even if you aren't convinced that the approach we've taken is the one to continue with, hopefully you recognize that there is a real problem here.</p>
<p id="37" style="font-size: 14px">37: I, at least, am not particularly special. I do however have a lot of context on this area of the code by now.</p>

<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Make your own Optionals</title><link>https://mccue.dev/pages/3-28-23-custom-optional</link><description></description><pubDate>Tue, 28 Mar 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Make your own Optionals</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Make your own Optionals</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
This is `java.util.Optional`.

<p>I took out all the comments and did a little reformatting, but this is the entire class. Just around 150 lines managing one nullable field.</p>
<p>Take a minute to read or skim it before moving on.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> Optional<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">static</span> <span class="dt">final</span> Optional<span class="op">&lt;?&gt;</span> EMPTY <span class="op">=</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> Optional<span class="op">&lt;&gt;(</span><span class="kw">null</span><span class="op">);</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> T value<span class="op">;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span><span class="op">&lt;</span>T<span class="op">&gt;</span> Optional<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="fu">empty</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>        <span class="at">@SuppressWarnings</span><span class="op">(</span><span class="st">&quot;unchecked&quot;</span><span class="op">)</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>        Optional<span class="op">&lt;</span>T<span class="op">&gt;</span> t <span class="op">=</span> <span class="op">(</span>Optional<span class="op">&lt;</span>T<span class="op">&gt;)</span> EMPTY<span class="op">;</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> t<span class="op">;</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Optional</span><span class="op">(</span>T value<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">value</span> <span class="op">=</span> value<span class="op">;</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="op">&lt;</span>T<span class="op">&gt;</span> Optional<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="fu">of</span><span class="op">(</span>T value<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> Optional<span class="op">&lt;&gt;(</span>Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>value<span class="op">));</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>    <span class="at">@SuppressWarnings</span><span class="op">(</span><span class="st">&quot;unchecked&quot;</span><span class="op">)</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="op">&lt;</span>T<span class="op">&gt;</span> Optional<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="fu">ofNullable</span><span class="op">(</span>T value<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> value <span class="op">==</span> <span class="kw">null</span> <span class="op">?</span> <span class="op">(</span>Optional<span class="op">&lt;</span>T<span class="op">&gt;)</span> EMPTY</span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>                             <span class="op">:</span> <span class="kw">new</span> Optional<span class="op">&lt;&gt;(</span>value<span class="op">);</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> T <span class="fu">get</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>value <span class="op">==</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a>            <span class="cf">throw</span> <span class="kw">new</span> <span class="bu">NoSuchElementException</span><span class="op">(</span><span class="st">&quot;No value present&quot;</span><span class="op">);</span></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> value<span class="op">;</span></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">boolean</span> <span class="fu">isPresent</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> value <span class="op">!=</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-37"><a href="#cb1-37" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-38"><a href="#cb1-38" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">boolean</span> <span class="fu">isEmpty</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-39"><a href="#cb1-39" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> value <span class="op">==</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb1-40"><a href="#cb1-40" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-41"><a href="#cb1-41" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-42"><a href="#cb1-42" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">ifPresent</span><span class="op">(</span>Consumer<span class="op">&lt;?</span> <span class="kw">super</span> T<span class="op">&gt;</span> action<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-43"><a href="#cb1-43" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>value <span class="op">!=</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-44"><a href="#cb1-44" aria-hidden="true" tabindex="-1"></a>            action<span class="op">.</span><span class="fu">accept</span><span class="op">(</span>value<span class="op">);</span></span>
<span id="cb1-45"><a href="#cb1-45" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-46"><a href="#cb1-46" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-47"><a href="#cb1-47" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-48"><a href="#cb1-48" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">ifPresentOrElse</span><span class="op">(</span></span>
<span id="cb1-49"><a href="#cb1-49" aria-hidden="true" tabindex="-1"></a>            Consumer<span class="op">&lt;?</span> <span class="kw">super</span> T<span class="op">&gt;</span> action<span class="op">,</span> </span>
<span id="cb1-50"><a href="#cb1-50" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Runnable</span> emptyAction</span>
<span id="cb1-51"><a href="#cb1-51" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-52"><a href="#cb1-52" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>value <span class="op">!=</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-53"><a href="#cb1-53" aria-hidden="true" tabindex="-1"></a>            action<span class="op">.</span><span class="fu">accept</span><span class="op">(</span>value<span class="op">);</span></span>
<span id="cb1-54"><a href="#cb1-54" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb1-55"><a href="#cb1-55" aria-hidden="true" tabindex="-1"></a>            emptyAction<span class="op">.</span><span class="fu">run</span><span class="op">();</span></span>
<span id="cb1-56"><a href="#cb1-56" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-57"><a href="#cb1-57" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-58"><a href="#cb1-58" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-59"><a href="#cb1-59" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> Optional<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="fu">filter</span><span class="op">(</span><span class="bu">Predicate</span><span class="op">&lt;?</span> <span class="kw">super</span> T<span class="op">&gt;</span> predicate<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-60"><a href="#cb1-60" aria-hidden="true" tabindex="-1"></a>        Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>predicate<span class="op">);</span></span>
<span id="cb1-61"><a href="#cb1-61" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(!</span><span class="fu">isPresent</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb1-62"><a href="#cb1-62" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb1-63"><a href="#cb1-63" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb1-64"><a href="#cb1-64" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> predicate<span class="op">.</span><span class="fu">test</span><span class="op">(</span>value<span class="op">)</span> <span class="op">?</span> <span class="kw">this</span> <span class="op">:</span> <span class="fu">empty</span><span class="op">();</span></span>
<span id="cb1-65"><a href="#cb1-65" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-66"><a href="#cb1-66" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-67"><a href="#cb1-67" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-68"><a href="#cb1-68" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="op">&lt;</span>U<span class="op">&gt;</span> Optional<span class="op">&lt;</span>U<span class="op">&gt;</span> <span class="fu">map</span><span class="op">(</span></span>
<span id="cb1-69"><a href="#cb1-69" aria-hidden="true" tabindex="-1"></a>        Function<span class="op">&lt;?</span> <span class="kw">super</span> T<span class="op">,</span> <span class="op">?</span> <span class="kw">extends</span> U<span class="op">&gt;</span> mapper</span>
<span id="cb1-70"><a href="#cb1-70" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-71"><a href="#cb1-71" aria-hidden="true" tabindex="-1"></a>        Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>mapper<span class="op">);</span></span>
<span id="cb1-72"><a href="#cb1-72" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(!</span><span class="fu">isPresent</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb1-73"><a href="#cb1-73" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="fu">empty</span><span class="op">();</span></span>
<span id="cb1-74"><a href="#cb1-74" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb1-75"><a href="#cb1-75" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> Optional<span class="op">.</span><span class="fu">ofNullable</span><span class="op">(</span>mapper<span class="op">.</span><span class="fu">apply</span><span class="op">(</span>value<span class="op">));</span></span>
<span id="cb1-76"><a href="#cb1-76" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-77"><a href="#cb1-77" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-78"><a href="#cb1-78" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-79"><a href="#cb1-79" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="op">&lt;</span>U<span class="op">&gt;</span> Optional<span class="op">&lt;</span>U<span class="op">&gt;</span> <span class="fu">flatMap</span><span class="op">(</span></span>
<span id="cb1-80"><a href="#cb1-80" aria-hidden="true" tabindex="-1"></a>         Function<span class="op">&lt;?</span> <span class="kw">super</span> T<span class="op">,</span> <span class="op">?</span> <span class="kw">extends</span> Optional<span class="op">&lt;?</span> <span class="kw">extends</span> U<span class="op">&gt;&gt;</span> mapper</span>
<span id="cb1-81"><a href="#cb1-81" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-82"><a href="#cb1-82" aria-hidden="true" tabindex="-1"></a>        Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>mapper<span class="op">);</span></span>
<span id="cb1-83"><a href="#cb1-83" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(!</span><span class="fu">isPresent</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb1-84"><a href="#cb1-84" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="fu">empty</span><span class="op">();</span></span>
<span id="cb1-85"><a href="#cb1-85" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb1-86"><a href="#cb1-86" aria-hidden="true" tabindex="-1"></a>            <span class="at">@SuppressWarnings</span><span class="op">(</span><span class="st">&quot;unchecked&quot;</span><span class="op">)</span></span>
<span id="cb1-87"><a href="#cb1-87" aria-hidden="true" tabindex="-1"></a>            Optional<span class="op">&lt;</span>U<span class="op">&gt;</span> r <span class="op">=</span> <span class="op">(</span>Optional<span class="op">&lt;</span>U<span class="op">&gt;)</span> mapper<span class="op">.</span><span class="fu">apply</span><span class="op">(</span>value<span class="op">);</span></span>
<span id="cb1-88"><a href="#cb1-88" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>r<span class="op">);</span></span>
<span id="cb1-89"><a href="#cb1-89" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-90"><a href="#cb1-90" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-91"><a href="#cb1-91" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-92"><a href="#cb1-92" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> Optional<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="fu">or</span><span class="op">(</span></span>
<span id="cb1-93"><a href="#cb1-93" aria-hidden="true" tabindex="-1"></a>            Supplier<span class="op">&lt;?</span> <span class="kw">extends</span> Optional<span class="op">&lt;?</span> <span class="kw">extends</span> T<span class="op">&gt;&gt;</span> supplier</span>
<span id="cb1-94"><a href="#cb1-94" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-95"><a href="#cb1-95" aria-hidden="true" tabindex="-1"></a>        Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>supplier<span class="op">);</span></span>
<span id="cb1-96"><a href="#cb1-96" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span><span class="fu">isPresent</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb1-97"><a href="#cb1-97" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb1-98"><a href="#cb1-98" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb1-99"><a href="#cb1-99" aria-hidden="true" tabindex="-1"></a>            <span class="at">@SuppressWarnings</span><span class="op">(</span><span class="st">&quot;unchecked&quot;</span><span class="op">)</span></span>
<span id="cb1-100"><a href="#cb1-100" aria-hidden="true" tabindex="-1"></a>            Optional<span class="op">&lt;</span>T<span class="op">&gt;</span> r <span class="op">=</span> <span class="op">(</span>Optional<span class="op">&lt;</span>T<span class="op">&gt;)</span> supplier<span class="op">.</span><span class="fu">get</span><span class="op">();</span></span>
<span id="cb1-101"><a href="#cb1-101" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>r<span class="op">);</span></span>
<span id="cb1-102"><a href="#cb1-102" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-103"><a href="#cb1-103" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-104"><a href="#cb1-104" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-105"><a href="#cb1-105" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> Stream<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="fu">stream</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-106"><a href="#cb1-106" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(!</span><span class="fu">isPresent</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb1-107"><a href="#cb1-107" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> Stream<span class="op">.</span><span class="fu">empty</span><span class="op">();</span></span>
<span id="cb1-108"><a href="#cb1-108" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb1-109"><a href="#cb1-109" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> Stream<span class="op">.</span><span class="fu">of</span><span class="op">(</span>value<span class="op">);</span></span>
<span id="cb1-110"><a href="#cb1-110" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-111"><a href="#cb1-111" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-112"><a href="#cb1-112" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-113"><a href="#cb1-113" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> T <span class="fu">orElse</span><span class="op">(</span>T other<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-114"><a href="#cb1-114" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> value <span class="op">!=</span> <span class="kw">null</span> <span class="op">?</span> value <span class="op">:</span> other<span class="op">;</span></span>
<span id="cb1-115"><a href="#cb1-115" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-116"><a href="#cb1-116" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-117"><a href="#cb1-117" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> T <span class="fu">orElseGet</span><span class="op">(</span>Supplier<span class="op">&lt;?</span> <span class="kw">extends</span> T<span class="op">&gt;</span> supplier<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-118"><a href="#cb1-118" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> value <span class="op">!=</span> <span class="kw">null</span> <span class="op">?</span> value <span class="op">:</span> supplier<span class="op">.</span><span class="fu">get</span><span class="op">();</span></span>
<span id="cb1-119"><a href="#cb1-119" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-120"><a href="#cb1-120" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-121"><a href="#cb1-121" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> T <span class="fu">orElseThrow</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-122"><a href="#cb1-122" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>value <span class="op">==</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-123"><a href="#cb1-123" aria-hidden="true" tabindex="-1"></a>            <span class="cf">throw</span> <span class="kw">new</span> <span class="bu">NoSuchElementException</span><span class="op">(</span><span class="st">&quot;No value present&quot;</span><span class="op">);</span></span>
<span id="cb1-124"><a href="#cb1-124" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-125"><a href="#cb1-125" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> value<span class="op">;</span></span>
<span id="cb1-126"><a href="#cb1-126" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-127"><a href="#cb1-127" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-128"><a href="#cb1-128" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="op">&lt;</span>X <span class="kw">extends</span> <span class="bu">Throwable</span><span class="op">&gt;</span> T <span class="fu">orElseThrow</span><span class="op">(</span></span>
<span id="cb1-129"><a href="#cb1-129" aria-hidden="true" tabindex="-1"></a>            Supplier<span class="op">&lt;?</span> <span class="kw">extends</span> X<span class="op">&gt;</span> exceptionSupplier</span>
<span id="cb1-130"><a href="#cb1-130" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">throws</span> X <span class="op">{</span></span>
<span id="cb1-131"><a href="#cb1-131" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>value <span class="op">!=</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-132"><a href="#cb1-132" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> value<span class="op">;</span></span>
<span id="cb1-133"><a href="#cb1-133" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb1-134"><a href="#cb1-134" aria-hidden="true" tabindex="-1"></a>            <span class="cf">throw</span> exceptionSupplier<span class="op">.</span><span class="fu">get</span><span class="op">();</span></span>
<span id="cb1-135"><a href="#cb1-135" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-136"><a href="#cb1-136" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-137"><a href="#cb1-137" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-138"><a href="#cb1-138" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb1-139"><a href="#cb1-139" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">boolean</span> <span class="fu">equals</span><span class="op">(</span><span class="bu">Object</span> obj<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-140"><a href="#cb1-140" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span><span class="kw">this</span> <span class="op">==</span> obj<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-141"><a href="#cb1-141" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">true</span><span class="op">;</span></span>
<span id="cb1-142"><a href="#cb1-142" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-143"><a href="#cb1-143" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-144"><a href="#cb1-144" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> obj <span class="kw">instanceof</span> Optional<span class="op">&lt;?&gt;</span> other</span>
<span id="cb1-145"><a href="#cb1-145" aria-hidden="true" tabindex="-1"></a>                <span class="op">&amp;&amp;</span> Objects<span class="op">.</span><span class="fu">equals</span><span class="op">(</span>value<span class="op">,</span> other<span class="op">.</span><span class="fu">value</span><span class="op">);</span></span>
<span id="cb1-146"><a href="#cb1-146" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-147"><a href="#cb1-147" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-148"><a href="#cb1-148" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb1-149"><a href="#cb1-149" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">int</span> <span class="fu">hashCode</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-150"><a href="#cb1-150" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> Objects<span class="op">.</span><span class="fu">hashCode</span><span class="op">(</span>value<span class="op">);</span></span>
<span id="cb1-151"><a href="#cb1-151" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-152"><a href="#cb1-152" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-153"><a href="#cb1-153" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb1-154"><a href="#cb1-154" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">String</span> <span class="fu">toString</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-155"><a href="#cb1-155" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> value <span class="op">!=</span> <span class="kw">null</span></span>
<span id="cb1-156"><a href="#cb1-156" aria-hidden="true" tabindex="-1"></a>            <span class="op">?</span> <span class="op">(</span><span class="st">&quot;Optional[&quot;</span> <span class="op">+</span> value <span class="op">+</span> <span class="st">&quot;]&quot;</span><span class="op">)</span></span>
<span id="cb1-157"><a href="#cb1-157" aria-hidden="true" tabindex="-1"></a>            <span class="op">:</span> <span class="st">&quot;Optional.empty&quot;</span><span class="op">;</span></span>
<span id="cb1-158"><a href="#cb1-158" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-159"><a href="#cb1-159" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="why-does-optional-exist">Why does <code>Optional</code> exist</h2>
<p><code>java.util.Optional</code> was introduced in Java 8 alongside the <code>Stream</code> API. Its raison d'etre is to make coders explicitly consider what to do when using methods like <code>findFirst</code> on a potentially empty <code>Stream</code>.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Explicitly throws </span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> valueOne <span class="op">=</span> list</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">stream</span><span class="op">()</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">map</span><span class="op">(</span>x <span class="op">-&gt;</span> x <span class="op">+</span> <span class="dv">1</span><span class="op">)</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">filter</span><span class="op">(</span>x <span class="op">-&gt;</span> x <span class="op">%</span> <span class="dv">2</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">findFirst</span><span class="op">()</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">orElseThrow</span><span class="op">()</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="co">// Explicitly uses a default value</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> valueTwo <span class="op">=</span> list</span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">stream</span><span class="op">()</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">map</span><span class="op">(</span>x <span class="op">-&gt;</span> x <span class="op">+</span> <span class="dv">1</span><span class="op">)</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">filter</span><span class="op">(</span>x <span class="op">-&gt;</span> x <span class="op">%</span> <span class="dv">2</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">findFirst</span><span class="op">()</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">orElse</span><span class="op">(</span><span class="dv">0</span><span class="op">)</span></span></code></pre></div>
<p>The deficiency it targets is in the interaction between <code>null</code> and "method chaining style". When there are so many method calls stacked up, it is hard for people to remember to handle cases like <code>null</code> return values.</p>
<p>So with streams poised to encourage method chaining, <code>Optional</code> was needed to make that API not lead to hidden bugs.</p>
<h2 id="whats-wrong-with-optional">What's wrong with <code>Optional</code>?</h2>
<p>Nothing really.</p>
<p>The core tension that leads to so much discourse is that there is no way to represent <code>null</code> in Java's type system. Whether from lived experience or religious fervor, folks tend to be afraid of an unaccounted for <code>null</code>.</p>
<p>Because <code>Optional</code> is in the standard library and explicitly represents "absence or presence", it is extremely tempting to just replace every nullable thing with an <code>Optional&lt;T&gt;</code>.</p>
<p>Doing this can lead to code that sucks, especially if you try to avoid <code>null</code> for local variables.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Some might try to use isPresent()/get() to avoid null</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>Optional<span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> nameOpt <span class="op">=</span> <span class="fu">f</span><span class="op">();</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>Optional<span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;</span> ageOpt <span class="op">=</span> <span class="fu">g</span><span class="op">();</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>nameOpt<span class="op">.</span><span class="fu">isPresent</span><span class="op">()</span> <span class="op">&amp;&amp;</span> ageOpt<span class="op">.</span><span class="fu">isPresent</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    var name <span class="op">=</span> nameOpt<span class="op">.</span><span class="fu">get</span><span class="op">();</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>    var age <span class="op">=</span> nameOpt<span class="op">.</span><span class="fu">get</span><span class="op">();</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>        name <span class="op">+</span> <span class="st">&quot; is &quot;</span> <span class="op">+</span> age <span class="op">+</span> <span class="st">&quot; years old&quot;</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Others might try to map/flatMap.</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>Optional<span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> nameOpt <span class="op">=</span> <span class="fu">f</span><span class="op">();</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>Optional<span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;</span> ageOpt <span class="op">=</span> <span class="fu">g</span><span class="op">();</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>nameOpt</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">flatMap</span><span class="op">(</span>name <span class="op">-&gt;</span> </span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>        ageOpt<span class="op">.</span><span class="fu">map</span><span class="op">(</span>age <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>            <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>                name <span class="op">+</span> <span class="st">&quot; is &quot;</span> <span class="op">+</span> age <span class="op">+</span> <span class="st">&quot; years old&quot;</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">}))</span></span></code></pre></div>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="co">// But its questionable what&#39;s gained over null.</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="bu">String</span> name <span class="op">=</span> <span class="fu">f</span><span class="op">().</span><span class="fu">orElse</span><span class="op">(</span><span class="kw">null</span><span class="op">);</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="bu">Integer</span> age <span class="op">=</span> <span class="fu">g</span><span class="op">().</span><span class="fu">orElse</span><span class="op">(</span><span class="kw">null</span><span class="op">);</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>name <span class="op">!=</span> <span class="kw">null</span> <span class="op">&amp;&amp;</span> age <span class="op">!=</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>        name <span class="op">+</span> <span class="st">&quot; is &quot;</span> <span class="op">+</span> age <span class="op">+</span> <span class="st">&quot; years old&quot;</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>But this is honestly <em>fine</em>.</p>
<p>Yes, the <code>Optional</code> will use up more memory and perform a bit worse than the equivalent code with <code>null</code>. Yes, code written with <code>isPresent</code>/<code>get</code>/<code>orElseThrow</code> or <code>map</code>/<code>flatMap</code> can be a bit crusty. Yes, it wasn't intended to be a field or a method parameter. There are a lot of bike sheds to build and "best practices" to get into internet fights over.</p>
<p>But <a href="https://jspecify.dev/"><code>jspecify</code></a> is poised to give standard nullability annotations and tooling to augment the type system with them. Project Valhalla is considering giving a way to express <a href="https://openjdk.org/jeps/401">null restricted storage</a>. In the fullness of time, the core tension that leads to this "overuse" seems like it will be resolved.</p>
<p>The problem with both <code>Optional</code> and <code>null</code> is that they <em>only</em> convey that some data might be absent and not what being absent implies.</p>
<h2 id="the-meaning-of-absence">The Meaning of Absence</h2>
<p>Say you were writing a program which had to record peoples' first and last names for legal reasons. Users can still sign up, but they will need to give that information before continuing on to other parts of the app.</p>
<p>Today you might see <code>Optional</code> being used to represent that.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">Optional</span><span class="op">;</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Person</span><span class="op">(</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> id<span class="op">,</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>        Optional<span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> firstName<span class="op">,</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>        Optional<span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> lastName</span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{}</span></span></code></pre></div>
<p>In the near future, maybe a <code>@Nullable</code> annotation.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">jspecify</span><span class="op">.</span><span class="im">annotations</span><span class="op">.</span><span class="im">Nullable</span><span class="op">;</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Person</span><span class="op">(</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> id<span class="op">,</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>        <span class="at">@Nullable</span> <span class="bu">String</span> firstName<span class="op">,</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>        <span class="at">@Nullable</span> <span class="bu">String</span> lastName</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{}</span></span></code></pre></div>
<p>In both cases - <code>null</code> and an empty <code>Optional</code> - an absent value implies that you have not been given that information yet.</p>
<p>You can use this to know when to stop a user and ask them for their name.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">Optional</span><span class="op">;</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Person</span><span class="op">(</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> id<span class="op">,</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>        Optional<span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> firstName<span class="op">,</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>        Optional<span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> lastName</span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">boolean</span> <span class="fu">shouldAskForInfo</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> firstName<span class="op">.</span><span class="fu">isEmpty</span><span class="op">()</span> <span class="op">||</span> lastName<span class="op">.</span><span class="fu">isEmpty</span><span class="op">();</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb9"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">jspecify</span><span class="op">.</span><span class="im">annotations</span><span class="op">.</span><span class="im">Nullable</span><span class="op">;</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Person</span><span class="op">(</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> id<span class="op">,</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>        <span class="at">@Nullable</span> <span class="bu">String</span> firstName<span class="op">,</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>        <span class="at">@Nullable</span> <span class="bu">String</span> lastName</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">boolean</span> <span class="fu">shouldAskForInfo</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> firstName <span class="op">==</span> <span class="kw">null</span> <span class="op">||</span> lastName <span class="op">==</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Now, consider Madonna. Madonna does not have a last name. If a <code>null</code> or empty value in the <code>lastName</code> field means "not provided", you have no way to directly represent "known to not exist."</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Need to ask Bob for his last name still</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>var bob <span class="op">=</span> <span class="kw">new</span> <span class="fu">Person</span><span class="op">(</span><span class="dv">1</span><span class="op">,</span> <span class="st">&quot;Bob&quot;</span><span class="op">,</span> <span class="kw">null</span><span class="op">);</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="co">// Shouldn&#39;t ask Madonna for anything</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>var madonna <span class="op">=</span> <span class="kw">new</span> <span class="fu">Person</span><span class="op">(</span><span class="dv">2</span><span class="op">,</span> <span class="st">&quot;Madonna&quot;</span><span class="op">,</span> <span class="kw">null</span><span class="op">);</span></span></code></pre></div>
<p>Using an empty string is tempting, but if you do that you will have the same problem that <code>null</code> currently has. By having a "special" value not expressed in the type system, you are liable to forget to check for that special value.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Empty string can be a sentinel</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>var madonna <span class="op">=</span> <span class="kw">new</span> <span class="fu">Person</span><span class="op">(</span><span class="dv">2</span><span class="op">,</span> <span class="st">&quot;Madonna&quot;</span><span class="op">,</span> <span class="st">&quot;&quot;</span><span class="op">);</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a><span class="co">// But if you forget that it is special</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a><span class="co">// you might give Madonna a subpar user experience</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>var welcome <span class="op">=</span> <span class="st">&quot;Hello &quot;</span> </span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">+</span> person<span class="op">.</span><span class="fu">firstName</span><span class="op">()</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">+</span> <span class="st">&quot; &quot;</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">+</span> person<span class="op">.</span><span class="fu">lastName</span><span class="op">()</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">+</span> <span class="st">&quot;!&quot;</span><span class="op">;</span></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a><span class="co">// &quot;Hello Madonna !&quot;</span></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a><span class="co">// She&#39;ll notice. She&#39;ll hate you.</span></span></code></pre></div>
<p>The reality of our fictional data model is that we have three distinct cases.</p>
<ol type="1">
<li>We have not been given a last name.</li>
<li>We have been told there is no last name.</li>
<li>We have been given a last name.</li>
</ol>
<p>The most convenient tool we have for representing this sort of situation is a <code>sealed interface</code>.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> LastName <span class="op">{</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">NotGiven</span><span class="op">()</span> <span class="kw">implements</span> LastName <span class="op">{}</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">DoesNotExist</span><span class="op">()</span> <span class="kw">implements</span> LastName <span class="op">{}</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">Given</span><span class="op">(</span><span class="bu">String</span> value<span class="op">)</span> <span class="kw">implements</span> LastName <span class="op">{}</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Now when a <code>LastName</code> has an absent value, we can know whether that is because it doesn't exist or we just haven't been told.</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">jspecify</span><span class="op">.</span><span class="im">annotations</span><span class="op">.</span><span class="im">Nullable</span><span class="op">;</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Person</span><span class="op">(</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> id<span class="op">,</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>        <span class="at">@Nullable</span> <span class="bu">String</span> firstName<span class="op">,</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>        LastName lastName</span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">boolean</span> <span class="fu">shouldAskForInfo</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> firstName <span class="op">==</span> <span class="kw">null</span> </span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>                <span class="op">||</span> lastName <span class="kw">instanceof</span> LastName<span class="op">.</span><span class="fu">NotGiven</span><span class="op">;</span></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And we can properly represent Madonna.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Need to ask Bob for his last name still</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>var bob <span class="op">=</span> <span class="kw">new</span> <span class="fu">Person</span><span class="op">(</span><span class="dv">1</span><span class="op">,</span> <span class="st">&quot;Bob&quot;</span><span class="op">,</span> <span class="kw">new</span> LastName<span class="op">.</span><span class="fu">NotGiven</span><span class="op">());</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a><span class="co">// Shouldn&#39;t ask Madonna for anything</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>var madonna <span class="op">=</span> <span class="kw">new</span> <span class="fu">Person</span><span class="op">(</span><span class="dv">2</span><span class="op">,</span> <span class="st">&quot;Madonna&quot;</span><span class="op">,</span> <span class="kw">new</span> LastName<span class="op">.</span><span class="fu">DoesNotExist</span><span class="op">());</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a><span class="co">// Joe is all set</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>var joe <span class="op">=</span> <span class="kw">new</span> <span class="fu">Person</span><span class="op">(</span><span class="dv">3</span><span class="op">,</span> <span class="st">&quot;Joe&quot;</span><span class="op">,</span> <span class="kw">new</span> LastName<span class="op">.</span><span class="fu">Given</span><span class="op">(</span><span class="st">&quot;Shmoe&quot;</span><span class="op">));</span></span></code></pre></div>
<p><code>Optional</code> and <code>null</code> let you represent exactly 2 possibilities, a sealed hierarchy lets you represent 2 or more possibilities. The reason I'm using the Madonna example is that it is a straw-man where you want to represent 3 distinct possibilities.</p>
<p>My bold claim is that even when there are only 2 possibilities you should still consider making your own class instead of using <code>Optional</code> or <code>null</code>.</p>
<p>Both <code>@Nullable String firstName</code> and <code>Optional&lt;String&gt; firstName</code> do not directly convey what it means if the data is missing. Its just "absent." The fact that it means you haven't been told is context external to your domain model.</p>
<p>It's a similar problem to <a href="https://sandimetz.com/blog/2014/9/9/shape-at-the-bottom-of-all-things">primitive obsession</a>. Because <code>null</code> and <code>Optional</code> are there and fit the "shape" we want we gravitate to them.</p>
<p>What if instead of that we were to make our own "optional" class.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> FirstName <span class="op">{</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">NotGiven</span><span class="op">()</span> <span class="kw">implements</span> FirstName <span class="op">{}</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">Given</span><span class="op">(</span><span class="bu">String</span> value<span class="op">)</span> <span class="kw">implements</span> FirstName <span class="op">{}</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>So here <code>FirstName</code> is identical in spirit to an <code>Optional&lt;String&gt;</code>, but with the benefit of us being able to give a name to the situation where there is no value. It's not empty or present, we were either given a first name or we weren't.</p>
<p>With pattern matching you will be able switch over these two situations.</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="cf">switch</span> <span class="op">(</span>person<span class="op">.</span><span class="fu">firstName</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>   <span class="cf">case</span> FirstName<span class="op">.</span><span class="fu">NotGiven</span> _ <span class="op">-&gt;</span>     </span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;No first name&quot;</span><span class="op">);</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>   <span class="cf">case</span> FirstName<span class="op">.</span><span class="fu">Given</span><span class="op">(</span><span class="bu">String</span> name<span class="op">)</span> <span class="op">-&gt;</span> </span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;First name is &quot;</span> <span class="op">+</span> name<span class="op">);</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And part of the reason I put all the code for <code>Optional</code> at the top was to impress upon you how trivial it would be to add any of those helper methods to a class you made yourself.</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> FirstName <span class="op">{</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">NotGiven</span><span class="op">()</span> <span class="kw">implements</span> FirstName <span class="op">{</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>        <span class="at">@Override</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="bu">String</span> <span class="fu">orElse</span><span class="op">(</span><span class="bu">String</span> defaultValue<span class="op">)</span> <span class="op">{</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> defaultValue<span class="op">;</span></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">Given</span><span class="op">(</span><span class="bu">String</span> value<span class="op">)</span> <span class="kw">implements</span> FirstName <span class="op">{</span></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a>        <span class="at">@Override</span></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="bu">String</span> <span class="fu">orElse</span><span class="op">(</span><span class="bu">String</span> defaultValue<span class="op">)</span> <span class="op">{</span></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">value</span><span class="op">;</span></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a>    <span class="bu">String</span> <span class="fu">orElse</span><span class="op">(</span><span class="bu">String</span> defaultValue<span class="op">);</span></span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb18"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a>var name <span class="op">=</span> person<span class="op">.</span><span class="fu">name</span><span class="op">().</span><span class="fu">orElse</span><span class="op">(</span><span class="st">&quot;?&quot;</span><span class="op">);</span></span></code></pre></div>
<p>That's it. That's the thesis.</p>
<p>If you are spending time modeling your domain objects, consider making your own versions of an <code>Optional</code> class. You can choose names which more align with your domain, adapt to more varied situations, and the boilerplate for doing so is at a historic low.</p>
<p>I will admit that if you have a huge number of fields with potentially missing data this can be more trouble than its worth. I still think its worth considering.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Please try my JSON library</title><link>https://mccue.dev/pages/2-26-23-json</link><description></description><pubDate>Sun, 26 Feb 0023 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Please try my JSON library</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Please try my JSON library</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
<meta property="og:image" content="https://mccue.dev/pages/2-26-23-bopbop.png" />
<meta name="twitter:image" content="https://mccue.dev/pages/2-26-23-bopbop.png">

<p><a href="https://github.com/bowbahdoe/json"><img src="https://gh-card.dev/repos/bowbahdoe/json.svg" alt="bowbahdoe/json - GitHub" /></a></p>
<p>For the past four months I've been working on <a href="https://github.com/bowbahdoe/json">a JSON library for Java</a>.</p>
<p>It's not original. Most of the implementation of the parser I stole from Clojure's <a href="https://github.com/clojure/data.json">data.json</a> and the user facing API is a total ripoff of <a href="https://elm-lang.org/">Elm</a>'s <a href="https://package.elm-lang.org/packages/elm/json/latest/">JSON library</a>. The only novel engineering I've done has been in translation.</p>
<p>It's also not amazingly fast. Last I benchmarked it, it was around <a href="https://github.com/fabienrenaud/java-json-benchmark/issues/59#issuecomment-1345650635">5x as slow as Jackson</a>, the current king of Java's JSON castle. There are paths to improve that but, whether for lack of time or ability, I haven't explored any of them.</p>
<p>Despite all that, I think you should try it. The rest of this post is going to be an effort to convince you to do so.</p>
<p>First, I am going to go through a basic tutorial to get you up to speed. Then I am going to go through some pitches that I hope convince you.</p>
<h2 id="tutorial">Tutorial</h2>
<h3 id="the-data-model">The Data Model</h3>
<p>JSON is a data format. It looks like the following sample.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">&quot;name&quot;</span><span class="fu">:</span> <span class="st">&quot;kermit&quot;</span><span class="fu">,</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">&quot;wife&quot;</span><span class="fu">:</span> <span class="kw">null</span><span class="fu">,</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">&quot;girlfriend&quot;</span><span class="fu">:</span> <span class="st">&quot;Ms. Piggy&quot;</span><span class="fu">,</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">&quot;age&quot;</span><span class="fu">:</span> <span class="dv">22</span><span class="fu">,</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">&quot;children&quot;</span><span class="fu">:</span> <span class="ot">[</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>        <span class="fu">{</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>            <span class="dt">&quot;species&quot;</span><span class="fu">:</span> <span class="st">&quot;frog&quot;</span><span class="fu">,</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>            <span class="dt">&quot;gender&quot;</span><span class="fu">:</span> <span class="st">&quot;male&quot;</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>        <span class="fu">}</span><span class="ot">,</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>        <span class="fu">{</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>            <span class="dt">&quot;species&quot;</span><span class="fu">:</span> <span class="st">&quot;pig&quot;</span><span class="fu">,</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>            <span class="dt">&quot;gender&quot;</span><span class="fu">:</span> <span class="st">&quot;female&quot;</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>        <span class="fu">}</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>    <span class="ot">]</span><span class="fu">,</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    <span class="dt">&quot;commitmentIssues&quot;</span><span class="fu">:</span> <span class="kw">true</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="fu">}</span></span></code></pre></div>
<p>In JSON you represent data using a combination of objects (maps from strings to JSON), arrays (ordered sequences of JSON), strings, numbers, true, false, and null.</p>
<p>Therefore, one "natural" way to think about the data stored in a JSON document is as the union of those possibilities.</p>
<pre><code>JSON is one of
- a map of string to JSON
- a list of JSON
- a string
- a number
- true
- false
- null</code></pre>
<p>The way to represent this in Java is using a sealed interface, which provides an explicit list of types which are allowed to implement it.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> sealed <span class="kw">interface</span> Json</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>        permits </span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>            JsonObject<span class="op">,</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>            JsonArray<span class="op">,</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>            JsonString<span class="op">,</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>            JsonNumber<span class="op">,</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>            JsonBoolean<span class="op">,</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>            JsonNull <span class="op">{</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This means that if you have a field or variable which has the type <code>Json</code>, you know that it is either a <code>JsonObject</code>, <code>JsonArray</code>, <code>JsonString</code>, <code>JsonNumber</code>, <code>JsonBoolean</code>, or <code>JsonNull</code>.</p>
<p>That is the first thing provided by my library. There is a <code>Json</code> type and subtypes representing those different cases.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.*;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> Json <span class="fu">greeting</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> JsonString<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;hello&quot;</span><span class="op">);</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>        Json json <span class="op">=</span> <span class="fu">greeting</span><span class="op">();</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">switch</span> <span class="op">(</span>json<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> JsonObject object <span class="op">-&gt;</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;An object&quot;</span><span class="op">);</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> JsonArray array <span class="op">-&gt;</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;An array&quot;</span><span class="op">);</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> JsonString str <span class="op">-&gt;</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;A string&quot;</span><span class="op">);</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> JsonNumber number <span class="op">-&gt;</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;A number&quot;</span><span class="op">);</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> JsonBoolean bool <span class="op">-&gt;</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;A boolean&quot;</span><span class="op">);</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> JsonNull __ <span class="op">-&gt;</span></span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;A json null&quot;</span><span class="op">);</span></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>You can create instances of these subtypes using factory methods on the types themselves.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.*;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">List</span><span class="op">;</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">Map</span><span class="op">;</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>        JsonObject kermit <span class="op">=</span> JsonObject<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="bu">Map</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;name&quot;</span><span class="op">,</span> JsonString<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;kermit&quot;</span><span class="op">),</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;age&quot;</span><span class="op">,</span> JsonNumber<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="dv">22</span><span class="op">),</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;commitmentIssues&quot;</span><span class="op">,</span> JsonBoolean<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="kw">true</span><span class="op">),</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;wife&quot;</span><span class="op">,</span> JsonNull<span class="op">.</span><span class="fu">instance</span><span class="op">(),</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;children&quot;</span><span class="op">,</span> JsonArray<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a>                        JsonString<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;Tiny Tim&quot;</span><span class="op">)</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>                <span class="op">))</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a>        <span class="op">));</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>kermit<span class="op">);</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Or by using factory methods on <code>Json</code>, which aren't guaranteed to give you any specific subtype but in exchange will handle converting any stray <code>null</code>s to <code>JsonNull</code>.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.*;</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">List</span><span class="op">;</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">Map</span><span class="op">;</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>        Json kermit <span class="op">=</span> Json<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="bu">Map</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;name&quot;</span><span class="op">,</span> Json<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;kermit&quot;</span><span class="op">),</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;age&quot;</span><span class="op">,</span> Json<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="dv">22</span><span class="op">),</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;commitmentIssues&quot;</span><span class="op">,</span> Json<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="kw">true</span><span class="op">),</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;wife&quot;</span><span class="op">,</span> Json<span class="op">.</span><span class="fu">ofNull</span><span class="op">(),</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;children&quot;</span><span class="op">,</span> Json<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a>                        JsonString<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;Tiny Tim&quot;</span><span class="op">)</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a>                <span class="op">))</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a>        <span class="op">));</span></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>kermit<span class="op">);</span></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>For <code>JsonObject</code> and <code>JsonArray</code>, there also use builders available which can make it so that you don't need to write <code>Json.of</code> on every value.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.</span><span class="im">Json</span><span class="op">;</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>        Json kermit <span class="op">=</span> Json<span class="op">.</span><span class="fu">objectBuilder</span><span class="op">()</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;name&quot;</span><span class="op">,</span> <span class="st">&quot;kermit&quot;</span><span class="op">)</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;age&quot;</span><span class="op">,</span> <span class="dv">22</span><span class="op">)</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">putTrue</span><span class="op">(</span><span class="st">&quot;commitmentIssues&quot;</span><span class="op">)</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">putNull</span><span class="op">(</span><span class="st">&quot;wife&quot;</span><span class="op">)</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;children&quot;</span><span class="op">,</span> Json<span class="op">.</span><span class="fu">arrayBuilder</span><span class="op">()</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>                        <span class="op">.</span><span class="fu">add</span><span class="op">(</span><span class="st">&quot;Tiny Tim&quot;</span><span class="op">))</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">build</span><span class="op">();</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>kermit<span class="op">);</span></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="writing">Writing</h3>
<p>Once you have some <code>Json</code> you can write it out to a <code>String</code> using <code>Json.writeString</code></p>
<div class="sourceCode" id="cb8"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.</span><span class="im">Json</span><span class="op">;</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>        Json songJson <span class="op">=</span> Json<span class="op">.</span><span class="fu">objectBuilder</span><span class="op">()</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;title&quot;</span><span class="op">,</span> <span class="st">&quot;Rainbow Connection&quot;</span><span class="op">)</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;year&quot;</span><span class="op">,</span> <span class="dv">1979</span><span class="op">)</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">build</span><span class="op">();</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>        <span class="bu">String</span> song <span class="op">=</span> Json<span class="op">.</span><span class="fu">writeString</span><span class="op">(</span>songJson<span class="op">);</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>song<span class="op">);</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb9"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span><span class="dt">&quot;title&quot;</span><span class="fu">:</span><span class="st">&quot;Rainbow Connection&quot;</span><span class="fu">,</span><span class="dt">&quot;year&quot;</span><span class="fu">:</span><span class="dv">1979</span><span class="fu">}</span></span></code></pre></div>
<p>If output is meant to be consumed by humans then whitespace can be added using a customized instance of <code>JsonWriteOptions</code>.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.</span><span class="im">Json</span><span class="op">;</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.</span><span class="im">JsonWriteOptions</span><span class="op">;</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>        Json songJson <span class="op">=</span> Json<span class="op">.</span><span class="fu">objectBuilder</span><span class="op">()</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;title&quot;</span><span class="op">,</span> <span class="st">&quot;Rainbow Connection&quot;</span><span class="op">)</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;year&quot;</span><span class="op">,</span> <span class="dv">1979</span><span class="op">)</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">build</span><span class="op">();</span></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a>        <span class="bu">String</span> song <span class="op">=</span> Json<span class="op">.</span><span class="fu">writeString</span><span class="op">(</span></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a>                songJson<span class="op">,</span></span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a>                <span class="kw">new</span> <span class="fu">JsonWriteOptions</span><span class="op">()</span></span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a>                        <span class="op">.</span><span class="fu">withIndentation</span><span class="op">(</span><span class="dv">4</span><span class="op">)</span></span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>song<span class="op">);</span></span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb11"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">&quot;title&quot;</span><span class="fu">:</span> <span class="st">&quot;Rainbow Connection&quot;</span><span class="fu">,</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">&quot;year&quot;</span><span class="fu">:</span> <span class="dv">1979</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a><span class="fu">}</span></span></code></pre></div>
<p>If you want to write JSON to something other than a <code>String</code>, you need to obtain a <code>Writer</code> and use <code>Json.write</code>.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.</span><span class="im">Json</span><span class="op">;</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">io</span><span class="op">.</span><span class="im">IOException</span><span class="op">;</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">nio</span><span class="op">.</span><span class="im">file</span><span class="op">.</span><span class="im">Files</span><span class="op">;</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">nio</span><span class="op">.</span><span class="im">file</span><span class="op">.</span><span class="im">Path</span><span class="op">;</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>        Json songJson <span class="op">=</span> Json<span class="op">.</span><span class="fu">objectBuilder</span><span class="op">()</span></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;title&quot;</span><span class="op">,</span> <span class="st">&quot;Rainbow Connection&quot;</span><span class="op">)</span></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;year&quot;</span><span class="op">,</span> <span class="dv">1979</span><span class="op">)</span></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">build</span><span class="op">();</span></span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span>var fileWriter <span class="op">=</span> Files<span class="op">.</span><span class="fu">newBufferedWriter</span><span class="op">(</span></span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true" tabindex="-1"></a>                Path<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;song.json&quot;</span><span class="op">))</span></span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="op">{</span></span>
<span id="cb12-18"><a href="#cb12-18" aria-hidden="true" tabindex="-1"></a>            Json<span class="op">.</span><span class="fu">write</span><span class="op">(</span>songJson<span class="op">,</span> fileWriter<span class="op">);</span></span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb12-20"><a href="#cb12-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb12-21"><a href="#cb12-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="encoding">Encoding</h3>
<p>To turn a class you have defined into JSON, you just need to make a method which creates an instance of <code>Json</code> from the data stored in your class.</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.</span><span class="im">Json</span><span class="op">;</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Muppet</span><span class="op">(</span><span class="bu">String</span> name<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>    Json <span class="fu">toJson</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> Json<span class="op">.</span><span class="fu">objectBuilder</span><span class="op">()</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;name&quot;</span><span class="op">,</span> name<span class="op">)</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">build</span><span class="op">();</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>        var beaker <span class="op">=</span> <span class="kw">new</span> <span class="fu">Muppet</span><span class="op">(</span><span class="st">&quot;beaker&quot;</span><span class="op">);</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a>        Json beakerJson <span class="op">=</span> beaker<span class="op">.</span><span class="fu">toJson</span><span class="op">();</span></span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>Json<span class="op">.</span><span class="fu">writeString</span><span class="op">(</span>beakerJson<span class="op">));</span></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This process is "encoding." You "encode" your data into JSON and then "write" that JSON to some output.</p>
<p>For classes that you did not define, the logic for the conversion just needs to live somewhere. Dealer's choice where, but static methods are generally a good call.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.</span><span class="im">Json</span><span class="op">;</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">time</span><span class="op">.</span><span class="im">Month</span><span class="op">;</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">time</span><span class="op">.</span><span class="im">MonthDay</span><span class="op">;</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">time</span><span class="op">.</span><span class="im">format</span><span class="op">.</span><span class="im">DateTimeFormatter</span><span class="op">;</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a><span class="dt">final</span> <span class="kw">class</span> TimeEncoders <span class="op">{</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">TimeEncoders</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> Json <span class="fu">monthDayToJson</span><span class="op">(</span>MonthDay monthDay<span class="op">)</span> <span class="op">{</span></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> Json<span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a>                DateTimeFormatter<span class="op">.</span><span class="fu">ofPattern</span><span class="op">(</span><span class="st">&quot;MM-dd&quot;</span><span class="op">)</span></span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a>                        <span class="op">.</span><span class="fu">format</span><span class="op">(</span>monthDay<span class="op">)</span></span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-16"><a href="#cb14-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb14-17"><a href="#cb14-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-18"><a href="#cb14-18" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Muppet</span><span class="op">(</span><span class="bu">String</span> name<span class="op">,</span> MonthDay birthday<span class="op">)</span> <span class="op">{</span></span>
<span id="cb14-19"><a href="#cb14-19" aria-hidden="true" tabindex="-1"></a>    Json <span class="fu">toJson</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb14-20"><a href="#cb14-20" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> Json<span class="op">.</span><span class="fu">objectBuilder</span><span class="op">()</span></span>
<span id="cb14-21"><a href="#cb14-21" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;name&quot;</span><span class="op">,</span> name<span class="op">)</span></span>
<span id="cb14-22"><a href="#cb14-22" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">put</span><span class="op">(</span></span>
<span id="cb14-23"><a href="#cb14-23" aria-hidden="true" tabindex="-1"></a>                        <span class="st">&quot;birthday&quot;</span><span class="op">,</span> </span>
<span id="cb14-24"><a href="#cb14-24" aria-hidden="true" tabindex="-1"></a>                        TimeEncoders<span class="op">.</span><span class="fu">monthDayToJson</span><span class="op">(</span>birthday<span class="op">)</span></span>
<span id="cb14-25"><a href="#cb14-25" aria-hidden="true" tabindex="-1"></a>                <span class="op">)</span></span>
<span id="cb14-26"><a href="#cb14-26" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">build</span><span class="op">();</span></span>
<span id="cb14-27"><a href="#cb14-27" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-28"><a href="#cb14-28" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb14-29"><a href="#cb14-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-30"><a href="#cb14-30" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb14-31"><a href="#cb14-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb14-32"><a href="#cb14-32" aria-hidden="true" tabindex="-1"></a>        var elmo <span class="op">=</span> <span class="kw">new</span> <span class="fu">Muppet</span><span class="op">(</span></span>
<span id="cb14-33"><a href="#cb14-33" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;Elmo&quot;</span><span class="op">,</span></span>
<span id="cb14-34"><a href="#cb14-34" aria-hidden="true" tabindex="-1"></a>                MonthDay<span class="op">.</span><span class="fu">of</span><span class="op">(</span>Month<span class="op">.</span><span class="fu">FEBRUARY</span><span class="op">,</span> <span class="dv">3</span><span class="op">)</span></span>
<span id="cb14-35"><a href="#cb14-35" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb14-36"><a href="#cb14-36" aria-hidden="true" tabindex="-1"></a>        Json elmoJson <span class="op">=</span> elmo<span class="op">.</span><span class="fu">toJson</span><span class="op">();</span></span>
<span id="cb14-37"><a href="#cb14-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-38"><a href="#cb14-38" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>Json<span class="op">.</span><span class="fu">writeString</span><span class="op">(</span>elmoJson<span class="op">));</span></span>
<span id="cb14-39"><a href="#cb14-39" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-40"><a href="#cb14-40" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb15"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span><span class="dt">&quot;name&quot;</span><span class="fu">:</span><span class="st">&quot;Elmo&quot;</span><span class="fu">,</span><span class="dt">&quot;birthday&quot;</span><span class="fu">:</span><span class="st">&quot;02-03&quot;</span><span class="fu">}</span></span></code></pre></div>
<p>If a class you define has a JSON representation that could be considered "canonical", the interface <code>JsonEncodable</code> can be implemented. This will let you pass an instance of the class directly to <code>Json.writeString</code> or <code>Json.write</code>.</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.</span><span class="im">Json</span><span class="op">;</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.</span><span class="im">JsonEncodable</span><span class="op">;</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Muppet</span><span class="op">(</span><span class="bu">String</span> name<span class="op">,</span> <span class="dt">boolean</span> great<span class="op">)</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">implements</span> JsonEncodable <span class="op">{</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> Json <span class="fu">toJson</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> Json<span class="op">.</span><span class="fu">objectBuilder</span><span class="op">()</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;name&quot;</span><span class="op">,</span> name<span class="op">)</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;great&quot;</span><span class="op">,</span> great<span class="op">)</span></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">build</span><span class="op">();</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a>        var gonzo <span class="op">=</span> <span class="kw">new</span> <span class="fu">Muppet</span><span class="op">(</span><span class="st">&quot;Gonzo&quot;</span><span class="op">,</span> <span class="kw">true</span><span class="op">);</span></span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>Json<span class="op">.</span><span class="fu">writeString</span><span class="op">(</span>gonzo<span class="op">));</span></span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-20"><a href="#cb16-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="reading">Reading</h3>
<p>The inverse of writing JSON is reading it.</p>
<p>If you have some JSON stored in a <code>String</code> you can read it into <code>Json</code> using <code>Json.readString</code>.</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.</span><span class="im">Json</span><span class="op">;</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a>        Json movie <span class="op">=</span> Json<span class="op">.</span><span class="fu">readString</span><span class="op">(</span><span class="st">&quot;&quot;&quot;</span></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>                <span class="op">{</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;title&quot;</span><span class="op">:</span> <span class="st">&quot;Treasure Island&quot;</span><span class="op">,</span></span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;cast&quot;</span><span class="op">:</span> <span class="op">[</span></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a>                        <span class="op">{</span></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a>                            <span class="st">&quot;name&quot;</span><span class="op">:</span> <span class="st">&quot;Kermit&quot;</span><span class="op">,</span></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a>                            <span class="st">&quot;role&quot;</span><span class="op">:</span> <span class="st">&quot;The Captain&quot;</span><span class="op">,</span></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a>                            <span class="st">&quot;muppet&quot;</span><span class="op">:</span> <span class="kw">true</span></span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a>                        <span class="op">},</span></span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a>                        <span class="op">{</span></span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a>                            <span class="st">&quot;name&quot;</span><span class="op">:</span> <span class="st">&quot;Tim Curry&quot;</span><span class="op">,</span></span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a>                            <span class="st">&quot;role&quot;</span><span class="op">:</span> <span class="st">&quot;Long John Silver&quot;</span><span class="op">,</span></span>
<span id="cb17-17"><a href="#cb17-17" aria-hidden="true" tabindex="-1"></a>                            <span class="st">&quot;muppet&quot;</span><span class="op">:</span> <span class="kw">false</span></span>
<span id="cb17-18"><a href="#cb17-18" aria-hidden="true" tabindex="-1"></a>                        <span class="op">}</span></span>
<span id="cb17-19"><a href="#cb17-19" aria-hidden="true" tabindex="-1"></a>                    <span class="op">]</span></span>
<span id="cb17-20"><a href="#cb17-20" aria-hidden="true" tabindex="-1"></a>                </span>
<span id="cb17-21"><a href="#cb17-21" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb17-22"><a href="#cb17-22" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;&quot;&quot;);</span></span>
<span id="cb17-23"><a href="#cb17-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-24"><a href="#cb17-24" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>movie<span class="op">);</span></span>
<span id="cb17-25"><a href="#cb17-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb17-26"><a href="#cb17-26" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>If that JSON is coming from another source, you need to obtain a <code>Reader</code> and use <code>Json.read</code>.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.</span><span class="im">Json</span><span class="op">;</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">io</span><span class="op">.</span><span class="im">IOException</span><span class="op">;</span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">io</span><span class="op">.</span><span class="im">Reader</span><span class="op">;</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">nio</span><span class="op">.</span><span class="im">file</span><span class="op">.</span><span class="im">Files</span><span class="op">;</span></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">nio</span><span class="op">.</span><span class="im">file</span><span class="op">.</span><span class="im">Path</span><span class="op">;</span></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a>        <span class="co">// If you were following along, we created this earlier!</span></span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a>        Json song<span class="op">;</span></span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span><span class="bu">Reader</span> fileReader <span class="op">=</span> Files<span class="op">.</span><span class="fu">newBufferedReader</span><span class="op">(</span></span>
<span id="cb18-13"><a href="#cb18-13" aria-hidden="true" tabindex="-1"></a>                Path<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;song.json&quot;</span><span class="op">))</span></span>
<span id="cb18-14"><a href="#cb18-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="op">{</span></span>
<span id="cb18-15"><a href="#cb18-15" aria-hidden="true" tabindex="-1"></a>            song <span class="op">=</span> Json<span class="op">.</span><span class="fu">read</span><span class="op">(</span>fileReader<span class="op">);</span></span>
<span id="cb18-16"><a href="#cb18-16" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb18-17"><a href="#cb18-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-18"><a href="#cb18-18" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>song<span class="op">);</span></span>
<span id="cb18-19"><a href="#cb18-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb18-20"><a href="#cb18-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>If the JSON you provide is malformed in some way, a <code>JsonReadException</code> will be thrown.</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.</span><span class="im">Json</span><span class="op">;</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a>        <span class="co">// Should be in quotes</span></span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>        Json<span class="op">.</span><span class="fu">readString</span><span class="op">(</span><span class="st">&quot;fozzie&quot;</span><span class="op">);</span></span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb20"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="bu">Exception</span> in thread <span class="st">&quot;main&quot;</span> dev<span class="op">.</span><span class="fu">mccue</span><span class="op">.</span><span class="fu">json</span><span class="op">.</span><span class="fu">JsonReadException</span><span class="op">:</span> JSON <span class="fu">error</span> <span class="op">(</span>unexpected character<span class="op">):</span> f</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>    at dev<span class="op">.</span><span class="fu">mccue</span><span class="op">.</span><span class="fu">json</span><span class="op">.</span><span class="fu">JsonReadException</span><span class="op">.</span><span class="fu">unexpectedCharacter</span><span class="op">(</span>JsonReadException<span class="op">.</span><span class="fu">java</span><span class="op">:</span><span class="dv">33</span><span class="op">)</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>    at dev<span class="op">.</span><span class="fu">mccue</span><span class="op">.</span><span class="fu">json</span><span class="op">.</span><span class="fu">internal</span><span class="op">.</span><span class="fu">JsonReaderMethods</span><span class="op">.</span><span class="fu">readStream</span><span class="op">(</span>JsonReaderMethods<span class="op">.</span><span class="fu">java</span><span class="op">:</span><span class="dv">525</span><span class="op">)</span></span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>    at dev<span class="op">.</span><span class="fu">mccue</span><span class="op">.</span><span class="fu">json</span><span class="op">.</span><span class="fu">internal</span><span class="op">.</span><span class="fu">JsonReaderMethods</span><span class="op">.</span><span class="fu">read</span><span class="op">(</span>JsonReaderMethods<span class="op">.</span><span class="fu">java</span><span class="op">:</span><span class="dv">533</span><span class="op">)</span></span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a>    at dev<span class="op">.</span><span class="fu">mccue</span><span class="op">.</span><span class="fu">json</span><span class="op">.</span><span class="fu">internal</span><span class="op">.</span><span class="fu">JsonReaderMethods</span><span class="op">.</span><span class="fu">readFullyConsume</span><span class="op">(</span>JsonReaderMethods<span class="op">.</span><span class="fu">java</span><span class="op">:</span><span class="dv">543</span><span class="op">)</span></span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a>    at dev<span class="op">.</span><span class="fu">mccue</span><span class="op">.</span><span class="fu">json</span><span class="op">.</span><span class="fu">Json</span><span class="op">.</span><span class="fu">readString</span><span class="op">(</span>Json<span class="op">.</span><span class="fu">java</span><span class="op">:</span><span class="dv">369</span><span class="op">)</span></span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a>    at dev<span class="op">.</span><span class="fu">mccue</span><span class="op">.</span><span class="fu">json</span><span class="op">.</span><span class="fu">Json</span><span class="op">.</span><span class="fu">readString</span><span class="op">(</span>Json<span class="op">.</span><span class="fu">java</span><span class="op">:</span><span class="dv">364</span><span class="op">)</span></span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a>    at dev<span class="op">.</span><span class="fu">mccue</span><span class="op">.</span><span class="fu">example</span><span class="op">.</span><span class="fu">Main</span><span class="op">.</span><span class="fu">main</span><span class="op">(</span>Main<span class="op">.</span><span class="fu">java</span><span class="op">:</span><span class="dv">9</span><span class="op">)</span></span></code></pre></div>
<h3 id="decoding">Decoding</h3>
<p>Up to this point, everything has been more or less the same as it is for other "tree-based" JSON libraries like <a href="https://github.com/stleary/JSON-java">org.json</a> or <a href="https://github.com/fangyidong/json-simple">json-simple</a>.</p>
<p>This is where that will start to change.</p>
<p>To take some <code>Json</code> and turn it into a user defined class, a basic approach would be to use <code>instanceof</code> checks to see if the <code>Json</code> is a particular subtype and navigate from there.</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.*;</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Muppet</span><span class="op">(</span><span class="bu">String</span> name<span class="op">,</span> <span class="dt">boolean</span> canSpeak<span class="op">)</span> <span class="op">{</span></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> Muppet <span class="fu">fromJson</span><span class="op">(</span>Json json<span class="op">)</span> <span class="op">{</span></span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>json <span class="kw">instanceof</span> JsonObject object <span class="op">&amp;&amp;</span></span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>            object<span class="op">.</span><span class="fu">get</span><span class="op">(</span><span class="st">&quot;name&quot;</span><span class="op">)</span> <span class="kw">instanceof</span> JsonString name <span class="op">&amp;&amp;</span></span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a>            object<span class="op">.</span><span class="fu">get</span><span class="op">(</span><span class="st">&quot;canSpeak&quot;</span><span class="op">)</span> <span class="kw">instanceof</span> JsonBoolean canSpeak<span class="op">)</span> <span class="op">{</span></span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Muppet</span><span class="op">(</span>name<span class="op">.</span><span class="fu">toString</span><span class="op">(),</span> canSpeak<span class="op">.</span><span class="fu">value</span><span class="op">());</span></span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb21-11"><a href="#cb21-11" aria-hidden="true" tabindex="-1"></a>            <span class="cf">throw</span> <span class="kw">new</span> <span class="bu">RuntimeException</span><span class="op">(</span><span class="st">&quot;Invalid Muppet&quot;</span><span class="op">);</span></span>
<span id="cb21-12"><a href="#cb21-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb21-13"><a href="#cb21-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb21-14"><a href="#cb21-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb21-15"><a href="#cb21-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-16"><a href="#cb21-16" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb21-17"><a href="#cb21-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb21-18"><a href="#cb21-18" aria-hidden="true" tabindex="-1"></a>        var json <span class="op">=</span> Json<span class="op">.</span><span class="fu">readString</span><span class="op">(</span><span class="st">&quot;&quot;&quot;</span></span>
<span id="cb21-19"><a href="#cb21-19" aria-hidden="true" tabindex="-1"></a>                <span class="op">{</span></span>
<span id="cb21-20"><a href="#cb21-20" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;name&quot;</span><span class="op">:</span> <span class="st">&quot;animal&quot;</span><span class="op">,</span></span>
<span id="cb21-21"><a href="#cb21-21" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;canSpeak&quot;</span><span class="op">:</span> <span class="kw">false</span></span>
<span id="cb21-22"><a href="#cb21-22" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb21-23"><a href="#cb21-23" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;&quot;&quot;);</span></span>
<span id="cb21-24"><a href="#cb21-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-25"><a href="#cb21-25" aria-hidden="true" tabindex="-1"></a>        var animal <span class="op">=</span> Muppet<span class="op">.</span><span class="fu">fromJson</span><span class="op">(</span>json<span class="op">);</span></span>
<span id="cb21-26"><a href="#cb21-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-27"><a href="#cb21-27" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>animal<span class="op">);</span></span>
<span id="cb21-28"><a href="#cb21-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb21-29"><a href="#cb21-29" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This process is "decoding." You "read" your data into JSON and then "decode" it to some type you define.</p>
<p>The problem with the <code>instanceof</code> approach is that you will end up with bad error messages on unexpected data. In this case the error message would just be <code>"Invalid Muppet"</code>. The code to get better errors is tedious to write and I haven't seen many folks in the wild do it.</p>
<p>To get good errors, you should use the static methods defined in <code>JsonDecoder</code>.</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span><span class="im"> dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">example</span><span class="op">;</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.*;</span></span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Muppet</span><span class="op">(</span><span class="bu">String</span> name<span class="op">,</span> <span class="dt">boolean</span> canSpeak<span class="op">)</span> <span class="op">{</span></span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> Muppet <span class="fu">fromJson</span><span class="op">(</span>Json json<span class="op">)</span> <span class="op">{</span></span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Muppet</span><span class="op">(</span></span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a>                JsonDecoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span></span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a>                        json<span class="op">,</span></span>
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a>                        <span class="st">&quot;name&quot;</span><span class="op">,</span> </span>
<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a>                        JsonDecoder<span class="op">::</span>string</span>
<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a>                <span class="op">),</span></span>
<span id="cb22-13"><a href="#cb22-13" aria-hidden="true" tabindex="-1"></a>                JsonDecoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span></span>
<span id="cb22-14"><a href="#cb22-14" aria-hidden="true" tabindex="-1"></a>                        json<span class="op">,</span> </span>
<span id="cb22-15"><a href="#cb22-15" aria-hidden="true" tabindex="-1"></a>                        <span class="st">&quot;canSpeak&quot;</span><span class="op">,</span> </span>
<span id="cb22-16"><a href="#cb22-16" aria-hidden="true" tabindex="-1"></a>                        JsonDecoder<span class="op">::</span>boolean_</span>
<span id="cb22-17"><a href="#cb22-17" aria-hidden="true" tabindex="-1"></a>                <span class="op">)</span></span>
<span id="cb22-18"><a href="#cb22-18" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb22-19"><a href="#cb22-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb22-20"><a href="#cb22-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb22-21"><a href="#cb22-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-22"><a href="#cb22-22" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb22-23"><a href="#cb22-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb22-24"><a href="#cb22-24" aria-hidden="true" tabindex="-1"></a>        var json <span class="op">=</span> Json<span class="op">.</span><span class="fu">readString</span><span class="op">(</span><span class="st">&quot;&quot;&quot;</span></span>
<span id="cb22-25"><a href="#cb22-25" aria-hidden="true" tabindex="-1"></a>                <span class="op">{</span></span>
<span id="cb22-26"><a href="#cb22-26" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;name&quot;</span><span class="op">:</span> <span class="st">&quot;animal&quot;</span><span class="op">,</span></span>
<span id="cb22-27"><a href="#cb22-27" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;canSpeak&quot;</span><span class="op">:</span> <span class="kw">false</span></span>
<span id="cb22-28"><a href="#cb22-28" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb22-29"><a href="#cb22-29" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;&quot;&quot;);</span></span>
<span id="cb22-30"><a href="#cb22-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-31"><a href="#cb22-31" aria-hidden="true" tabindex="-1"></a>        var animal <span class="op">=</span> Muppet<span class="op">.</span><span class="fu">fromJson</span><span class="op">(</span>json<span class="op">);</span></span>
<span id="cb22-32"><a href="#cb22-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-33"><a href="#cb22-33" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>animal<span class="op">);</span></span>
<span id="cb22-34"><a href="#cb22-34" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb22-35"><a href="#cb22-35" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>These handle the fiddly process of checking whether the JSON matches the structure you expect and throwing an appropriate error.</p>
<p>You should read this declaration as "at the field <code>name</code> I expect a string."</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a>JsonDecoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span>json<span class="op">,</span> <span class="st">&quot;name&quot;</span><span class="op">,</span> JsonDecoder<span class="op">::</span>string<span class="op">)</span></span></code></pre></div>
<p>If the JSON is not an object, or doesn't have a value for <code>name</code>, or that value is not a string, you will get a <code>JsonDecodeException</code>.</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>        var json <span class="op">=</span> Json<span class="op">.</span><span class="fu">readString</span><span class="op">(</span><span class="st">&quot;&quot;&quot;</span></span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>                <span class="op">{</span></span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;canSpeak&quot;</span><span class="op">:</span> <span class="kw">false</span></span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;&quot;&quot;);</span></span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a>        var animal <span class="op">=</span> JsonDecoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span></span>
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a>                json<span class="op">,</span> </span>
<span id="cb24-11"><a href="#cb24-11" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;name&quot;</span><span class="op">,</span> </span>
<span id="cb24-12"><a href="#cb24-12" aria-hidden="true" tabindex="-1"></a>                JsonDecoder<span class="op">::</span>string</span>
<span id="cb24-13"><a href="#cb24-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb24-14"><a href="#cb24-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-15"><a href="#cb24-15" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>animal<span class="op">);</span></span>
<span id="cb24-16"><a href="#cb24-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb24-17"><a href="#cb24-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Which will have a message indicating exactly what went wrong and where.</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a>Problem with the value at json<span class="op">.</span><span class="fu">name</span><span class="op">:</span></span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;canSpeak&quot;</span><span class="op">:</span> <span class="kw">false</span></span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-7"><a href="#cb25-7" aria-hidden="true" tabindex="-1"></a>no value <span class="cf">for</span> field</span></code></pre></div>
<p>The last argument to <code>JsonDecoder.field</code> is the <code>JsonDecoder</code> you want to use to interpret the value at that field. In this case a method reference to <code>JsonDecoder.string</code>, which is a method that asserts JSON is a string and throws if it isn't.</p>
<p>For the methods which take more than one argument, there are overloads which can be used to get an instance of <code>JsonDecoder</code>.</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="co">// This will actually decode the json into a list of strings</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a><span class="bu">List</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> items <span class="op">=</span> JsonDecoder<span class="op">.</span><span class="fu">array</span><span class="op">(</span>json<span class="op">,</span> JsonDecoder<span class="op">::</span>string<span class="op">);</span></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a><span class="co">// This will just return a decoder</span></span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a>Decoder<span class="op">&lt;</span><span class="bu">List</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;&gt;</span> decoder <span class="op">=</span> </span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a>        JsonDecoder<span class="op">.</span><span class="fu">array</span><span class="op">(</span>JsonDecoder<span class="op">::</span>string<span class="op">);</span></span></code></pre></div>
<p>This, in conjunction with <code>JsonDecoder.field</code> is how you are intended to explore nested paths.</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a>        var json <span class="op">=</span> Json<span class="op">.</span><span class="fu">readString</span><span class="op">(</span><span class="st">&quot;&quot;&quot;</span></span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a>                <span class="op">{</span></span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;villains&quot;</span><span class="op">:</span> <span class="op">[</span><span class="st">&quot;constantine&quot;</span><span class="op">,</span> <span class="st">&quot;doc hopper&quot;</span><span class="op">]</span></span>
<span id="cb27-6"><a href="#cb27-6" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb27-7"><a href="#cb27-7" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;&quot;&quot;);</span></span>
<span id="cb27-8"><a href="#cb27-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-9"><a href="#cb27-9" aria-hidden="true" tabindex="-1"></a>        <span class="bu">List</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> villains <span class="op">=</span> JsonDecoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span></span>
<span id="cb27-10"><a href="#cb27-10" aria-hidden="true" tabindex="-1"></a>                json<span class="op">,</span></span>
<span id="cb27-11"><a href="#cb27-11" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;villains&quot;</span><span class="op">,</span></span>
<span id="cb27-12"><a href="#cb27-12" aria-hidden="true" tabindex="-1"></a>                JsonDecoder<span class="op">.</span><span class="fu">array</span><span class="op">(</span>JsonDecoder<span class="op">::</span>string<span class="op">)</span></span>
<span id="cb27-13"><a href="#cb27-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb27-14"><a href="#cb27-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-15"><a href="#cb27-15" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>villains<span class="op">);</span></span>
<span id="cb27-16"><a href="#cb27-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb27-17"><a href="#cb27-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>To decode JSON into your custom classes, you should add either a constructor or a static factory method which takes in <code>Json</code> and use these decoders to make your objects.</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.*;</span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">List</span><span class="op">;</span></span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Actor</span><span class="op">(</span><span class="bu">String</span> name<span class="op">,</span> <span class="bu">String</span> role<span class="op">,</span> <span class="dt">boolean</span> muppet<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> Actor <span class="fu">fromJson</span><span class="op">(</span>Json json<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Actor</span><span class="op">(</span></span>
<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a>                JsonDecoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span>json<span class="op">,</span> <span class="st">&quot;name&quot;</span><span class="op">,</span> JsonDecoder<span class="op">::</span>string<span class="op">),</span></span>
<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a>                JsonDecoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span>json<span class="op">,</span> <span class="st">&quot;role&quot;</span><span class="op">,</span> JsonDecoder<span class="op">::</span>string<span class="op">),</span></span>
<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a>                JsonDecoder<span class="op">.</span><span class="fu">optionalField</span><span class="op">(</span></span>
<span id="cb28-11"><a href="#cb28-11" aria-hidden="true" tabindex="-1"></a>                        json<span class="op">,</span> </span>
<span id="cb28-12"><a href="#cb28-12" aria-hidden="true" tabindex="-1"></a>                        <span class="st">&quot;muppet&quot;</span><span class="op">,</span></span>
<span id="cb28-13"><a href="#cb28-13" aria-hidden="true" tabindex="-1"></a>                        JsonDecoder<span class="op">::</span>boolean_<span class="op">,</span></span>
<span id="cb28-14"><a href="#cb28-14" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">true</span></span>
<span id="cb28-15"><a href="#cb28-15" aria-hidden="true" tabindex="-1"></a>                <span class="op">)</span></span>
<span id="cb28-16"><a href="#cb28-16" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb28-17"><a href="#cb28-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-18"><a href="#cb28-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb28-19"><a href="#cb28-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-20"><a href="#cb28-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-21"><a href="#cb28-21" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Movie</span><span class="op">(</span><span class="bu">String</span> title<span class="op">,</span> <span class="bu">List</span><span class="op">&lt;</span>Actor<span class="op">&gt;</span> cast<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-22"><a href="#cb28-22" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> Movie <span class="fu">fromJson</span><span class="op">(</span>Json json<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-23"><a href="#cb28-23" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Movie</span><span class="op">(</span></span>
<span id="cb28-24"><a href="#cb28-24" aria-hidden="true" tabindex="-1"></a>                JsonDecoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span>json<span class="op">,</span> <span class="st">&quot;title&quot;</span><span class="op">,</span> JsonDecoder<span class="op">::</span>string<span class="op">),</span></span>
<span id="cb28-25"><a href="#cb28-25" aria-hidden="true" tabindex="-1"></a>                JsonDecoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span></span>
<span id="cb28-26"><a href="#cb28-26" aria-hidden="true" tabindex="-1"></a>                        json<span class="op">,</span> </span>
<span id="cb28-27"><a href="#cb28-27" aria-hidden="true" tabindex="-1"></a>                        <span class="st">&quot;cast&quot;</span><span class="op">,</span> </span>
<span id="cb28-28"><a href="#cb28-28" aria-hidden="true" tabindex="-1"></a>                        JsonDecoder<span class="op">.</span><span class="fu">array</span><span class="op">(</span>Actor<span class="op">::</span>fromJson<span class="op">)</span></span>
<span id="cb28-29"><a href="#cb28-29" aria-hidden="true" tabindex="-1"></a>                <span class="op">)</span></span>
<span id="cb28-30"><a href="#cb28-30" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb28-31"><a href="#cb28-31" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-32"><a href="#cb28-32" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb28-33"><a href="#cb28-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-34"><a href="#cb28-34" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb28-35"><a href="#cb28-35" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-36"><a href="#cb28-36" aria-hidden="true" tabindex="-1"></a>        var json <span class="op">=</span> Json<span class="op">.</span><span class="fu">readString</span><span class="op">(</span><span class="st">&quot;&quot;&quot;</span></span>
<span id="cb28-37"><a href="#cb28-37" aria-hidden="true" tabindex="-1"></a>                 <span class="op">{</span></span>
<span id="cb28-38"><a href="#cb28-38" aria-hidden="true" tabindex="-1"></a>                     <span class="st">&quot;title&quot;</span><span class="op">:</span> <span class="st">&quot;Treasure Island&quot;</span><span class="op">,</span></span>
<span id="cb28-39"><a href="#cb28-39" aria-hidden="true" tabindex="-1"></a>                     <span class="st">&quot;cast&quot;</span><span class="op">:</span> <span class="op">[</span></span>
<span id="cb28-40"><a href="#cb28-40" aria-hidden="true" tabindex="-1"></a>                         <span class="op">{</span></span>
<span id="cb28-41"><a href="#cb28-41" aria-hidden="true" tabindex="-1"></a>                             <span class="st">&quot;name&quot;</span><span class="op">:</span> <span class="st">&quot;Kermit&quot;</span><span class="op">,</span></span>
<span id="cb28-42"><a href="#cb28-42" aria-hidden="true" tabindex="-1"></a>                             <span class="st">&quot;role&quot;</span><span class="op">:</span> <span class="st">&quot;The Captain&quot;</span></span>
<span id="cb28-43"><a href="#cb28-43" aria-hidden="true" tabindex="-1"></a>                         <span class="op">},</span></span>
<span id="cb28-44"><a href="#cb28-44" aria-hidden="true" tabindex="-1"></a>                         <span class="op">{</span></span>
<span id="cb28-45"><a href="#cb28-45" aria-hidden="true" tabindex="-1"></a>                             <span class="st">&quot;name&quot;</span><span class="op">:</span> <span class="st">&quot;Tim Curry&quot;</span><span class="op">,</span></span>
<span id="cb28-46"><a href="#cb28-46" aria-hidden="true" tabindex="-1"></a>                             <span class="st">&quot;role&quot;</span><span class="op">:</span> <span class="st">&quot;Long John Silver&quot;</span><span class="op">,</span></span>
<span id="cb28-47"><a href="#cb28-47" aria-hidden="true" tabindex="-1"></a>                             <span class="st">&quot;muppet&quot;</span><span class="op">:</span> <span class="kw">false</span></span>
<span id="cb28-48"><a href="#cb28-48" aria-hidden="true" tabindex="-1"></a>                         <span class="op">}</span></span>
<span id="cb28-49"><a href="#cb28-49" aria-hidden="true" tabindex="-1"></a>                     <span class="op">]</span></span>
<span id="cb28-50"><a href="#cb28-50" aria-hidden="true" tabindex="-1"></a>                 <span class="op">}</span></span>
<span id="cb28-51"><a href="#cb28-51" aria-hidden="true" tabindex="-1"></a>                 <span class="st">&quot;&quot;&quot;);</span></span>
<span id="cb28-52"><a href="#cb28-52" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-53"><a href="#cb28-53" aria-hidden="true" tabindex="-1"></a>        var movie <span class="op">=</span> Movie<span class="op">.</span><span class="fu">fromJson</span><span class="op">(</span>json<span class="op">);</span></span>
<span id="cb28-54"><a href="#cb28-54" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-55"><a href="#cb28-55" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>movie<span class="op">);</span></span>
<span id="cb28-56"><a href="#cb28-56" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-57"><a href="#cb28-57" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="full-round-trip">Full Round-Trip</h3>
<p>With all of that out of the way, here is how you might define a model, write it to json, and read it back in.</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.*;</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">List</span><span class="op">;</span></span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Actor</span><span class="op">(</span><span class="bu">String</span> name<span class="op">,</span> <span class="bu">String</span> role<span class="op">,</span> <span class="dt">boolean</span> muppet<span class="op">)</span></span>
<span id="cb29-6"><a href="#cb29-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">implements</span> JsonEncodable <span class="op">{</span></span>
<span id="cb29-7"><a href="#cb29-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> Actor <span class="fu">fromJson</span><span class="op">(</span>Json json<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-8"><a href="#cb29-8" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Actor</span><span class="op">(</span></span>
<span id="cb29-9"><a href="#cb29-9" aria-hidden="true" tabindex="-1"></a>                JsonDecoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span>json<span class="op">,</span> <span class="st">&quot;name&quot;</span><span class="op">,</span> JsonDecoder<span class="op">::</span>string<span class="op">),</span></span>
<span id="cb29-10"><a href="#cb29-10" aria-hidden="true" tabindex="-1"></a>                JsonDecoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span>json<span class="op">,</span> <span class="st">&quot;role&quot;</span><span class="op">,</span> JsonDecoder<span class="op">::</span>string<span class="op">),</span></span>
<span id="cb29-11"><a href="#cb29-11" aria-hidden="true" tabindex="-1"></a>                JsonDecoder<span class="op">.</span><span class="fu">optionalField</span><span class="op">(</span></span>
<span id="cb29-12"><a href="#cb29-12" aria-hidden="true" tabindex="-1"></a>                        json<span class="op">,</span></span>
<span id="cb29-13"><a href="#cb29-13" aria-hidden="true" tabindex="-1"></a>                        <span class="st">&quot;muppet&quot;</span><span class="op">,</span></span>
<span id="cb29-14"><a href="#cb29-14" aria-hidden="true" tabindex="-1"></a>                        JsonDecoder<span class="op">::</span>boolean_<span class="op">,</span></span>
<span id="cb29-15"><a href="#cb29-15" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">true</span><span class="op">)</span></span>
<span id="cb29-16"><a href="#cb29-16" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb29-17"><a href="#cb29-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb29-18"><a href="#cb29-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-19"><a href="#cb29-19" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb29-20"><a href="#cb29-20" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> Json <span class="fu">toJson</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb29-21"><a href="#cb29-21" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> Json<span class="op">.</span><span class="fu">objectBuilder</span><span class="op">()</span></span>
<span id="cb29-22"><a href="#cb29-22" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;name&quot;</span><span class="op">,</span> name<span class="op">)</span></span>
<span id="cb29-23"><a href="#cb29-23" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;role&quot;</span><span class="op">,</span> role<span class="op">)</span></span>
<span id="cb29-24"><a href="#cb29-24" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;muppet&quot;</span><span class="op">,</span> muppet<span class="op">)</span></span>
<span id="cb29-25"><a href="#cb29-25" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">build</span><span class="op">();</span></span>
<span id="cb29-26"><a href="#cb29-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb29-27"><a href="#cb29-27" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb29-28"><a href="#cb29-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-29"><a href="#cb29-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-30"><a href="#cb29-30" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Movie</span><span class="op">(</span><span class="bu">String</span> title<span class="op">,</span> <span class="bu">List</span><span class="op">&lt;</span>Actor<span class="op">&gt;</span> cast<span class="op">)</span></span>
<span id="cb29-31"><a href="#cb29-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">implements</span> JsonEncodable <span class="op">{</span></span>
<span id="cb29-32"><a href="#cb29-32" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> Movie <span class="fu">fromJson</span><span class="op">(</span>Json json<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-33"><a href="#cb29-33" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Movie</span><span class="op">(</span></span>
<span id="cb29-34"><a href="#cb29-34" aria-hidden="true" tabindex="-1"></a>                JsonDecoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span>json<span class="op">,</span> <span class="st">&quot;title&quot;</span><span class="op">,</span> JsonDecoder<span class="op">::</span>string<span class="op">),</span></span>
<span id="cb29-35"><a href="#cb29-35" aria-hidden="true" tabindex="-1"></a>                JsonDecoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span></span>
<span id="cb29-36"><a href="#cb29-36" aria-hidden="true" tabindex="-1"></a>                        json<span class="op">,</span> </span>
<span id="cb29-37"><a href="#cb29-37" aria-hidden="true" tabindex="-1"></a>                        <span class="st">&quot;cast&quot;</span><span class="op">,</span> </span>
<span id="cb29-38"><a href="#cb29-38" aria-hidden="true" tabindex="-1"></a>                        JsonDecoder<span class="op">.</span><span class="fu">array</span><span class="op">(</span>Actor<span class="op">::</span>fromJson<span class="op">)</span></span>
<span id="cb29-39"><a href="#cb29-39" aria-hidden="true" tabindex="-1"></a>                <span class="op">)</span></span>
<span id="cb29-40"><a href="#cb29-40" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb29-41"><a href="#cb29-41" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb29-42"><a href="#cb29-42" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-43"><a href="#cb29-43" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb29-44"><a href="#cb29-44" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> Json <span class="fu">toJson</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb29-45"><a href="#cb29-45" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> Json<span class="op">.</span><span class="fu">objectBuilder</span><span class="op">()</span></span>
<span id="cb29-46"><a href="#cb29-46" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;title&quot;</span><span class="op">,</span> title<span class="op">)</span></span>
<span id="cb29-47"><a href="#cb29-47" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;cast&quot;</span><span class="op">,</span> cast<span class="op">)</span></span>
<span id="cb29-48"><a href="#cb29-48" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">build</span><span class="op">();</span></span>
<span id="cb29-49"><a href="#cb29-49" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb29-50"><a href="#cb29-50" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb29-51"><a href="#cb29-51" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-52"><a href="#cb29-52" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb29-53"><a href="#cb29-53" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-54"><a href="#cb29-54" aria-hidden="true" tabindex="-1"></a>        var json <span class="op">=</span> Json<span class="op">.</span><span class="fu">readString</span><span class="op">(</span><span class="st">&quot;&quot;&quot;</span></span>
<span id="cb29-55"><a href="#cb29-55" aria-hidden="true" tabindex="-1"></a>                 <span class="op">{</span></span>
<span id="cb29-56"><a href="#cb29-56" aria-hidden="true" tabindex="-1"></a>                     <span class="st">&quot;title&quot;</span><span class="op">:</span> <span class="st">&quot;Treasure Island&quot;</span><span class="op">,</span></span>
<span id="cb29-57"><a href="#cb29-57" aria-hidden="true" tabindex="-1"></a>                     <span class="st">&quot;cast&quot;</span><span class="op">:</span> <span class="op">[</span></span>
<span id="cb29-58"><a href="#cb29-58" aria-hidden="true" tabindex="-1"></a>                         <span class="op">{</span></span>
<span id="cb29-59"><a href="#cb29-59" aria-hidden="true" tabindex="-1"></a>                             <span class="st">&quot;name&quot;</span><span class="op">:</span> <span class="st">&quot;Kermit&quot;</span><span class="op">,</span></span>
<span id="cb29-60"><a href="#cb29-60" aria-hidden="true" tabindex="-1"></a>                             <span class="st">&quot;role&quot;</span><span class="op">:</span> <span class="st">&quot;The Captain&quot;</span><span class="op">,</span></span>
<span id="cb29-61"><a href="#cb29-61" aria-hidden="true" tabindex="-1"></a>                             <span class="st">&quot;muppet&quot;</span><span class="op">:</span> <span class="kw">true</span></span>
<span id="cb29-62"><a href="#cb29-62" aria-hidden="true" tabindex="-1"></a>                         <span class="op">},</span></span>
<span id="cb29-63"><a href="#cb29-63" aria-hidden="true" tabindex="-1"></a>                         <span class="op">{</span></span>
<span id="cb29-64"><a href="#cb29-64" aria-hidden="true" tabindex="-1"></a>                             <span class="st">&quot;name&quot;</span><span class="op">:</span> <span class="st">&quot;Tim Curry&quot;</span><span class="op">,</span></span>
<span id="cb29-65"><a href="#cb29-65" aria-hidden="true" tabindex="-1"></a>                             <span class="st">&quot;role&quot;</span><span class="op">:</span> <span class="st">&quot;Long John Silver&quot;</span><span class="op">,</span></span>
<span id="cb29-66"><a href="#cb29-66" aria-hidden="true" tabindex="-1"></a>                             <span class="st">&quot;muppet&quot;</span><span class="op">:</span> <span class="kw">false</span></span>
<span id="cb29-67"><a href="#cb29-67" aria-hidden="true" tabindex="-1"></a>                         <span class="op">}</span></span>
<span id="cb29-68"><a href="#cb29-68" aria-hidden="true" tabindex="-1"></a>                     <span class="op">]</span></span>
<span id="cb29-69"><a href="#cb29-69" aria-hidden="true" tabindex="-1"></a>                 <span class="op">}</span></span>
<span id="cb29-70"><a href="#cb29-70" aria-hidden="true" tabindex="-1"></a>                 <span class="st">&quot;&quot;&quot;);</span></span>
<span id="cb29-71"><a href="#cb29-71" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-72"><a href="#cb29-72" aria-hidden="true" tabindex="-1"></a>        var movie <span class="op">=</span> Movie<span class="op">.</span><span class="fu">fromJson</span><span class="op">(</span>json<span class="op">);</span></span>
<span id="cb29-73"><a href="#cb29-73" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-74"><a href="#cb29-74" aria-hidden="true" tabindex="-1"></a>        var roundTrippedJson <span class="op">=</span> Json<span class="op">.</span><span class="fu">readString</span><span class="op">(</span></span>
<span id="cb29-75"><a href="#cb29-75" aria-hidden="true" tabindex="-1"></a>                Json<span class="op">.</span><span class="fu">writeString</span><span class="op">(</span>movie<span class="op">.</span><span class="fu">toJson</span><span class="op">())</span></span>
<span id="cb29-76"><a href="#cb29-76" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb29-77"><a href="#cb29-77" aria-hidden="true" tabindex="-1"></a>        var roundTrippedMovie <span class="op">=</span> Movie<span class="op">.</span><span class="fu">fromJson</span><span class="op">(</span>roundTrippedJson<span class="op">);</span></span>
<span id="cb29-78"><a href="#cb29-78" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-79"><a href="#cb29-79" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span></span>
<span id="cb29-80"><a href="#cb29-80" aria-hidden="true" tabindex="-1"></a>                json<span class="op">.</span><span class="fu">equals</span><span class="op">(</span>roundTrippedJson<span class="op">)</span></span>
<span id="cb29-81"><a href="#cb29-81" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb29-82"><a href="#cb29-82" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-83"><a href="#cb29-83" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span></span>
<span id="cb29-84"><a href="#cb29-84" aria-hidden="true" tabindex="-1"></a>                movie<span class="op">.</span><span class="fu">equals</span><span class="op">(</span>roundTrippedMovie<span class="op">)</span></span>
<span id="cb29-85"><a href="#cb29-85" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb29-86"><a href="#cb29-86" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb29-87"><a href="#cb29-87" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="pitches">Pitches</h2>
<p>My hope is that at this point you have a sense of how it might look to use this library for your projects.</p>
<p>The rest of the post will just be some pitches to try to push you into the dark side.</p>
<h3 id="it-is-not-magic">It is not magic</h3>
<p>Some people are perfectly fine with jackson-databind, gson, and other frameworks which use a class as a schema to read in JSON.</p>
<p>Others seem not to be. Kvetching about annotations and frameworks that make use of annotations is a common past-time in the community.</p>
<p>The current options for decoding without databind kinda suck though. To highlight this - I was talking with someone who takes the "magic bad" position. They said that generally they just use gson and manually construct their objects.</p>
<p>I challenged them to interpret this JSON into classes using their usual method.</p>
<div class="sourceCode" id="cb30"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">&quot;title&quot;</span><span class="fu">:</span> <span class="st">&quot;Treasure Island&quot;</span><span class="fu">,</span></span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">&quot;cast&quot;</span><span class="fu">:</span> <span class="ot">[</span></span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a>        <span class="fu">{</span></span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a>            <span class="dt">&quot;name&quot;</span><span class="fu">:</span> <span class="st">&quot;kermit&quot;</span></span>
<span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a>        <span class="fu">}</span><span class="ot">,</span></span>
<span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a>        <span class="fu">{</span></span>
<span id="cb30-8"><a href="#cb30-8" aria-hidden="true" tabindex="-1"></a>            <span class="dt">&quot;name&quot;</span><span class="fu">:</span> <span class="st">&quot;gonzo&quot;</span></span>
<span id="cb30-9"><a href="#cb30-9" aria-hidden="true" tabindex="-1"></a>        <span class="fu">}</span><span class="ot">,</span></span>
<span id="cb30-10"><a href="#cb30-10" aria-hidden="true" tabindex="-1"></a>        <span class="fu">{</span></span>
<span id="cb30-11"><a href="#cb30-11" aria-hidden="true" tabindex="-1"></a>            <span class="dt">&quot;name&quot;</span><span class="fu">:</span> <span class="st">&quot;rizzo&quot;</span></span>
<span id="cb30-12"><a href="#cb30-12" aria-hidden="true" tabindex="-1"></a>        <span class="fu">}</span></span>
<span id="cb30-13"><a href="#cb30-13" aria-hidden="true" tabindex="-1"></a>    <span class="ot">]</span></span>
<span id="cb30-14"><a href="#cb30-14" aria-hidden="true" tabindex="-1"></a><span class="fu">}</span></span></code></pre></div>
<p>And the following is the code they came up with.</p>
<div class="sourceCode" id="cb31"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span><span class="im"> example</span><span class="op">.</span><span class="im">gson</span><span class="op">;</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">google</span><span class="op">.</span><span class="im">gson</span><span class="op">.</span><span class="im">JsonObject</span><span class="op">;</span></span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> record <span class="fu">Muppet</span><span class="op">(</span><span class="bu">String</span> name<span class="op">)</span> <span class="op">{</span></span>
<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> Muppet <span class="fu">createFrom</span><span class="op">(</span>JsonObject muppetObject<span class="op">)</span> <span class="op">{</span></span>
<span id="cb31-8"><a href="#cb31-8" aria-hidden="true" tabindex="-1"></a>        <span class="bu">String</span> name <span class="op">=</span> muppetObject</span>
<span id="cb31-9"><a href="#cb31-9" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">get</span><span class="op">(</span><span class="st">&quot;name&quot;</span><span class="op">)</span></span>
<span id="cb31-10"><a href="#cb31-10" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">getAsString</span><span class="op">();</span></span>
<span id="cb31-11"><a href="#cb31-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Muppet</span><span class="op">(</span>name<span class="op">);</span></span>
<span id="cb31-12"><a href="#cb31-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb31-13"><a href="#cb31-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-14"><a href="#cb31-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb32"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span><span class="im"> example</span><span class="op">.</span><span class="im">gson</span><span class="op">;</span></span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">ArrayList</span><span class="op">;</span></span>
<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">List</span><span class="op">;</span></span>
<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">google</span><span class="op">.</span><span class="im">gson</span><span class="op">.</span><span class="im">JsonArray</span><span class="op">;</span></span>
<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">google</span><span class="op">.</span><span class="im">gson</span><span class="op">.</span><span class="im">JsonObject</span><span class="op">;</span></span>
<span id="cb32-8"><a href="#cb32-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-9"><a href="#cb32-9" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> record <span class="fu">Movie</span><span class="op">(</span><span class="bu">String</span> title<span class="op">,</span> <span class="bu">List</span><span class="op">&lt;</span>Muppet<span class="op">&gt;</span> cast<span class="op">)</span> <span class="op">{</span></span>
<span id="cb32-10"><a href="#cb32-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-11"><a href="#cb32-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> Movie <span class="fu">createFrom</span><span class="op">(</span>JsonObject object<span class="op">)</span> <span class="op">{</span></span>
<span id="cb32-12"><a href="#cb32-12" aria-hidden="true" tabindex="-1"></a>        <span class="bu">String</span> muppetTitle <span class="op">=</span> object</span>
<span id="cb32-13"><a href="#cb32-13" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">get</span><span class="op">(</span><span class="st">&quot;title&quot;</span><span class="op">)</span></span>
<span id="cb32-14"><a href="#cb32-14" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">getAsString</span><span class="op">();</span></span>
<span id="cb32-15"><a href="#cb32-15" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb32-16"><a href="#cb32-16" aria-hidden="true" tabindex="-1"></a>        <span class="bu">List</span><span class="op">&lt;</span>Muppet<span class="op">&gt;</span> cast <span class="op">=</span> <span class="kw">new</span> <span class="bu">ArrayList</span><span class="op">&lt;&gt;();</span></span>
<span id="cb32-17"><a href="#cb32-17" aria-hidden="true" tabindex="-1"></a>        JsonArray castArray <span class="op">=</span> object<span class="op">.</span><span class="fu">getAsJsonArray</span><span class="op">(</span><span class="st">&quot;cast&quot;</span><span class="op">);</span></span>
<span id="cb32-18"><a href="#cb32-18" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> castArray<span class="op">.</span><span class="fu">size</span><span class="op">();</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb32-19"><a href="#cb32-19" aria-hidden="true" tabindex="-1"></a>            JsonObject muppetObject <span class="op">=</span> castArray</span>
<span id="cb32-20"><a href="#cb32-20" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">get</span><span class="op">(</span>i<span class="op">)</span></span>
<span id="cb32-21"><a href="#cb32-21" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">getAsJsonObject</span><span class="op">();</span></span>
<span id="cb32-22"><a href="#cb32-22" aria-hidden="true" tabindex="-1"></a>            cast<span class="op">.</span><span class="fu">add</span><span class="op">(</span>Muppet<span class="op">.</span><span class="fu">createFrom</span><span class="op">(</span>muppetObject<span class="op">));</span></span>
<span id="cb32-23"><a href="#cb32-23" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb32-24"><a href="#cb32-24" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb32-25"><a href="#cb32-25" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Movie</span><span class="op">(</span>muppetTitle<span class="op">,</span> cast<span class="op">);</span></span>
<span id="cb32-26"><a href="#cb32-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb32-27"><a href="#cb32-27" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb33"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span><span class="im"> example</span><span class="op">.</span><span class="im">gson</span><span class="op">;</span></span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">google</span><span class="op">.</span><span class="im">gson</span><span class="op">.</span><span class="im">JsonObject</span><span class="op">;</span></span>
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">google</span><span class="op">.</span><span class="im">gson</span><span class="op">.</span><span class="im">JsonParser</span><span class="op">;</span></span>
<span id="cb33-5"><a href="#cb33-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-6"><a href="#cb33-6" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Example <span class="op">{</span></span>
<span id="cb33-7"><a href="#cb33-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-8"><a href="#cb33-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb33-9"><a href="#cb33-9" aria-hidden="true" tabindex="-1"></a>        <span class="bu">String</span> content <span class="op">=</span> <span class="st">&quot;{</span><span class="sc">\r\n</span><span class="st">&quot;</span></span>
<span id="cb33-10"><a href="#cb33-10" aria-hidden="true" tabindex="-1"></a>                <span class="op">+</span> <span class="st">&quot; </span><span class="sc">\&quot;</span><span class="st">title</span><span class="sc">\&quot;</span><span class="st">: </span><span class="sc">\&quot;</span><span class="st">Treasure Island</span><span class="sc">\&quot;</span><span class="st">,</span><span class="sc">\r\n</span><span class="st">&quot;</span></span>
<span id="cb33-11"><a href="#cb33-11" aria-hidden="true" tabindex="-1"></a>                <span class="op">+</span> <span class="st">&quot; </span><span class="sc">\&quot;</span><span class="st">cast</span><span class="sc">\&quot;</span><span class="st">: [</span><span class="sc">\r\n</span><span class="st">&quot;</span></span>
<span id="cb33-12"><a href="#cb33-12" aria-hidden="true" tabindex="-1"></a>                <span class="op">+</span> <span class="st">&quot;     {</span><span class="sc">\r\n</span><span class="st">&quot;</span></span>
<span id="cb33-13"><a href="#cb33-13" aria-hidden="true" tabindex="-1"></a>                <span class="op">+</span> <span class="st">&quot;         </span><span class="sc">\&quot;</span><span class="st">name</span><span class="sc">\&quot;</span><span class="st">: </span><span class="sc">\&quot;</span><span class="st">kermit</span><span class="sc">\&quot;\r\n</span><span class="st">&quot;</span></span>
<span id="cb33-14"><a href="#cb33-14" aria-hidden="true" tabindex="-1"></a>                <span class="op">+</span> <span class="st">&quot;     },</span><span class="sc">\r\n</span><span class="st">&quot;</span></span>
<span id="cb33-15"><a href="#cb33-15" aria-hidden="true" tabindex="-1"></a>                <span class="op">+</span> <span class="st">&quot;     {</span><span class="sc">\r\n</span><span class="st">&quot;</span></span>
<span id="cb33-16"><a href="#cb33-16" aria-hidden="true" tabindex="-1"></a>                <span class="op">+</span> <span class="st">&quot;         </span><span class="sc">\&quot;</span><span class="st">name</span><span class="sc">\&quot;</span><span class="st">: </span><span class="sc">\&quot;</span><span class="st">gonzo</span><span class="sc">\&quot;\r\n</span><span class="st">&quot;</span></span>
<span id="cb33-17"><a href="#cb33-17" aria-hidden="true" tabindex="-1"></a>                <span class="op">+</span> <span class="st">&quot;     },</span><span class="sc">\r\n</span><span class="st">&quot;</span></span>
<span id="cb33-18"><a href="#cb33-18" aria-hidden="true" tabindex="-1"></a>                <span class="op">+</span> <span class="st">&quot;     {</span><span class="sc">\r\n</span><span class="st">&quot;</span></span>
<span id="cb33-19"><a href="#cb33-19" aria-hidden="true" tabindex="-1"></a>                <span class="op">+</span> <span class="st">&quot;         </span><span class="sc">\&quot;</span><span class="st">name</span><span class="sc">\&quot;</span><span class="st">: </span><span class="sc">\&quot;</span><span class="st">rizzo</span><span class="sc">\&quot;\r\n</span><span class="st">&quot;</span></span>
<span id="cb33-20"><a href="#cb33-20" aria-hidden="true" tabindex="-1"></a>                <span class="op">+</span> <span class="st">&quot;     }</span><span class="sc">\r\n</span><span class="st">&quot;</span></span>
<span id="cb33-21"><a href="#cb33-21" aria-hidden="true" tabindex="-1"></a>                <span class="op">+</span> <span class="st">&quot; ]</span><span class="sc">\r\n</span><span class="st">&quot;</span></span>
<span id="cb33-22"><a href="#cb33-22" aria-hidden="true" tabindex="-1"></a>                <span class="op">+</span> <span class="st">&quot;}&quot;</span><span class="op">;</span></span>
<span id="cb33-23"><a href="#cb33-23" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb33-24"><a href="#cb33-24" aria-hidden="true" tabindex="-1"></a>        JsonObject json <span class="op">=</span> JsonParser</span>
<span id="cb33-25"><a href="#cb33-25" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">parseString</span><span class="op">(</span>content<span class="op">)</span></span>
<span id="cb33-26"><a href="#cb33-26" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span><span class="fu">getAsJsonObject</span><span class="op">();</span></span>
<span id="cb33-27"><a href="#cb33-27" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb33-28"><a href="#cb33-28" aria-hidden="true" tabindex="-1"></a>        Movie movie <span class="op">=</span> Movie<span class="op">.</span><span class="fu">createFrom</span><span class="op">(</span>json<span class="op">);</span></span>
<span id="cb33-29"><a href="#cb33-29" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb33-30"><a href="#cb33-30" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>movie<span class="op">);</span></span>
<span id="cb33-31"><a href="#cb33-31" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb33-32"><a href="#cb33-32" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>I think this code is pretty representative of the variety one would produce when working against this sort of API.</p>
<p>The follow-up challenge I gave him was to run this code against some malformed input.</p>
<div class="sourceCode" id="cb34"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span></span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;title&quot;</span><span class="fu">:</span> <span class="st">&quot;Treasure Island&quot;</span><span class="fu">,</span></span>
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;cast&quot;</span><span class="fu">:</span> <span class="ot">[</span></span>
<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a>    <span class="fu">{</span></span>
<span id="cb34-5"><a href="#cb34-5" aria-hidden="true" tabindex="-1"></a>    <span class="fu">}</span><span class="ot">,</span></span>
<span id="cb34-6"><a href="#cb34-6" aria-hidden="true" tabindex="-1"></a>    <span class="fu">{</span></span>
<span id="cb34-7"><a href="#cb34-7" aria-hidden="true" tabindex="-1"></a>      <span class="dt">&quot;name&quot;</span><span class="fu">:</span> <span class="st">&quot;gonzo&quot;</span></span>
<span id="cb34-8"><a href="#cb34-8" aria-hidden="true" tabindex="-1"></a>    <span class="fu">}</span><span class="ot">,</span></span>
<span id="cb34-9"><a href="#cb34-9" aria-hidden="true" tabindex="-1"></a>    <span class="fu">{</span></span>
<span id="cb34-10"><a href="#cb34-10" aria-hidden="true" tabindex="-1"></a>      <span class="dt">&quot;name&quot;</span><span class="fu">:</span> <span class="st">&quot;rizzo&quot;</span></span>
<span id="cb34-11"><a href="#cb34-11" aria-hidden="true" tabindex="-1"></a>    <span class="fu">}</span></span>
<span id="cb34-12"><a href="#cb34-12" aria-hidden="true" tabindex="-1"></a>  <span class="ot">]</span></span>
<span id="cb34-13"><a href="#cb34-13" aria-hidden="true" tabindex="-1"></a><span class="fu">}</span></span></code></pre></div>
<p>The error message that his code produced was the following.</p>
<pre><code>Cannot invoke &quot;com.google.gson.JsonElement.getAsString()&quot; because the return value of &quot;com.google.gson.JsonObject.get(String)&quot; is null</code></pre>
<p>Which, while better than it would have been in years past (thanks <a href="https://openjdk.org/jeps/358">JEP 358</a>), still isn't amazing.</p>
<p>Compare that to the error message someone will get with what is the most natural way to express this with my library.</p>
<div class="sourceCode" id="cb36"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Muppet</span><span class="op">(</span><span class="bu">String</span> name<span class="op">)</span> <span class="op">{</span></span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> Muppet <span class="fu">fromJson</span><span class="op">(</span>Json json<span class="op">)</span> <span class="op">{</span></span>
<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Muppet</span><span class="op">(</span></span>
<span id="cb36-4"><a href="#cb36-4" aria-hidden="true" tabindex="-1"></a>                JsonDecoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span>json<span class="op">,</span> <span class="st">&quot;name&quot;</span><span class="op">,</span> JsonDecoder<span class="op">::</span>string<span class="op">)</span></span>
<span id="cb36-5"><a href="#cb36-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb36-6"><a href="#cb36-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb36-7"><a href="#cb36-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb36-8"><a href="#cb36-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-9"><a href="#cb36-9" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Movie</span><span class="op">(</span><span class="bu">String</span> title<span class="op">,</span> <span class="bu">List</span><span class="op">&lt;</span>Muppet<span class="op">&gt;</span> cast<span class="op">)</span> <span class="op">{</span></span>
<span id="cb36-10"><a href="#cb36-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> Movie <span class="fu">fromJson</span><span class="op">(</span>Json json<span class="op">)</span> <span class="op">{</span></span>
<span id="cb36-11"><a href="#cb36-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Movie</span><span class="op">(</span></span>
<span id="cb36-12"><a href="#cb36-12" aria-hidden="true" tabindex="-1"></a>                JsonDecoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span></span>
<span id="cb36-13"><a href="#cb36-13" aria-hidden="true" tabindex="-1"></a>                        json<span class="op">,</span> </span>
<span id="cb36-14"><a href="#cb36-14" aria-hidden="true" tabindex="-1"></a>                        <span class="st">&quot;title&quot;</span><span class="op">,</span> </span>
<span id="cb36-15"><a href="#cb36-15" aria-hidden="true" tabindex="-1"></a>                        JsonDecoder<span class="op">::</span>string</span>
<span id="cb36-16"><a href="#cb36-16" aria-hidden="true" tabindex="-1"></a>                <span class="op">),</span></span>
<span id="cb36-17"><a href="#cb36-17" aria-hidden="true" tabindex="-1"></a>                JsonDecoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span></span>
<span id="cb36-18"><a href="#cb36-18" aria-hidden="true" tabindex="-1"></a>                        json<span class="op">,</span> </span>
<span id="cb36-19"><a href="#cb36-19" aria-hidden="true" tabindex="-1"></a>                        <span class="st">&quot;cast&quot;</span><span class="op">,</span> </span>
<span id="cb36-20"><a href="#cb36-20" aria-hidden="true" tabindex="-1"></a>                        JsonDecoder<span class="op">.</span><span class="fu">array</span><span class="op">(</span>Muppet<span class="op">::</span>fromJson<span class="op">)</span></span>
<span id="cb36-21"><a href="#cb36-21" aria-hidden="true" tabindex="-1"></a>                <span class="op">)</span></span>
<span id="cb36-22"><a href="#cb36-22" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb36-23"><a href="#cb36-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb36-24"><a href="#cb36-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<pre><code>Problem with the value at json.cast[0].name

    {}
    
no value for field</code></pre>
<p>The code they produced is also pretty heavily "imperative." To make their list of Muppets they have a plain for loop and transform every element individually.</p>
<div class="sourceCode" id="cb38"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a><span class="bu">List</span><span class="op">&lt;</span>Muppet<span class="op">&gt;</span> cast <span class="op">=</span> <span class="kw">new</span> <span class="bu">ArrayList</span><span class="op">&lt;&gt;();</span></span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a>JsonArray castArray <span class="op">=</span> object<span class="op">.</span><span class="fu">getAsJsonArray</span><span class="op">(</span><span class="st">&quot;cast&quot;</span><span class="op">);</span></span>
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> castArray<span class="op">.</span><span class="fu">size</span><span class="op">();</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb38-4"><a href="#cb38-4" aria-hidden="true" tabindex="-1"></a>    JsonObject muppetObject <span class="op">=</span> castArray</span>
<span id="cb38-5"><a href="#cb38-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">get</span><span class="op">(</span>i<span class="op">)</span></span>
<span id="cb38-6"><a href="#cb38-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">getAsJsonObject</span><span class="op">();</span></span>
<span id="cb38-7"><a href="#cb38-7" aria-hidden="true" tabindex="-1"></a>    cast<span class="op">.</span><span class="fu">add</span><span class="op">(</span>Muppet<span class="op">.</span><span class="fu">createFrom</span><span class="op">(</span>muppetObject<span class="op">));</span></span>
<span id="cb38-8"><a href="#cb38-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This is not intrinsically bad by any means, for loops are not evil, but all code lives somewhere on a spectrum from "declarative" to "imperative". Describing what should be done versus how it should be done.</p>
<p>If you compare their code to what one would write when relying on gson's reflection mechanisms the difference is stark.</p>
<div class="sourceCode" id="cb39"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Muppet</span><span class="op">(</span><span class="bu">String</span> name<span class="op">)</span> <span class="op">{}</span></span>
<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb39-3"><a href="#cb39-3" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Movie</span><span class="op">(</span><span class="bu">String</span> title<span class="op">,</span> <span class="bu">List</span><span class="op">&lt;</span>Muppet<span class="op">&gt;</span> cast<span class="op">)</span> <span class="op">{}</span></span></code></pre></div>
<p>Yes, you need to know the rules for how JSON is automatically mapped to these structures and what different annotations mean if they are present. But this is unquestionably a "declarative schema." If you know the rules it is easier to read.</p>
<p>The code you would write with my library occupies a middle ground.</p>
<div class="sourceCode" id="cb40"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Muppet</span><span class="op">(</span><span class="bu">String</span> name<span class="op">)</span> <span class="op">{</span></span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> Muppet <span class="fu">fromJson</span><span class="op">(</span>Json json<span class="op">)</span> <span class="op">{</span></span>
<span id="cb40-3"><a href="#cb40-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Muppet</span><span class="op">(</span></span>
<span id="cb40-4"><a href="#cb40-4" aria-hidden="true" tabindex="-1"></a>                JsonDecoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span>json<span class="op">,</span> <span class="st">&quot;name&quot;</span><span class="op">,</span> JsonDecoder<span class="op">::</span>string<span class="op">)</span></span>
<span id="cb40-5"><a href="#cb40-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb40-6"><a href="#cb40-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb40-7"><a href="#cb40-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb40-8"><a href="#cb40-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-9"><a href="#cb40-9" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Movie</span><span class="op">(</span><span class="bu">String</span> title<span class="op">,</span> <span class="bu">List</span><span class="op">&lt;</span>Muppet<span class="op">&gt;</span> cast<span class="op">)</span> <span class="op">{</span></span>
<span id="cb40-10"><a href="#cb40-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> Movie <span class="fu">fromJson</span><span class="op">(</span>Json json<span class="op">)</span> <span class="op">{</span></span>
<span id="cb40-11"><a href="#cb40-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Movie</span><span class="op">(</span></span>
<span id="cb40-12"><a href="#cb40-12" aria-hidden="true" tabindex="-1"></a>                JsonDecoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span></span>
<span id="cb40-13"><a href="#cb40-13" aria-hidden="true" tabindex="-1"></a>                        json<span class="op">,</span> </span>
<span id="cb40-14"><a href="#cb40-14" aria-hidden="true" tabindex="-1"></a>                        <span class="st">&quot;title&quot;</span><span class="op">,</span> </span>
<span id="cb40-15"><a href="#cb40-15" aria-hidden="true" tabindex="-1"></a>                        JsonDecoder<span class="op">::</span>string</span>
<span id="cb40-16"><a href="#cb40-16" aria-hidden="true" tabindex="-1"></a>                <span class="op">),</span></span>
<span id="cb40-17"><a href="#cb40-17" aria-hidden="true" tabindex="-1"></a>                JsonDecoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span></span>
<span id="cb40-18"><a href="#cb40-18" aria-hidden="true" tabindex="-1"></a>                        json<span class="op">,</span> </span>
<span id="cb40-19"><a href="#cb40-19" aria-hidden="true" tabindex="-1"></a>                        <span class="st">&quot;cast&quot;</span><span class="op">,</span> </span>
<span id="cb40-20"><a href="#cb40-20" aria-hidden="true" tabindex="-1"></a>                        JsonDecoder<span class="op">.</span><span class="fu">array</span><span class="op">(</span>Muppet<span class="op">::</span>fromJson<span class="op">)</span></span>
<span id="cb40-21"><a href="#cb40-21" aria-hidden="true" tabindex="-1"></a>                <span class="op">)</span></span>
<span id="cb40-22"><a href="#cb40-22" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb40-23"><a href="#cb40-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb40-24"><a href="#cb40-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>While there is more of it than when you rely on heuristics, it is still "reasonably declarative."</p>
<div class="sourceCode" id="cb41"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> <span class="kw">new</span> <span class="fu">Movie</span><span class="op">(</span></span>
<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a>        JsonDecoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span></span>
<span id="cb41-3"><a href="#cb41-3" aria-hidden="true" tabindex="-1"></a>                json<span class="op">,</span> </span>
<span id="cb41-4"><a href="#cb41-4" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;title&quot;</span><span class="op">,</span> </span>
<span id="cb41-5"><a href="#cb41-5" aria-hidden="true" tabindex="-1"></a>                JsonDecoder<span class="op">::</span>string</span>
<span id="cb41-6"><a href="#cb41-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">),</span></span>
<span id="cb41-7"><a href="#cb41-7" aria-hidden="true" tabindex="-1"></a>        JsonDecoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span></span>
<span id="cb41-8"><a href="#cb41-8" aria-hidden="true" tabindex="-1"></a>                json<span class="op">,</span> </span>
<span id="cb41-9"><a href="#cb41-9" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;cast&quot;</span><span class="op">,</span> </span>
<span id="cb41-10"><a href="#cb41-10" aria-hidden="true" tabindex="-1"></a>                JsonDecoder<span class="op">.</span><span class="fu">array</span><span class="op">(</span>Muppet<span class="op">::</span>fromJson<span class="op">)</span></span>
<span id="cb41-11"><a href="#cb41-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span></span>
<span id="cb41-12"><a href="#cb41-12" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span></code></pre></div>
<p>The logic for it is both extensible (there is nothing privileged about <code>JsonDecoder</code>; you can write your own helper methods) and defined in code that you can click-to-definition to.</p>
<p>If a field can be null you would see <code>nullableField</code>. If a field can be missing, you would see <code>optionalField</code>. If it could be both, you would see <code>optionalNullableField</code>.</p>
<h3 id="this-is-simple-to-teach">This is simple to teach</h3>
<p>I don't know about you, but I am absolutely sick of explaining Jackson to students who are still struggling with classes in general.</p>
<p>If a student has JSON like this</p>
<div class="sourceCode" id="cb42"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb42-1"><a href="#cb42-1" aria-hidden="true" tabindex="-1"></a><span class="op">[</span> <span class="op">{</span><span class="st">&quot;name&quot;</span><span class="op">:</span> <span class="st">&quot;kailee&quot;</span><span class="op">},</span> <span class="op">{</span><span class="st">&quot;name&quot;</span><span class="op">:</span> <span class="st">&quot;fran&quot;</span><span class="op">}</span> <span class="op">]</span></span></code></pre></div>
<p>Then to read it in as a <code>List&lt;Person&gt;</code> they need to either</p>
<ul>
<li>target a Person[]</li>
<li>target a class which extends ArrayList<Person></li>
<li>provide a TypeToken&lt;List<Person>&gt;</li>
</ul>
<p>Plus maybe some other options I might be unaware of.</p>
<p>To actually understand what they are doing for just that, they need to have a sense for some combination of</p>
<ul>
<li>Inheritance</li>
<li>Generic Erasure</li>
<li>Reflection</li>
</ul>
<p>And that is really hard to impart at their stage, so often us online helpers just say "ah, make a class that looks like this." and send them on their way.</p>
<p>On the flip-side, when beginners get frustrated with a databind approach and fall back to something like <a href="https://github.com/stleary/JSON-java">org.json</a> they seem to produce some absolute monstrosities before they come back with another question.</p>
<p>It's not their fault, they learned loops at most a semester ago, but it does present some practical problems.</p>
<p>The tension is between giving an option that there is enough time to teach the mechanics of and teaching an approach that will be ergonomic enough for them to complete their assignments.</p>
<p>I've been testing early drafts of this library against real students and, while there are too many confounding variables to say I've done any real science, I've found it to be far easier.</p>
<p>When a student needs a quick monkey-see-monkey-do, the <code>JsonDecoder.field</code> pattern seems to work just fine. When a student wants, needs, or has time for a full explanation there is a far shorter distance between where they are and where I need to get them.</p>
<p>I just need to make sure they understand interfaces and lambdas then they are ready for some version of the tutorial I gave in the first section.</p>
<p>Students in college aren't the only people who need to be taught how to work with JSON in Java either. If you work for a company that hires juniors or folks who come from different language backgrounds, then there has to be an education step.</p>
<p>It might be worth the boilerplate of writing out <code>fromJson</code> and <code>toJson</code> to have a codebase where onboarding doesn't need to touch the "advanced" side of Java to send JSON over the wire.</p>
<h3 id="it-could-help-java-get-an-official-json-library">It could help Java get an official JSON library</h3>
<p>There has been a JEP open for years which <a href="https://openjdk.org/jeps/198">proposes adding JSON to the standard library</a></p>
<p>If you use a build tool like maven for all of your programs, it might not seem important. You can pull in Jackson, gson, org.json, this, or any library with one declaration.</p>
<p>There are a few things which make me care about it though</p>
<ol type="1">
<li>Right now, the only data format built in the Java is XML. That's not exactly the king of language neutral formats it was in the 90s.</li>
<li>Java now supports <a href="https://openjdk.org/jeps/330">single file programs</a> and will eventually support <a href="https://openjdk.org/jeps/8302326">"terse" main methods</a>. As the applicability for scripting goes up, the lack of the ability to use JSON hurts more since that is generally a "no-dependency" situation.</li>
<li>Whatever is in the standard library has the power to affect defaults. Databind as the default for the ecosystem feels like it has too much momentum to change otherwise.</li>
<li>When <a href="https://www.graalvm.org/2022/openjdk-announcement/">integrating Graal</a> there are going to be components, like the <code>reflection-config.json</code> file it uses for <a href="https://www.graalvm.org/22.0/reference-manual/native-image/">native image</a>, that will read and write JSON. I fear that will be too tempting a target for <code>--add-opens</code>.</li>
</ol>
<p>Regardless of if you agree that support should be in the standard library, I think the previous section illustrates some of the problems that could come if one of the existing APIs were adopted.</p>
<div class="sourceCode" id="cb43"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb43-1"><a href="#cb43-1" aria-hidden="true" tabindex="-1"></a><span class="bu">List</span><span class="op">&lt;</span>Muppet<span class="op">&gt;</span> cast <span class="op">=</span> <span class="kw">new</span> <span class="bu">ArrayList</span><span class="op">&lt;&gt;();</span></span>
<span id="cb43-2"><a href="#cb43-2" aria-hidden="true" tabindex="-1"></a>JsonArray castArray <span class="op">=</span> object<span class="op">.</span><span class="fu">getAsJsonArray</span><span class="op">(</span><span class="st">&quot;cast&quot;</span><span class="op">);</span></span>
<span id="cb43-3"><a href="#cb43-3" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> castArray<span class="op">.</span><span class="fu">size</span><span class="op">();</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb43-4"><a href="#cb43-4" aria-hidden="true" tabindex="-1"></a>    JsonObject muppetObject <span class="op">=</span> castArray</span>
<span id="cb43-5"><a href="#cb43-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">get</span><span class="op">(</span>i<span class="op">)</span></span>
<span id="cb43-6"><a href="#cb43-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">getAsJsonObject</span><span class="op">();</span></span>
<span id="cb43-7"><a href="#cb43-7" aria-hidden="true" tabindex="-1"></a>    cast<span class="op">.</span><span class="fu">add</span><span class="op">(</span>Muppet<span class="op">.</span><span class="fu">createFrom</span><span class="op">(</span>muppetObject<span class="op">));</span></span>
<span id="cb43-8"><a href="#cb43-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Regardless of applicability, availability could end up making this the default. That is unideal.</p>
<p>An option to avoid this is for the standard library to add direct support for databind. Not only was that ruled out by the existing JEP, it would probably just be a bad idea. Mapping the JSON data model to the wide universe of Java objects has solutions that occupy a very large design space.</p>
<p>Considering the long term commitments the JDK makes whenever it adds a new feature as well as the mental, physical, and emotional damage dealt by its existing <code>Serializable</code> mechanism - I don't see that happening.</p>
<p>If the JDK gave up and just provided a low-level streaming parser akin to <a href="https://github.com/FasterXML/jackson-core"><code>jackson-core</code></a>, then it wouldn't affect the defaults in the ecosystem that much, but it would raise the question of "why not just use <a href="https://github.com/FasterXML/jackson-core"><code>jackson-core</code></a>." In addition, users would still have to add a library to accomplish most tasks. There wouldn't be much of a benefit.</p>
<p>So that's where this library comes in. It's nowhere near seaworthy for that ocean, but the <code>JsonDecoder</code> approach is relatively novel in the JVM ecosystem. The mechanisms needed to make it "work" have only been around since Java 8 and, as far as I know, haven't been tested on any large scale.</p>
<p>The more folks try it, or write libraries that do the concept "but better", or socialize it, etc. the more confidence there can be in whether a decoder based API would be applicable to the needs of the JDK.</p>
<p>You can see my recent conversation on the mailing list about this <a href="https://mail.openjdk.org/pipermail/core-libs-dev/2022-December/097949.html">here</a>.</p>
<h3 id="you-can-play-with-new-features">You can play with new features</h3>
<p>Maybe I haven't convinced you to give it a try for your work or personal projects. That's fine.</p>
<p>Still, it is a small codebase. It makes (I think) good use of the features added to Java in the last decade. If you aren't caught up it might be a good reference point to do so.</p>
<p>If you want to play with upcoming features like <a href="https://openjdk.org/jeps/8277163">value classes</a> or <a href="https://openjdk.org/jeps/430">string templates</a> it could be a nice playground to see how that would affect performance, design, or just how the code feels.</p>
<p>In particular, JSON is mentioned as a use-case in the <a href="https://openjdk.org/jeps/430">JEPs</a> and <a href="https://www.infoq.com/articles/data-oriented-programming-java/">explanations for new features</a> often. Could be nice to have a JSON api to point to that actually works in the way being described.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Development Perils: How to not create a mobile application</title><link>https://mccue.dev/pages/12-28-22-development-perils-how-to-not-create-a-mobile-application</link><description></description><pubDate>Wed, 28 Dec 0022 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Development Perils: How to not create a mobile application</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Development Perils: How to not create a mobile application</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Matthias Ngeo</b></div>

<p>Ever since Forus Labs' first mobile application, <a href="https://timebloc.foruslabs.com/">TimeBloc</a>, was acquired in September 2020, I've mused about writing a short postmortem on its less-than-stellar development. Perhaps as a conclusion to the first chapter in our software engineering careers. I hesitated each time, unsure of how to concisely fit everything into an article. It's almost 2023. Enough time has passed that memories of that period are becoming hazy. I can't hesitate any longer.</p>
<figure>
  <img src="/pages/12-28-22-timebloc-development.jpeg" alt=""/>
  <figcaption>Rare photograph of TimeBloc's development circa 2019</figcaption>
</figure>

<p>Those seeking groundbreaking insights into software engineering should stop reading. This article just describes the aftermath of ignoring practices beaten to death by others.</p>
<p>So gather around the fireplace, as I tell a tale of poor software engineering decisions; of how to <em>not</em> create a mobile application.</p>
<h2 id="choose-wisely">Choose Wisely</h2>
<p>Our tale begins in early 2019. Three lads, fresh out of polytechnic (high-school equivalent), had an overabundance of time before embarking on their <a href="https://en.wikipedia.org/wiki/National_service_in_Singapore">compulsory service</a>. They assumed creating a mobile application to be entertaining and straightforward affair. However, none of them had any prior professional experience creating mobile applications. You can probably sense where this is heading.</p>
<p>During meetings at their local Starbucks, they pitched wild and fantastical features to include in their time-blocking application. One of those features was real-time synchronization of all the user's data, i.e. time-blocks and settings, across their devices. Debates on whether even <em>that</em> was too fantastical continued perpetually until a compromise was sought, deferring the feature to a subsequent release. Unknowingly, the three lads had steered the project away from certain doom.</p>
<p>Deferring the feature was one of the few mistakes <em>avoided</em>. It was only discovered to be fraught with difficulty after implementing a similar feature in a subsequent application.</p>
<figure>
  <img src="/pages/12-28-22-multileader-replication.png" alt=""/>
</figure>

<p>In essence, it was a distributed computing problem. Users could concurrently modify and sync data across several of their devices. To further complicate matters, the application had to be offline-first. That is to say, the application must work even when unconnected to the internet. Modifications had to be reconciled and propagated as they arrived piecemeal. Think <em>"Multi-Leader Replication on Steroids"</em>.</p>
<p>Had the three lads stubbornly insisted on real-time synchronization of data, TimeBloc would remain vaporware until today. A project's features is quite literally make-or-break. Moral of the story is, <em>choose wisely what to implement, err on the side of caution and do not implement something if in doubt</em>, <a href="https://en.wikipedia.org/wiki/KISS_principle">KISS</a>. Likewise, don't implement offline-first support and data synchronization together. It's difficult.</p>
<h2 id="ecological-survey">Ecological Survey</h2>
<p>A few weeks passed in the blink of an eye. The three lads had finished bike-shedding the application's initial features. Said features remained tame, devoid of those too deemed outlandish. Before development commenced, one question still remained. Which language and framework do they use?</p>
<figure>
  <img src="/pages/12-28-22-seaport-at-sunset.jpeg" alt=""/>
  <figcaption>"Sea port at sunset" - Claude Lorrain, 1639</figcaption>
</figure>

<p>The three lads found themselves at a port seeking passage across a perilous, sprawling ocean. Once aboard, it was nigh impossible to switch ships mid-voyage. Moored close to shore were two colossal ships, native Android and iOS development, surrounded by flocks of passengers awaiting embarkment. Both ships were remarkably popular, their seaworthiness trialed-and-tested by time. Moored further down the pier was React Native. Despite having been built later, it had proven to be seaworthy and attracted a respectable crowd. Lastly, there was Flutter, a brand-new ship yet to sail its maiden voyage. It incorporated the latest advancements in shipbuilding and was surrounded by crowds on the dock. Nevertheless, few in those crowds were actual passengers.</p>
<p>Lacking the manpower and funding to develop two separate applications, native Android and iOS development were out of the picture. Both had a single, different destination. However, our funds afforded us passage to only one. Yet, we sought to visit both destinations. Thus, the only contenders were cross-platform frameworks like Flutter and React Native.</p>
<p>After brief experimentation and poring over documentation, Flutter was chosen. Unbeknown to us was the importance of conducting a thorough ecological survey. That is to say, smitten by the ship's advanced exterior, we forgot to check if the ship's interior was even furnished. Flutter in 2019 isn't Flutter in 2022. It was still in its infancy. Likewise, the community and open-source ecosystem surrounding the framework was still budding. It was only discovered partway through development that there was no support for <a href="https://airbnb.io/lottie/#/">Lottie</a> animations.</p>
<figure>
  <img src="/pages/12-28-22-lottie-animation.gif" alt=""/>
  <figcaption>Sample Lottie animation</figcaption>
</figure>

<p>Although <a href="https://rive.app/">Rive</a> was supported, good luck convincing any freelance designer to create an animation in that format. Stuck between a rock and a hard place, the difficult decision was eventually made to scrap all animations.</p>
<p>Some other memorable issues included the notification scheduling library not accounting for Daylight saving time, and the SQLite Flutter library not supporting desktop environments. The latter meant unit tests depending on SQLite couldn't be ran outside an Android/iOS emulator. It greatly influenced the decision to skip unit tests covered in the next section.</p>
<p>Because of its recency, Flutter's community had yet to take root. This manifested as less publicly available information owning to the lack of grey-haired Gandalf-types that thrived on other platforms. Consequentially, that led to greater difficulty with debugging and troubleshooting problems.</p>
<p>One particularly nasty incident occurred after integrating background notification scheduling. In production, reports that the application crashed during start-up began coming in. Further examination revealed that it only affected iPhone 8 devices running a certain iOS version. To complicate matters, the issue could not be replicated on an emulator nor did we own an iPhone 8 running that iOS version. An entire weekend was spent frantically debugging the issue, scouring the internet for any hints to no avail. Desperate, the decision was made to remove background notification scheduling altogether in an emergency patch.</p>
<p>Developing any non-trivial piece of software will inevitably require features offered beyond the language or framework. It is often the surrounding community that provides those missing pieces. Reusing the ship analogy, embarking on a ship guarantees passage but not comfort. The moral of the story is, <em>always conduct an ecological survey on the surrounding open-source ecosystem and community when deciding on a language/framework</em>.</p>
<h2 id="test-now">Test Now</h2>
<p>Yet in another blink of an eye, a few months have passed. Our three lads found themselves wading knee-deep in development work. Things had progressed slower than anticipated while the looming deadline drew close. The metaphorical ship's pace had to be tightened. To lighten the ship, the three lads tossed the lifeboats overboard. They reasoned that the ship wasn't on fire, and the lifeboats could be retrieved if it did, or at the end of the voyage. Long story short, they didn't. The lifeboats remain lost at seas till today.</p>
<p>Skipping unit testing was controversial. Although we acknowledged it to be potentially disastrous, the motivations seemed rationale. Unit tests benefited maintenance in the long term. However, there wasn't going to be a long term if the application missed the initial deadline. Tests could always be added once things have stabilized. In the interim, manual testing should suffice. <em>It couldn't be that bad</em>.</p>
<p>In short, test later gradually became test never. Things <em>could</em> be that bad. Manual testing was time-consuming and unreliable in a constant development flux. That meant manual tests gradually subsided too, while developer confidence plummeted. Eventually, manual testing was only conducted when gluing the UI and business logic together.</p>
<p>The application was built using a pseudo-BLoC architecture composed of several layers. Each developer tackled a single layer in isolation. Contrary to the adage of "<em>integrating often and early</em>", integration only commenced once all layers were individually completed. It was neither often nor early.</p>
<p>Skipping tests and delaying integration was a potent combination. It halted progress and development manifested into the nine circles of hell. It was only discovered during integration that each layer behaved contrary to the other developers' expectations. Similar to the Tower of Babel, further examination revealed contrasting interpretations of each layer's supposed behaviour. To remedy the issue, several bootleg modifications were applied over the span of a day, further damaging the application's structure.</p>
<figure>
  <img src="/pages/12-28-22-debugging-timebloc.gif" alt=""/>
  <figcaption>Rare photo of developer debugging TimeBloc, circa 2019</figcaption>
</figure>

<p>To worsen matters, every imaginable bug surfaced in swarms during manual testing. The application would spontaneously crash and data would become corrupted seemingly at random. Since each individual layer wasn't tested, identifying and isolating the root causes became miniature D&amp;D campaigns. A bug could be caused by the UI, persistence layer, and everything in between. Speaking from personal experience, nothing is as soul-draining as reaching work at 10am and debugging bugs until 4am in the morning.</p>
<p>In the end, although the application barely met the looming deadline, the decision to forego unit testing turned the application into a "<a href="https://www.usenix.org/sites/default/files/conference/protected-files/srecon17americas_slides_reese.pdf">Haunted Graveyard</a>" during its lifetime. Future development stalled. Features couldn't be added and existing bugs couldn't be fully stamped-out. Because of that, rewriting the application was under consideration shortly before the application was acquired.</p>
<p>We failed to acknowledge the immediate maintenance benefits of unit tests. The time spent performing manual testing surpassed the predicted time writing equivalent unit tests by a few folds. Notwithstanding the time spent debugging nor the toll on developers' morale. Similarly, integrating changes late increased the cost of debugging and modification substantially. This combination forced us to cut features and postpone our plans to implement monetization in the initial release. Shedding tests to quicken velocity is almost always counterproductive. <em>Test now before it becomes test never</em>. That goes both for writing unit tests and integrating early. See <a href="https://abseil.io/resources/swe-book/html/ch11.html">Chapter 11 of Software Engineering at Google</a> for a more in-depth treatise of the subject.</p>
<h2 id="perils">Perils</h2>
<p>Following the previous sections, leftover material still remains. None of which substantial enough to dedicate an entire section to. Listed below in no particular order, are perils encountered during development.</p>
<ul>
<li>Bundled SQLite versions may be ancient. Ensure that all SQLite features used are supported on all target platforms.</li>
<li>Foreign keys aren't enabled by default in SQLite. Always enable foreign keys via <code>PRAGMA_foreign_key = ON</code>.</li>
<li>Offline-first &amp; data synchronization aren't a simple combination. Be prepared for distributed computing problems.</li>
<li>It is trivial to mangle time zones. Be careful when using Dart's lackluster DateTime class. See <a href="https://www.zainrizvi.io/blog/falsehoods-programmers-believe-about-time-zones/">Falsehoods programmers believe about time zones</a>.</li>
<li>Don't publish new versions before the weekends/holidays. You might wind up spending that time debugging issues in production.</li>
<li>Document everything. Trying to understand undocumented spaghetti code you wrote 1 year ago is difficult.</li>
</ul>
<h2 id="final-thoughts">Final Thoughts</h2>
<p>Our first foray into the world of professional software engineering wasn't glamorous. Nevertheless, it still represented a significant step forward. Although plenty of lessons were learnt through blood, toil, tears and sweat, I'm glad to be able to sit here and laugh at our own foolish mistakes in hindsight. Likewise, I hope you had a chuckle at the sheer madness even if you didn't take away anything else.</p>
<h2 id="tldr">TL;DR</h2>
<ul>
<li><em>Choose wisely what to implement, err on the side of caution and do not implement something if in doubt.</em></li>
<li><em>Always conduct an ecological survey on the surrounding open source space &amp; community when deciding on a language/framework.</em></li>
<li><em>Test now before it becomes test never.</em></li>
</ul>
<hr />
<p>Article was originally published on <a href="https://matthiasngeo.medium.com/development-perils-how-to-not-create-a-mobile-application-bda101009438">Medium</a>.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How to Structure a Clojure Web App 101</title><link>https://mccue.dev/pages/12-7-22-clojure-web-primer</link><description></description><pubDate>Wed, 07 Dec 0022 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How to Structure a Clojure Web App 101</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How to Structure a Clojure Web App 101</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
<meta property="og:image" content="https://mccue.dev/pages/12-7-22-bobs.png" />
<meta name="twitter:image" content="https://mccue.dev/pages/12-7-22-bobs.png">

<p>At work, we use <a href="https://github.com/weavejester/integrant">integrant</a> to manage stateful components in our Clojure apps.</p>
<p>It has been fine, but it's a constant struggle to explain it.</p>
<p>From a purely mechanical perspective there is a lot to teach. It uses multimethods to register lifecycle hooks, idiomatic use demands namespaced keywords, and in testing we've needed to incorporate <a href="https://github.com/RickMoynihan/redef-methods">special libraries</a>.</p>
<p>None of that is fundamentally a problem though. All the libraries which do this sort of thing use <em>some</em> weirder part of Clojure's arsenal. For <a href="https://github.com/stuartsierra/component">component</a> it is records and protocols. For <a href="https://github.com/juxt/clip">clip</a> it is namespaced symbols and dynamic lookup. For <a href="https://github.com/donut-party/system">donut</a> it's a secret, more complex third thing.</p>
<p>What has been a challenge is explaining what exactly it is that these libraries <em>do</em>. Doing that - really doing that - requires a mountain of shared context that folks simply do not have.</p>
<p><a href="https://www.youtube.com/watch?v=m4OvQIGDg4I"><img src="/pages/12-7-22-bobs.png" alt="What would you say you... do here?"/></a></p>
<p>This article is an attempt to convey some of that shared context. Apologies if it gets a bit ranty.</p>
<h2 id="ring">Ring</h2>
<p>This is an HTTP Request.</p>
<pre><code>GET /echo HTTP/1.1
Host: mccue.dev
Accept: text/html
</code></pre>
<p>This is an HTTP Response.</p>
<pre class="http"><code>HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 19

{&quot;success&quot;:&quot;true&quot;}</code></pre>
<p>Basically the entire Clojure world has agreed to a <a href="https://github.com/ring-clojure/ring/blob/master/SPEC">specification called "ring"</a> which says how these requests and responses translate to data structures in Clojure.</p>
<p>Clojure web servers are functions that take "ring requests" which look like the following</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>{<span class="at">:uri</span>            <span class="st">&quot;/echo&quot;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a> <span class="at">:request-method</span> <span class="at">:get</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a> <span class="at">:headers</span>        {}</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a> <span class="at">:body</span>           ...</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a> <span class="at">:protocol</span>       <span class="st">&quot;HTTP/1.1&quot;</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a> <span class="at">:remote-addr</span>    <span class="st">&quot;127.0.0.1&quot;</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a> <span class="at">:server-port</span>    <span class="dv">80</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a> <span class="at">:content-length</span> <span class="va">nil</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a> <span class="at">:query-string</span>   <span class="va">nil</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a> <span class="at">:scheme</span>         <span class="at">:http</span>}</span></code></pre></div>
<p>and produce "ring responses" which look like this.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>{<span class="at">:status</span>  <span class="dv">200</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a> <span class="at">:headers</span> {<span class="st">&quot;Content-Type&quot;</span> <span class="st">&quot;application/json&quot;</span>}</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a> <span class="at">:body</span>    <span class="st">&quot;{</span><span class="sc">\&quot;</span><span class="st">success</span><span class="sc">\&quot;</span><span class="st">:</span><span class="sc">\&quot;</span><span class="st">true</span><span class="sc">\&quot;</span><span class="st">}&quot;</span>}</span></code></pre></div>
<p>Everything else - <a href="https://github.com/metosin/reitit">routing</a>, <a href="https://github.com/funcool/buddy-auth">authentication</a>, <a href="https://github.com/ring-clojure/ring-json">middleware</a> - is built upon this foundation.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">ns</span> example</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>   (<span class="at">:require</span> [ring.adapter.jetty <span class="at">:as</span> jetty]))</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> handler </span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>  [request]</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>  (<span class="kw">cond</span> </span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>    (<span class="kw">=</span> (<span class="at">:uri</span> request) <span class="st">&quot;/hello&quot;</span>)</span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>    {<span class="at">:status</span> <span class="dv">200</span> </span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>     <span class="at">:body</span>   <span class="st">&quot;Hello, World&quot;</span>}</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>    <span class="at">:else</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>    {<span class="at">:status</span> <span class="dv">404</span>}))</span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> start-server </span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>  [] </span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a>  (jetty/run-server handler {<span class="at">:port</span> <span class="dv">1234</span>}))</span></code></pre></div>
<p>So this code, as written, will run a <a href="https://www.eclipse.org/jetty/">Jetty</a> server which responds to all requests to <code>/hello</code> with <code>Hello, World</code> and all other requests with a <code>404</code>.</p>
<h2 id="the-repl">The REPL</h2>
<p>One issue that is already relevant with preceding example, and will be a common theme going forward, is "REPL Friendliness."</p>
<p>Clojure and <a href="https://www.youtube.com/watch?v=Y0LUZ7gbWbk">other Lisps</a> have the unique property that the "unit" of code isn't a file, but instead an individual "form."</p>
<p>As an example, with Python you cannot run the following code.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="bu">print</span>(<span class="st">&quot;Start&quot;</span>)</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="dv">3</span>di92d93209032</span></code></pre></div>
<p>You will get a syntax error on the third line and nothing with run.</p>
<pre><code>  File &quot;/Users/emccue/Development/posts/example.py&quot;, line 3
    3di92d93209032
    ^
SyntaxError: invalid decimal literal</code></pre>
<p>The equivalent Clojure looks like this.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">println</span> <span class="st">&quot;Start&quot;</span>)</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>903f903jf939cn34f934fj9j39f4</span></code></pre></div>
<p>Unlike with the Python example, the very first <code>println</code> will actually run before a crash.</p>
<pre><code>Start
Syntax error reading source at (example.clj:4:0).
Invalid number: 903f903jf939cn34f934fj9j39f4</code></pre>
<p>The reason for this is that the Clojure reader will evaluate each "form" one at a time. There is no full pass of the file before running code.</p>
<p>This enables a workflow where a developer has a file open in one window with the full contents of their code and another window open at the same time with their "live" program - the "REPL".</p>
<p>Through editor magic, a developer can then load new code one form at a time into the live program. If in doing so a function is redefined, then the new definition of the function will start to be used.</p>
<p>There are many other explanations for <a href="https://clojure.org/guides/repl/introduction">this mechanism</a> and <a href="https://clojure.org/guides/repl/enhancing_your_repl_workflow">the workflow it enables</a> online.</p>
<p>So with that context, what is "not REPL friendly" about the example server code?</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> handler</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>   [request]</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">cond</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">=</span> (<span class="at">:uri</span> request) <span class="st">&quot;/hello&quot;</span>)</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>      {<span class="at">:status</span> <span class="dv">200</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>       <span class="at">:body</span>   <span class="st">&quot;Hello, World&quot;</span>}</span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>      <span class="at">:else</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>      {<span class="at">:status</span> <span class="dv">404</span>}))</span></code></pre></div>
<p>Assuming that first we load the <code>handler</code> function, we will next load the <code>start-server</code> function.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> start-server</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>   []</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>   (jetty/run-server handler {<span class="at">:port</span>  <span class="dv">1234</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>                              <span class="at">:join</span>? <span class="va">false</span>}))</span></code></pre></div>
<p>And some code will eventually call it to start the server</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>(start-server)</span></code></pre></div>
<p>At this point, a developer might want to modify the <code>handler</code> function to respond to requests on the <code>/marco</code> route.</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> handler</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>   [request]</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">cond</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">=</span> (<span class="at">:uri</span> request) <span class="st">&quot;/hello&quot;</span>)</span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>      {<span class="at">:status</span> <span class="dv">200</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>       <span class="at">:body</span>   <span class="st">&quot;Hello, World&quot;</span>}</span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">=</span> (<span class="at">:uri</span> request) <span class="st">&quot;/marco&quot;</span>)</span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>      {<span class="at">:status</span> <span class="dv">200</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>       <span class="at">:body</span>   <span class="st">&quot;POLO!&quot;</span>}</span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a>      <span class="at">:else</span></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>      {<span class="at">:status</span> <span class="dv">404</span>}))</span></code></pre></div>
<p>If they did this and tried making a request to <code>/marco</code>, the server would still respond with a <code>404</code>.</p>
<p>The reason for this is that whenever <code>start-server</code> is called it will be passed the current "value" backing the <code>handler</code> function. Future updates won't be picked up unless the server is stopped and restarted.</p>
<p>This is pretty trivially side-steppable by using some "indirection" mechanisms.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> start-server</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>   []</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>   (jetty/run-server <span class="va">#&#39;handler</span> {<span class="at">:port</span>  <span class="dv">1234</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>                                <span class="at">:join</span>? <span class="va">false</span>}))</span></code></pre></div>
<p>In this case, putting the <code>#'</code> in front of <code>handler</code> makes it so that whenever it is called the <a href="https://clojure.org/reference/vars">current value of the <code>handler</code> function will be used</a>. If a developer were to re-load a new definition of <code>handler</code> into the REPL it would be immediately picked up and used.</p>
<p>This is what REPL friendly code looks like. It makes it easier for a developer to have changes picked up on the fly in a running program and rapidly experiment with new things.</p>
<p>There are other associated techniques like leaving a comment at the bottom of a file with code only intended to be used with the REPL.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">ns</span> example</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>   (<span class="at">:require</span> [ring.adapter.jetty <span class="at">:as</span> jetty]))</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> handler </span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>  [request]</span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>  ...)</span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> start-server </span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a>  [] </span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a>  ...)</span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a><span class="co">;; The Server will not start automatically, but a dev</span></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a><span class="co">;; can conveniently start it by putting their cursor in</span></span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true" tabindex="-1"></a><span class="co">;; the comment and loading the call into the repl</span></span>
<span id="cb15-15"><a href="#cb15-15" aria-hidden="true" tabindex="-1"></a>(<span class="kw">comment</span></span>
<span id="cb15-16"><a href="#cb15-16" aria-hidden="true" tabindex="-1"></a>   (start-server))</span></code></pre></div>
<h2 id="global-stateful-resources">Global Stateful Resources</h2>
<p>Of course, most web apps are not written entirely in a single function. The most natural point at which to split out logic tends to be at handlers for different paths.</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">ns</span> example</span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>   (<span class="at">:require</span> [ring.adapter.jetty <span class="at">:as</span> jetty]))</span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> hello-handler </span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>   [request]</span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>   {<span class="at">:status</span> <span class="dv">200</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>    <span class="at">:body</span>   <span class="st">&quot;Hello, World&quot;</span>})</span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> marco-handler</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>   [request]</span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>   {<span class="at">:status</span> <span class="dv">200</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>    <span class="at">:body</span>   <span class="st">&quot;POLO!&quot;</span>})</span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> handler</span></span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a>   [request]</span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">cond</span></span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">=</span> (<span class="at">:uri</span> request) <span class="st">&quot;/hello&quot;</span>)</span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a>      (hello-handler request)</span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-20"><a href="#cb16-20" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">=</span> (<span class="at">:uri</span> request) <span class="st">&quot;/marco&quot;</span>)</span>
<span id="cb16-21"><a href="#cb16-21" aria-hidden="true" tabindex="-1"></a>      (marco-handler request)</span>
<span id="cb16-22"><a href="#cb16-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-23"><a href="#cb16-23" aria-hidden="true" tabindex="-1"></a>      <span class="at">:else</span></span>
<span id="cb16-24"><a href="#cb16-24" aria-hidden="true" tabindex="-1"></a>      {<span class="at">:status</span> <span class="dv">404</span>}))</span>
<span id="cb16-25"><a href="#cb16-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-26"><a href="#cb16-26" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> start-server</span></span>
<span id="cb16-27"><a href="#cb16-27" aria-hidden="true" tabindex="-1"></a>   []</span>
<span id="cb16-28"><a href="#cb16-28" aria-hidden="true" tabindex="-1"></a>   (jetty/run-server <span class="va">#&#39;handler</span> {<span class="at">:port</span>  <span class="dv">1234</span></span>
<span id="cb16-29"><a href="#cb16-29" aria-hidden="true" tabindex="-1"></a>                                <span class="at">:join</span>? <span class="va">false</span>}))</span>
<span id="cb16-30"><a href="#cb16-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-31"><a href="#cb16-31" aria-hidden="true" tabindex="-1"></a>(<span class="kw">comment</span></span>
<span id="cb16-32"><a href="#cb16-32" aria-hidden="true" tabindex="-1"></a>   (start-server))</span></code></pre></div>
<p>And of course the actual declarations of the routes can be separated from the code that starts the server, but that would get hard to follow here.</p>
<p>At this point most of the code is fairly easy to test. You just make fake requests, pass them to the handlers, and check that the responses are what you expect.</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">ns</span> example-test</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>   (<span class="at">:require</span> [clojure.<span class="kw">test</span> <span class="at">:as</span> t]</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>             [example]))</span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>   </span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a>(t/deftest handler-test</span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>  (t/testing <span class="st">&quot;Request to /hello gets Hello, World&quot;</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a>     (<span class="kw">let</span> [response (example/handler {<span class="at">:uri</span> <span class="st">&quot;/hello&quot;</span>})]</span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>        (t/is (<span class="kw">=</span> (<span class="at">:status</span> response) <span class="dv">200</span>))</span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a>        (t/is (<span class="kw">=</span> (<span class="at">:body</span> response) <span class="st">&quot;Hello, World&quot;</span>))))</span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a>  (t/testing <span class="st">&quot;Request to /marco gets POLO!&quot;</span></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a>     (<span class="kw">let</span> [response (example/handler {<span class="at">:uri</span> <span class="st">&quot;/marco&quot;</span>})]</span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a>        (t/is (<span class="kw">=</span> (<span class="at">:status</span> response) <span class="dv">200</span>))</span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a>        (t/is (<span class="kw">=</span> (<span class="at">:body</span> response) <span class="st">&quot;POLO!&quot;</span>))))</span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a>  (t/testing <span class="st">&quot;Request to unknown path gets 404&quot;</span></span>
<span id="cb17-17"><a href="#cb17-17" aria-hidden="true" tabindex="-1"></a>     (<span class="kw">let</span> [response (example/handler {<span class="at">:uri</span> <span class="st">&quot;/jdkdawdoaddwadad&quot;</span>})]</span>
<span id="cb17-18"><a href="#cb17-18" aria-hidden="true" tabindex="-1"></a>        (t/is (<span class="kw">=</span> (<span class="at">:status</span> response) <span class="dv">404</span>)))))</span></code></pre></div>
<p>This is a cool property of the overall ring model. <a href="https://github.com/ring-clojure/ring-mock">You can directly test handlers without having to actually spin up a server</a>.</p>
<p>No <a href="https://www.haskell.org/">real programs</a> can ever stay easy to test pure functions. Handling a request often implies the need for dependence on some "stateful resources" such as external services and connection pools.</p>
<h3 id="external-services">External Services</h3>
<p>As an example, lets say when you make a request to <code>/marco</code> we still want to respond with <code>POLO!</code>, but if the user specifies that they are not in a pool with a query string <code>/marco?nopool</code> then we want to respond with the entire Wikipedia page for Marco Polo.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> marco-handler</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>   [request]</span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">if</span> (<span class="kw">=</span> (<span class="at">:query-string</span> request) <span class="st">&quot;nopool&quot;</span>)</span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>      {<span class="at">:status</span> <span class="dv">200</span> </span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>       <span class="at">:body</span>   (<span class="kw">slurp</span> <span class="st">&quot;https://en.wikipedia.org/wiki/Marco_Polo&quot;</span>)}</span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>      {<span class="at">:status</span> <span class="dv">200</span></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a>       <span class="at">:body</span>   <span class="st">&quot;POLO!&quot;</span>}))</span></code></pre></div>
<p>While we can still test this conveniently, the test will have an implicit dependence on Wikipedia being online. It also makes our tests slower than they need to be since we are making an actual http call.</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">ns</span> example-test</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>   (<span class="at">:require</span> [clojure.string <span class="at">:as</span> string]</span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>             [clojure.<span class="kw">test</span> <span class="at">:as</span> t]</span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>             [example]))</span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a>             </span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>(t/deftest marco-handler-test        </span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a>  (t/testing <span class="st">&quot;Request to /marco gets POLO!&quot;</span></span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a>     (<span class="kw">let</span> [response (example/marco-handler {<span class="at">:uri</span> <span class="st">&quot;/marco&quot;</span>})]</span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a>        (t/is (<span class="kw">=</span> (<span class="at">:status</span> response) <span class="dv">200</span>))</span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a>        (t/is (<span class="kw">=</span> (<span class="at">:body</span> response) <span class="st">&quot;POLO!&quot;</span>))))</span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb19-12"><a href="#cb19-12" aria-hidden="true" tabindex="-1"></a>  (t/testing <span class="st">&quot;Request to /marco with no pool gets info&quot;</span></span>
<span id="cb19-13"><a href="#cb19-13" aria-hidden="true" tabindex="-1"></a>     (<span class="kw">let</span> [response (example/marco-handler {<span class="at">:uri</span>          <span class="st">&quot;/marco&quot;</span></span>
<span id="cb19-14"><a href="#cb19-14" aria-hidden="true" tabindex="-1"></a>                                            <span class="at">:query-string</span> <span class="st">&quot;nopool&quot;</span>})]</span>
<span id="cb19-15"><a href="#cb19-15" aria-hidden="true" tabindex="-1"></a>        (t/is (<span class="kw">=</span> (<span class="at">:status</span> response) <span class="dv">200</span>))</span>
<span id="cb19-16"><a href="#cb19-16" aria-hidden="true" tabindex="-1"></a>        (t/is (string/includes?</span>
<span id="cb19-17"><a href="#cb19-17" aria-hidden="true" tabindex="-1"></a>                (<span class="at">:body</span> response) </span>
<span id="cb19-18"><a href="#cb19-18" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;The Travels of Marco Polo&quot;</span>)))))</span></code></pre></div>
<p>This isn't ideal, but it could be worse. Imagine if you wanted to alert an admin every time the <code>/hello</code> route was called. A bit of a silly example, but calls to APIs like <a href="https://sendgrid.com/">Sendgrid</a> aren't unreasonable to do in response to some requests.</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> hello-handler</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>   [request]</span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>   (sendgrid/send-email <span class="st">&quot;admin@website.com&quot;</span> <span class="st">&quot;You got a user!&quot;</span>)</span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>   {<span class="at">:status</span> <span class="dv">200</span></span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a>    <span class="at">:body</span>   <span class="st">&quot;Hello, World&quot;</span>})</span></code></pre></div>
<p>As written, this is a doozy to test. Either you</p>
<ul>
<li>Make sure you only have test credentials loaded when running your unit tests. Don't mess it up!</li>
<li>Make sure you have no credentials loaded when running your unit tests. You now need to be extra cautious that you are okay with calls being made that will always fail.</li>
<li>Stub out the functions that call out to external services with a mechanism like <code>with-redefs</code>.</li>
</ul>
<p>The problem with the last solution, even though it does mechanically solve the issue, is that you need to know what external services a piece of code will use. Since our handlers are just taking a request, there is not enough information at call-sites or in the function header to say for sure.</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> hello-handler</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>   [request]</span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>   <span class="co">;; Have to read every function this calls</span></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>   <span class="co">;; to see what stateful stuff is going on...</span></span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>   (some-other-code request))</span></code></pre></div>
<p>So tests end up looking like the following, with pretty low confidence that everything has been stubbed out.</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a>(with-redefs [sendgrid/send-email (<span class="kw">constantly</span> <span class="va">nil</span>)]</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>   (t/testing ... ACTUAL TEST ...))</span></code></pre></div>
<h3 id="connection-pools">Connection Pools</h3>
<p>Handlers also very often need to talk to a database. It is wasteful to make a new database connection on every request, so a really common technique is to keep a certain number of connections alive in a "pool" and re-use them over and over again.</p>
<p>What is common, and saddening, to find is a connection pool stored in a top-level constant and referenced by a large part of the codebase.</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">ns</span> example.db</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>   (<span class="at">:import</span> (com.zaxxer.hikari</span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>              HikariConfig</span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>              HikariDataSource)))</span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a>(<span class="bu">def</span><span class="fu"> pool </span>(HikariDataSource. </span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a>            (<span class="kw">doto</span> (HikariConfig.)</span>
<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a>              (.setJdbcUrl <span class="st">&quot;...&quot;</span>))))</span></code></pre></div>
<div class="sourceCode" id="cb24"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> hello-handler</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>   [request]</span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>   <span class="co">;; Information like this can come from middleware.</span></span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">let</span> [user-id   (<span class="at">:user-id</span> request)</span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a>         user-name (jdbc/execute-one! </span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a>                      db/pool </span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a>                      [<span class="st">&quot;SELECT name FROM user </span></span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a><span class="st">                        WHERE user.user_id = ?&quot;</span></span>
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a>                       user-id])]</span>
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a>     {<span class="at">:status</span> <span class="dv">200</span></span>
<span id="cb24-11"><a href="#cb24-11" aria-hidden="true" tabindex="-1"></a>      <span class="at">:body</span>   (<span class="kw">str</span> <span class="st">&quot;Hello, &quot;</span> user-name)}))</span></code></pre></div>
<p>Even assuming that, <a href="https://dhh.dk/2014/slow-database-test-fallacy.html">like DHH</a>, you are fine with your tests hitting a real database this still creates some practical problems.</p>
<p>For one, if you edit the file where the connection is defined you might accidentally reload the constant and leak a bunch of connections. This isn't the most likely on a large project where you aren't touching this code that often, but over the course of a <a href="https://www.youtube.com/watch?v=gIoadGfm5T8">long lived REPL session</a> it can be an annoying.</p>
<p>But also it is annoying logistically that the connection pool is established immediately when the code is loaded. If you Ahead-of-Time compile your Clojure code then you will pretty immediately want that to not be the case.</p>
<p>You can sidestep that last issue by putting the connection pool behind a "<a href="https://clojuredocs.org/clojure.core/delay">delay</a>", which lazily starts the connection pool when it is needed.</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">ns</span> example.db)</span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a>(<span class="bu">def</span><span class="fu"> pool </span>(<span class="kw">delay</span> </span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a>             (HikariDataSource. </span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a>               (<span class="kw">doto</span> (HikariConfig.)</span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a>                 (.setJdbcUrl <span class="st">&quot;...&quot;</span>)))))</span></code></pre></div>
<p>But now this detail changes how users have to access the actual pool. Usage sites have to add an <code>@</code> to make sure the pool has been started and to retrieve it.</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> hello-handler</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>   [request]</span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">let</span> [user-id   (<span class="at">:user-id</span> request)</span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a>         user-name (jdbc/execute-one! </span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a>                      <span class="at">@db/pool</span> </span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a>                      [<span class="st">&quot;SELECT name FROM user </span></span>
<span id="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a><span class="st">                        WHERE user.user_id = ?&quot;</span></span>
<span id="cb26-8"><a href="#cb26-8" aria-hidden="true" tabindex="-1"></a>                       user-id])]</span>
<span id="cb26-9"><a href="#cb26-9" aria-hidden="true" tabindex="-1"></a>     {<span class="at">:status</span> <span class="dv">200</span></span>
<span id="cb26-10"><a href="#cb26-10" aria-hidden="true" tabindex="-1"></a>      <span class="at">:body</span>   (<span class="kw">str</span> <span class="st">&quot;Hello, &quot;</span> user-name)}))</span></code></pre></div>
<p>Annoying, but that's not all. if you want to sub out the pool in a test fixture and maybe run tests in parallel then the whole pool needs to be dynamically re-bindable as well.</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">def</span><span class="fu"> </span>^<span class="at">:dynamic</span> </span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>   *pool* </span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">delay</span> </span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a>      (HikariDataSource. </span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a>         (<span class="kw">doto</span> (HikariConfig.)</span>
<span id="cb27-6"><a href="#cb27-6" aria-hidden="true" tabindex="-1"></a>            (.setJdbcUrl <span class="st">&quot;...&quot;</span>)))))</span></code></pre></div>
<div class="sourceCode" id="cb28"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> hello-handler</span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>   [request]</span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">let</span> [user-id   (<span class="at">:user-id</span> request)</span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a>         user-name (jdbc/execute-one! </span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a>                      <span class="at">@db/*pool*</span></span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a>                      [<span class="st">&quot;SELECT name FROM user </span></span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a><span class="st">                        WHERE user.user_id = ?&quot;</span></span>
<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a>                       user-id])]</span>
<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a>     {<span class="at">:status</span> <span class="dv">200</span></span>
<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a>      <span class="at">:body</span>   (<span class="kw">str</span> <span class="st">&quot;Hello, &quot;</span> user-name)}))</span></code></pre></div>
<div class="sourceCode" id="cb29"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">binding</span> [db/*pool* (<span class="kw">delay</span> (make-test-pool))]</span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>   (insert-user <span class="dv">123</span> <span class="st">&quot;bob&quot;</span>)</span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">let</span> [response (hello-handler {<span class="at">:user-id</span> <span class="dv">123</span>})]</span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a>      (t/is (<span class="kw">=</span> (<span class="at">:body</span> response)</span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a>               <span class="st">&quot;Hello, bob&quot;</span>))))</span></code></pre></div>
<p>All of that is workable - you can use macros and helper functions to alleviate the syntax ugliness and generally speaking your app <em>will</em> just have one database.</p>
<p>But it also is not that uncommon for an app to have two databases. Usually one SQL and one Redis-like. And while it's not as hard as for arbitrary external services - you still don't really know from a call-site whether you need to establish a test database before calling it in a test.</p>
<h2 id="inversion-of-control">Inversion of Control</h2>
<p>The general shape of the solution to those problems is to not have "global" stateful resources.</p>
<p>For external services, this means making an actual object to pass as the first argument to calls.</p>
<p>If the service is like Sendgrid, this could be a convenient place to put information like your API key or make a <a href="https://github.com/gnarroway/hato#building-a-client">persistent http client</a>.</p>
<div class="sourceCode" id="cb30"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> make-sendgrid-client </span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>   [api-key]</span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a>   {<span class="at">:api-key</span> api-key</span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a>    <span class="at">:client</span>  (hato/build-http-client {<span class="at">:connect-timeout</span> <span class="dv">10000</span></span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a>                                      <span class="at">:redirect-policy</span> <span class="at">:always</span>})})</span>
<span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> send-email </span></span>
<span id="cb30-8"><a href="#cb30-8" aria-hidden="true" tabindex="-1"></a>   [sendgrid-client]</span>
<span id="cb30-9"><a href="#cb30-9" aria-hidden="true" tabindex="-1"></a>   (hato/post (<span class="at">:client</span> sendgrid-client) <span class="st">&quot;/send-email&quot;</span>))</span></code></pre></div>
<p>But even if the service is "stupid" and requires no authentication or special treatment like Wikipedia, there is still value.</p>
<div class="sourceCode" id="cb31"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> make-wikipedia-client</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>   []</span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a>   <span class="co">;; Nothing really to put...</span></span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a>   {<span class="at">:name</span> <span class="st">&quot;Wikipedia Client&quot;</span>})</span>
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> get-marco-polo-info</span></span>
<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a>  [wikipedia-client]</span>
<span id="cb31-8"><a href="#cb31-8" aria-hidden="true" tabindex="-1"></a>  (<span class="kw">slurp</span> <span class="st">&quot;https://en.wikipedia.org/wiki/Marco_Polo&quot;</span>))</span></code></pre></div>
<p>The value being in the fact that having <em>something</em> as a first argument means that later on you have the ability to refactor calls to be behind some dispatch mechanism like a protocol.</p>
<div class="sourceCode" id="cb32"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defprotocol</span><span class="fu"> WikipediaClient</span></span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a>   (get-marco-polo-info [_]))</span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> make-wikipedia-client</span></span>
<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a>   []</span>
<span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">reify</span> WikipediaClient</span>
<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a>      (get-marco-polo-info [_]</span>
<span id="cb32-8"><a href="#cb32-8" aria-hidden="true" tabindex="-1"></a>         (<span class="kw">slurp</span> <span class="st">&quot;https://en.wikipedia.org/wiki/Marco_Polo&quot;</span>))))</span></code></pre></div>
<p>Which in turn can enable creating "fake" implementations for testing.</p>
<div class="sourceCode" id="cb33"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">def</span><span class="fu"> fake-wikipedia</span></span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">reify</span> WikipediaClient</span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a>      (get-marco-polo-info [_]</span>
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a>         <span class="st">&quot;was a dude, i guess?&quot;</span>)))</span></code></pre></div>
<p>For connection pools, there is already an actual object to pass so that isn't an issue. The same "maybe make it a protocol later" strategy is applicable to that sort of resource as well.</p>
<p>Then in all the code that wants these dependencies, just expect them to be given as arguments.</p>
<div class="sourceCode" id="cb34"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> marco-handler</span></span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>   [wikipedia-client request]</span>
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">if</span> (<span class="kw">=</span> (<span class="at">:query-string</span> request) <span class="st">&quot;nopool&quot;</span>)</span>
<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a>      {<span class="at">:status</span> <span class="dv">200</span> </span>
<span id="cb34-5"><a href="#cb34-5" aria-hidden="true" tabindex="-1"></a>       <span class="at">:body</span>   (wikipedia/get-marco-polo-info wikipedia-client)}</span>
<span id="cb34-6"><a href="#cb34-6" aria-hidden="true" tabindex="-1"></a>      {<span class="at">:status</span> <span class="dv">200</span></span>
<span id="cb34-7"><a href="#cb34-7" aria-hidden="true" tabindex="-1"></a>       <span class="at">:body</span>   <span class="st">&quot;POLO!&quot;</span>}))</span></code></pre></div>
<p>Which provides a clear path to sensible testing.</p>
<div class="sourceCode" id="cb35"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">ns</span> example-test</span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a>   (<span class="at">:require</span> [clojure.string <span class="at">:as</span> string]</span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a>             [clojure.<span class="kw">test</span> <span class="at">:as</span> t]</span>
<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a>             [example]))</span>
<span id="cb35-5"><a href="#cb35-5" aria-hidden="true" tabindex="-1"></a>             </span>
<span id="cb35-6"><a href="#cb35-6" aria-hidden="true" tabindex="-1"></a>(t/deftest marco-handler-test </span>
<span id="cb35-7"><a href="#cb35-7" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">let</span> [mock-wikipedia (<span class="kw">reify</span> WikipediaClient</span>
<span id="cb35-8"><a href="#cb35-8" aria-hidden="true" tabindex="-1"></a>                           (get-marco-polo-info [_]</span>
<span id="cb35-9"><a href="#cb35-9" aria-hidden="true" tabindex="-1"></a>                              <span class="st">&quot;INFO&quot;</span>))]       </span>
<span id="cb35-10"><a href="#cb35-10" aria-hidden="true" tabindex="-1"></a>     (t/testing <span class="st">&quot;Request to /marco gets POLO!&quot;</span></span>
<span id="cb35-11"><a href="#cb35-11" aria-hidden="true" tabindex="-1"></a>        (<span class="kw">let</span> [response (example/marco-handler </span>
<span id="cb35-12"><a href="#cb35-12" aria-hidden="true" tabindex="-1"></a>                         mock-wikipedia</span>
<span id="cb35-13"><a href="#cb35-13" aria-hidden="true" tabindex="-1"></a>                         {<span class="at">:uri</span> <span class="st">&quot;/marco&quot;</span>})]</span>
<span id="cb35-14"><a href="#cb35-14" aria-hidden="true" tabindex="-1"></a>           (t/is (<span class="kw">=</span> (<span class="at">:status</span> response) <span class="dv">200</span>))</span>
<span id="cb35-15"><a href="#cb35-15" aria-hidden="true" tabindex="-1"></a>           (t/is (<span class="kw">=</span> (<span class="at">:body</span> response) <span class="st">&quot;POLO!&quot;</span>))))</span>
<span id="cb35-16"><a href="#cb35-16" aria-hidden="true" tabindex="-1"></a>           </span>
<span id="cb35-17"><a href="#cb35-17" aria-hidden="true" tabindex="-1"></a>     (t/testing <span class="st">&quot;Request to /marco with no pool gets info&quot;</span></span>
<span id="cb35-18"><a href="#cb35-18" aria-hidden="true" tabindex="-1"></a>        (<span class="kw">let</span> [response (example/marco-handler </span>
<span id="cb35-19"><a href="#cb35-19" aria-hidden="true" tabindex="-1"></a>                        mock-wikipedia</span>
<span id="cb35-20"><a href="#cb35-20" aria-hidden="true" tabindex="-1"></a>                        {<span class="at">:uri</span>          <span class="st">&quot;/marco&quot;</span></span>
<span id="cb35-21"><a href="#cb35-21" aria-hidden="true" tabindex="-1"></a>                         <span class="at">:query-string</span> <span class="st">&quot;nopool&quot;</span>})]</span>
<span id="cb35-22"><a href="#cb35-22" aria-hidden="true" tabindex="-1"></a>           (t/is (<span class="kw">=</span> (<span class="at">:status</span> response) <span class="dv">200</span>))</span>
<span id="cb35-23"><a href="#cb35-23" aria-hidden="true" tabindex="-1"></a>           (t/is (<span class="kw">=</span> (<span class="at">:body</span> response) <span class="st">&quot;INFO&quot;</span>)))))</span></code></pre></div>
<p>This technique - where we get dependencies as arguments instead of making them locally or getting them from some global place - is commonly called "<a href="https://martinfowler.com/bliki/InversionOfControl.html">Inversion of Control</a>."</p>
<h2 id="dependency-injection-and-the-system">Dependency Injection and "The System"</h2>
<p>While this is a concrete improvement - we can directly see what the dependencies of a process are in the argument list - there are still some unresolved issues.</p>
<p>Let's say our <code>hello-handler</code> wants to use a <code>sendgrid-service</code> and the database <code>pool</code> and our <code>marco-handler</code> wants to use a <code>wikipedia-service</code> and the database <code>pool</code>.</p>
<div class="sourceCode" id="cb36"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> hello-handler</span></span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a>   [sendgrid-service pool request]</span>
<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a>   ...)</span>
<span id="cb36-4"><a href="#cb36-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-5"><a href="#cb36-5" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> marco-handler</span></span>
<span id="cb36-6"><a href="#cb36-6" aria-hidden="true" tabindex="-1"></a>   [wikipedia-service pool request]</span>
<span id="cb36-7"><a href="#cb36-7" aria-hidden="true" tabindex="-1"></a>   ...)</span></code></pre></div>
<p>This implies that the root <code>handler</code> function will have access to all of these things and pass them down as needed.</p>
<div class="sourceCode" id="cb37"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> handler</span></span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a>   [sendgrid-service wikipedia-service pool request]</span>
<span id="cb37-3"><a href="#cb37-3" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">cond</span></span>
<span id="cb37-4"><a href="#cb37-4" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">=</span> (<span class="at">:uri</span> request) <span class="st">&quot;/hello&quot;</span>)</span>
<span id="cb37-5"><a href="#cb37-5" aria-hidden="true" tabindex="-1"></a>      (hello-handler sendgrid-service pool request)</span>
<span id="cb37-6"><a href="#cb37-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-7"><a href="#cb37-7" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">=</span> (<span class="at">:uri</span> request) <span class="st">&quot;/marco&quot;</span>)</span>
<span id="cb37-8"><a href="#cb37-8" aria-hidden="true" tabindex="-1"></a>      (marco-handler wikipedia-service pool request)</span>
<span id="cb37-9"><a href="#cb37-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-10"><a href="#cb37-10" aria-hidden="true" tabindex="-1"></a>      <span class="at">:else</span></span>
<span id="cb37-11"><a href="#cb37-11" aria-hidden="true" tabindex="-1"></a>      {<span class="at">:status</span> <span class="dv">404</span>}))</span></code></pre></div>
<p>With just three stateful components and two handlers this is manageable, but beyond three arguments using positional arguments is overly burdensome and error-prone.</p>
<div class="sourceCode" id="cb38"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> handler</span></span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a>   [sendgrid-service </span>
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a>    wikipedia-service </span>
<span id="cb38-4"><a href="#cb38-4" aria-hidden="true" tabindex="-1"></a>    pool</span>
<span id="cb38-5"><a href="#cb38-5" aria-hidden="true" tabindex="-1"></a>    some-service</span>
<span id="cb38-6"><a href="#cb38-6" aria-hidden="true" tabindex="-1"></a>    other-thing</span>
<span id="cb38-7"><a href="#cb38-7" aria-hidden="true" tabindex="-1"></a>    oh-no</span>
<span id="cb38-8"><a href="#cb38-8" aria-hidden="true" tabindex="-1"></a>    request]</span>
<span id="cb38-9"><a href="#cb38-9" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">cond</span></span>
<span id="cb38-10"><a href="#cb38-10" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">=</span> (<span class="at">:uri</span> request) <span class="st">&quot;/hello&quot;</span>)</span>
<span id="cb38-11"><a href="#cb38-11" aria-hidden="true" tabindex="-1"></a>      (hello-handler sendgrid-service pool request)</span>
<span id="cb38-12"><a href="#cb38-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-13"><a href="#cb38-13" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">=</span> (<span class="at">:uri</span> request) <span class="st">&quot;/marco&quot;</span>)</span>
<span id="cb38-14"><a href="#cb38-14" aria-hidden="true" tabindex="-1"></a>      (marco-handler wikipedia-service pool request)</span>
<span id="cb38-15"><a href="#cb38-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-16"><a href="#cb38-16" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">=</span> (<span class="at">:uri</span> request) <span class="st">&quot;/thing&quot;</span>)</span>
<span id="cb38-17"><a href="#cb38-17" aria-hidden="true" tabindex="-1"></a>      (some-handler some-service sendgrid-service request)</span>
<span id="cb38-18"><a href="#cb38-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-19"><a href="#cb38-19" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">=</span> (<span class="at">:uri</span> request) <span class="st">&quot;/thing2&quot;</span>)</span>
<span id="cb38-20"><a href="#cb38-20" aria-hidden="true" tabindex="-1"></a>      (some-handler some-service </span>
<span id="cb38-21"><a href="#cb38-21" aria-hidden="true" tabindex="-1"></a>                    oh-no </span>
<span id="cb38-22"><a href="#cb38-22" aria-hidden="true" tabindex="-1"></a>                    sendgrid-service </span>
<span id="cb38-23"><a href="#cb38-23" aria-hidden="true" tabindex="-1"></a>                    other-thing  </span>
<span id="cb38-24"><a href="#cb38-24" aria-hidden="true" tabindex="-1"></a>                    request)</span>
<span id="cb38-25"><a href="#cb38-25" aria-hidden="true" tabindex="-1"></a>      </span>
<span id="cb38-26"><a href="#cb38-26" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">=</span> (<span class="at">:uri</span> request) <span class="st">&quot;/thing3&quot;</span>)</span>
<span id="cb38-27"><a href="#cb38-27" aria-hidden="true" tabindex="-1"></a>      (some-handler some-service </span>
<span id="cb38-28"><a href="#cb38-28" aria-hidden="true" tabindex="-1"></a>                    oh-no</span>
<span id="cb38-29"><a href="#cb38-29" aria-hidden="true" tabindex="-1"></a>                    other-thing  </span>
<span id="cb38-30"><a href="#cb38-30" aria-hidden="true" tabindex="-1"></a>                    request)</span>
<span id="cb38-31"><a href="#cb38-31" aria-hidden="true" tabindex="-1"></a>      </span>
<span id="cb38-32"><a href="#cb38-32" aria-hidden="true" tabindex="-1"></a>      <span class="co">;; ... * 100</span></span>
<span id="cb38-33"><a href="#cb38-33" aria-hidden="true" tabindex="-1"></a>      </span>
<span id="cb38-34"><a href="#cb38-34" aria-hidden="true" tabindex="-1"></a>      <span class="at">:else</span></span>
<span id="cb38-35"><a href="#cb38-35" aria-hidden="true" tabindex="-1"></a>      {<span class="at">:status</span> <span class="dv">404</span>}))</span></code></pre></div>
<p>The solution is to put all stateful components into a single map, popularly called the "system."</p>
<div class="sourceCode" id="cb39"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a>{<span class="at">:sendgrid-service</span>  sendgrid-service</span>
<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a> <span class="at">:wikipedia-service</span> wikipedia-service</span>
<span id="cb39-3"><a href="#cb39-3" aria-hidden="true" tabindex="-1"></a> <span class="at">:pool</span>              pool}</span></code></pre></div>
<p>Then the handler just threads down this one map to all the entry-points</p>
<div class="sourceCode" id="cb40"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> handler</span></span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a>   [system request]</span>
<span id="cb40-3"><a href="#cb40-3" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">cond</span></span>
<span id="cb40-4"><a href="#cb40-4" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">=</span> (<span class="at">:uri</span> request) <span class="st">&quot;/hello&quot;</span>)</span>
<span id="cb40-5"><a href="#cb40-5" aria-hidden="true" tabindex="-1"></a>      (hello-handler system request)</span>
<span id="cb40-6"><a href="#cb40-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-7"><a href="#cb40-7" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">=</span> (<span class="at">:uri</span> request) <span class="st">&quot;/marco&quot;</span>)</span>
<span id="cb40-8"><a href="#cb40-8" aria-hidden="true" tabindex="-1"></a>      (marco-handler system request)</span>
<span id="cb40-9"><a href="#cb40-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-10"><a href="#cb40-10" aria-hidden="true" tabindex="-1"></a>      <span class="at">:else</span></span>
<span id="cb40-11"><a href="#cb40-11" aria-hidden="true" tabindex="-1"></a>      {<span class="at">:status</span> <span class="dv">404</span>}))</span></code></pre></div>
<p>and individual handlers "declare" which of these components they are interested in by only pulling those keys out of the map.</p>
<div class="sourceCode" id="cb41"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> hello-handler</span></span>
<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a>   [{<span class="at">:keys</span> [sendgrid-service pool]} request]</span>
<span id="cb41-3"><a href="#cb41-3" aria-hidden="true" tabindex="-1"></a>   ...)</span>
<span id="cb41-4"><a href="#cb41-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb41-5"><a href="#cb41-5" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> marco-handler</span></span>
<span id="cb41-6"><a href="#cb41-6" aria-hidden="true" tabindex="-1"></a>   [{<span class="at">:keys</span> [wikipedia-service pool]} request]</span>
<span id="cb41-7"><a href="#cb41-7" aria-hidden="true" tabindex="-1"></a>   ...)</span></code></pre></div>
<p>This way it is still declared up front what stateful components some bit of code needs to do its work, but the "wiring" code for each entry-point can stay uniform.</p>
<p>This technique, where all a piece of code needs to do to get access to a resource is "declare" that they want it is usually called "<a href="https://martinfowler.com/articles/injection.html">Dependency Injection</a>."</p>
<p>Important to note also that after this "entry-point" code should generally pass down things explicitly. Passing the whole system is a hand-gun pointed at a foot-foot.</p>
<div class="sourceCode" id="cb42"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb42-1"><a href="#cb42-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> marco-handler</span></span>
<span id="cb42-2"><a href="#cb42-2" aria-hidden="true" tabindex="-1"></a>   [{<span class="at">:keys</span> [wikipedia-service pool]</span>
<span id="cb42-3"><a href="#cb42-3" aria-hidden="true" tabindex="-1"></a>     <span class="at">:as</span> system} request]</span>
<span id="cb42-4"><a href="#cb42-4" aria-hidden="true" tabindex="-1"></a>   ...</span>
<span id="cb42-5"><a href="#cb42-5" aria-hidden="true" tabindex="-1"></a>   <span class="co">;; Back to not knowing what this could be doing deep down...</span></span>
<span id="cb42-6"><a href="#cb42-6" aria-hidden="true" tabindex="-1"></a>   (some-code system)</span>
<span id="cb42-7"><a href="#cb42-7" aria-hidden="true" tabindex="-1"></a>   ...)</span></code></pre></div>
<h2 id="starting-and-stopping-the-system">Starting and Stopping the System</h2>
<p>There needs to be some code that actually starts up all the components of the system.</p>
<div class="sourceCode" id="cb43"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb43-1"><a href="#cb43-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> start-system </span></span>
<span id="cb43-2"><a href="#cb43-2" aria-hidden="true" tabindex="-1"></a>  []</span>
<span id="cb43-3"><a href="#cb43-3" aria-hidden="true" tabindex="-1"></a>  (<span class="kw">let</span> [config            (load-config)</span>
<span id="cb43-4"><a href="#cb43-4" aria-hidden="true" tabindex="-1"></a>        sendgrid-service  (make-sendgrid-service config)</span>
<span id="cb43-5"><a href="#cb43-5" aria-hidden="true" tabindex="-1"></a>        wikipedia-service (make-wikipedia-service)</span>
<span id="cb43-6"><a href="#cb43-6" aria-hidden="true" tabindex="-1"></a>        pool              (make-pool config)]</span>
<span id="cb43-7"><a href="#cb43-7" aria-hidden="true" tabindex="-1"></a>     {<span class="at">:config</span>            config</span>
<span id="cb43-8"><a href="#cb43-8" aria-hidden="true" tabindex="-1"></a>      <span class="at">:sendgrid-service</span>  sendgrid-service</span>
<span id="cb43-9"><a href="#cb43-9" aria-hidden="true" tabindex="-1"></a>      <span class="at">:wikipedia-service</span> wikipedia-service</span>
<span id="cb43-10"><a href="#cb43-10" aria-hidden="true" tabindex="-1"></a>      <span class="at">:pool</span>              pool}))</span></code></pre></div>
<p>Some stateful bits might depend on other stateful bits to get started. In the above example the hypothetical Sendgrid service and database connection pool depend on some config object which is loaded earlier.</p>
<p>Clearest example of that is the server instance itself. If it is to be put into the system, then it will need all the things started before it.</p>
<div class="sourceCode" id="cb44"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb44-1"><a href="#cb44-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> start-system </span></span>
<span id="cb44-2"><a href="#cb44-2" aria-hidden="true" tabindex="-1"></a>  []</span>
<span id="cb44-3"><a href="#cb44-3" aria-hidden="true" tabindex="-1"></a>  (<span class="kw">let</span> [config            (load-config)</span>
<span id="cb44-4"><a href="#cb44-4" aria-hidden="true" tabindex="-1"></a>        sendgrid-service  (make-sendgrid-service config)</span>
<span id="cb44-5"><a href="#cb44-5" aria-hidden="true" tabindex="-1"></a>        wikipedia-service (make-wikipedia-service)</span>
<span id="cb44-6"><a href="#cb44-6" aria-hidden="true" tabindex="-1"></a>        pool              (make-pool config)</span>
<span id="cb44-7"><a href="#cb44-7" aria-hidden="true" tabindex="-1"></a>        system-so-far     {<span class="at">:config</span>            config</span>
<span id="cb44-8"><a href="#cb44-8" aria-hidden="true" tabindex="-1"></a>                           <span class="at">:sendgrid-service</span>  sendgrid-service</span>
<span id="cb44-9"><a href="#cb44-9" aria-hidden="true" tabindex="-1"></a>                           <span class="at">:wikipedia-service</span> wikipedia-service</span>
<span id="cb44-10"><a href="#cb44-10" aria-hidden="true" tabindex="-1"></a>                           <span class="at">:pool</span>              pool}</span>
<span id="cb44-11"><a href="#cb44-11" aria-hidden="true" tabindex="-1"></a>        server            (start-server system-so-far)]</span>
<span id="cb44-12"><a href="#cb44-12" aria-hidden="true" tabindex="-1"></a>     (<span class="kw">assoc</span> system-so-far <span class="at">:server</span> server)))</span></code></pre></div>
<div class="sourceCode" id="cb45"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb45-1"><a href="#cb45-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> hello-handler</span></span>
<span id="cb45-2"><a href="#cb45-2" aria-hidden="true" tabindex="-1"></a>   [{<span class="at">:keys</span> [sendgrid-service pool]} request]</span>
<span id="cb45-3"><a href="#cb45-3" aria-hidden="true" tabindex="-1"></a>   ...)</span>
<span id="cb45-4"><a href="#cb45-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb45-5"><a href="#cb45-5" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> marco-handler</span></span>
<span id="cb45-6"><a href="#cb45-6" aria-hidden="true" tabindex="-1"></a>   [{<span class="at">:keys</span> [wikipedia-service pool]} request]</span>
<span id="cb45-7"><a href="#cb45-7" aria-hidden="true" tabindex="-1"></a>   ...)</span>
<span id="cb45-8"><a href="#cb45-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb45-9"><a href="#cb45-9" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> handler</span></span>
<span id="cb45-10"><a href="#cb45-10" aria-hidden="true" tabindex="-1"></a>   [system request]</span>
<span id="cb45-11"><a href="#cb45-11" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">cond</span></span>
<span id="cb45-12"><a href="#cb45-12" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">=</span> (<span class="at">:uri</span> request) <span class="st">&quot;/hello&quot;</span>)</span>
<span id="cb45-13"><a href="#cb45-13" aria-hidden="true" tabindex="-1"></a>      (hello-handler system request)</span>
<span id="cb45-14"><a href="#cb45-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb45-15"><a href="#cb45-15" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">=</span> (<span class="at">:uri</span> request) <span class="st">&quot;/marco&quot;</span>)</span>
<span id="cb45-16"><a href="#cb45-16" aria-hidden="true" tabindex="-1"></a>      (marco-handler system request)</span>
<span id="cb45-17"><a href="#cb45-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb45-18"><a href="#cb45-18" aria-hidden="true" tabindex="-1"></a>      <span class="at">:else</span></span>
<span id="cb45-19"><a href="#cb45-19" aria-hidden="true" tabindex="-1"></a>      {<span class="at">:status</span> <span class="dv">404</span>}))</span>
<span id="cb45-20"><a href="#cb45-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb45-21"><a href="#cb45-21" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> start-server</span></span>
<span id="cb45-22"><a href="#cb45-22" aria-hidden="true" tabindex="-1"></a>   [system]</span>
<span id="cb45-23"><a href="#cb45-23" aria-hidden="true" tabindex="-1"></a>   (jetty/run-server </span>
<span id="cb45-24"><a href="#cb45-24" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">partial</span> <span class="va">#&#39;handler</span> system) </span>
<span id="cb45-25"><a href="#cb45-25" aria-hidden="true" tabindex="-1"></a>      {<span class="at">:port</span>  <span class="dv">1234</span></span>
<span id="cb45-26"><a href="#cb45-26" aria-hidden="true" tabindex="-1"></a>       <span class="at">:join</span>? <span class="va">false</span>}))</span></code></pre></div>
<p>The reason you would want the server to be part of the system ties back to the REPL workflow. If you change or add some stateful component you might want to stop an old running system and start up a new one. The running http server is likely to be one of these things you would want to restart.</p>
<p>To properly do this, every stateful resource which might have shutdown logic needs to provide a function which shuts it down.</p>
<div class="sourceCode" id="cb46"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb46-1"><a href="#cb46-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> stop-server </span></span>
<span id="cb46-2"><a href="#cb46-2" aria-hidden="true" tabindex="-1"></a>   [server]</span>
<span id="cb46-3"><a href="#cb46-3" aria-hidden="true" tabindex="-1"></a>   (.stop server))</span></code></pre></div>
<p>And then some larger function needs to be able to stop each component of the system, doing so in the reverse order they were started ideally.</p>
<div class="sourceCode" id="cb47"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb47-1"><a href="#cb47-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> stop-system </span></span>
<span id="cb47-2"><a href="#cb47-2" aria-hidden="true" tabindex="-1"></a>   [system]</span>
<span id="cb47-3"><a href="#cb47-3" aria-hidden="true" tabindex="-1"></a>   (stop-server (<span class="at">:server</span> system))</span>
<span id="cb47-4"><a href="#cb47-4" aria-hidden="true" tabindex="-1"></a>   (stop-connection-pool (<span class="at">:pool</span> system))</span>
<span id="cb47-5"><a href="#cb47-5" aria-hidden="true" tabindex="-1"></a>   <span class="co">;; In this hypothetical the sendgrid service</span></span>
<span id="cb47-6"><a href="#cb47-6" aria-hidden="true" tabindex="-1"></a>   <span class="co">;; has shutdown logic, but the wikipedia service does not.</span></span>
<span id="cb47-7"><a href="#cb47-7" aria-hidden="true" tabindex="-1"></a>   (stop-sendgrid-service (<span class="at">:sendgrid-service</span> system)))</span></code></pre></div>
<p>Then to facilitate working with the "current system" in the REPL it does need to be bound to some global value.</p>
<div class="sourceCode" id="cb48"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb48-1"><a href="#cb48-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">ns</span> example.<span class="kw">repl</span></span>
<span id="cb48-2"><a href="#cb48-2" aria-hidden="true" tabindex="-1"></a>   (<span class="at">:require</span> [example.system <span class="at">:as</span> system]))</span>
<span id="cb48-3"><a href="#cb48-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb48-4"><a href="#cb48-4" aria-hidden="true" tabindex="-1"></a>(<span class="bu">def</span><span class="fu"> system </span><span class="va">nil</span>)</span>
<span id="cb48-5"><a href="#cb48-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb48-6"><a href="#cb48-6" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> start-system!</span></span>
<span id="cb48-7"><a href="#cb48-7" aria-hidden="true" tabindex="-1"></a>   []</span>
<span id="cb48-8"><a href="#cb48-8" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">alter-var-root</span> <span class="va">#&#39;system</span> (<span class="kw">constantly</span> (system/start-system))))</span>
<span id="cb48-9"><a href="#cb48-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb48-10"><a href="#cb48-10" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> stop-system!</span></span>
<span id="cb48-11"><a href="#cb48-11" aria-hidden="true" tabindex="-1"></a>   []</span>
<span id="cb48-12"><a href="#cb48-12" aria-hidden="true" tabindex="-1"></a>   (system/stop-system system)</span>
<span id="cb48-13"><a href="#cb48-13" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">alter-var-root</span> <span class="va">#&#39;system</span> (<span class="kw">constantly</span> <span class="va">nil</span>)))</span>
<span id="cb48-14"><a href="#cb48-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb48-15"><a href="#cb48-15" aria-hidden="true" tabindex="-1"></a>(<span class="kw">comment</span></span>
<span id="cb48-16"><a href="#cb48-16" aria-hidden="true" tabindex="-1"></a>   (start-system!)</span>
<span id="cb48-17"><a href="#cb48-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb48-18"><a href="#cb48-18" aria-hidden="true" tabindex="-1"></a>   (stop-system!))</span></code></pre></div>
<p>A developer can then reference <code>example.repl/system</code> in their REPL session to see the currently running system and pull out values to test calls to functions they are playing with.</p>
<div class="sourceCode" id="cb49"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb49-1"><a href="#cb49-1" aria-hidden="true" tabindex="-1"></a>(some-db-function </span>
<span id="cb49-2"><a href="#cb49-2" aria-hidden="true" tabindex="-1"></a>   (<span class="at">:pool</span> example.repl/system) </span>
<span id="cb49-3"><a href="#cb49-3" aria-hidden="true" tabindex="-1"></a>   <span class="dv">123</span> </span>
<span id="cb49-4"><a href="#cb49-4" aria-hidden="true" tabindex="-1"></a>   <span class="st">&quot;abc&quot;</span>)</span></code></pre></div>
<p>And while this does give birth to a global stateful thing, the problems of that are fairly mitigated.</p>
<p>For one, it can reasonably exist only in development. In the code above there is a distinct namespace just for giving a <code>start-system!</code> and <code>stop-system!</code> to be used in development. On the tooling side you can even make sure this file isn't included in production builds with something like <a href="https://clojure.org/reference/deps_and_cli">deps.edn aliases.</a></p>
<div class="sourceCode" id="cb50"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb50-1"><a href="#cb50-1" aria-hidden="true" tabindex="-1"></a><span class="co">;; Assuming example/repl.clj is under dev-src</span></span>
<span id="cb50-2"><a href="#cb50-2" aria-hidden="true" tabindex="-1"></a>{<span class="at">:paths</span> [<span class="st">&quot;src&quot;</span>]</span>
<span id="cb50-3"><a href="#cb50-3" aria-hidden="true" tabindex="-1"></a> <span class="at">:aliases</span> {<span class="at">:dev</span> {<span class="at">:paths</span> [<span class="st">&quot;dev-src&quot;</span>]}}}</span></code></pre></div>
<h2 id="so-what-is-integrant-for">So what is integrant for?</h2>
<p>As I mentioned before, you need to start all of your stateful components in the right order and stop them all in the reverse of that order.</p>
<div class="sourceCode" id="cb51"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb51-1"><a href="#cb51-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> start-system</span></span>
<span id="cb51-2"><a href="#cb51-2" aria-hidden="true" tabindex="-1"></a>   []</span>
<span id="cb51-3"><a href="#cb51-3" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">let</span> [config            (load-config)</span>
<span id="cb51-4"><a href="#cb51-4" aria-hidden="true" tabindex="-1"></a>         sendgrid-service  (make-sendgrid-service config)</span>
<span id="cb51-5"><a href="#cb51-5" aria-hidden="true" tabindex="-1"></a>         wikipedia-service (make-wikipedia-service)</span>
<span id="cb51-6"><a href="#cb51-6" aria-hidden="true" tabindex="-1"></a>         pool              (make-pool config)</span>
<span id="cb51-7"><a href="#cb51-7" aria-hidden="true" tabindex="-1"></a>         system-so-far     {<span class="at">:config</span>            config</span>
<span id="cb51-8"><a href="#cb51-8" aria-hidden="true" tabindex="-1"></a>                            <span class="at">:sendgrid-service</span>  sendgrid-service</span>
<span id="cb51-9"><a href="#cb51-9" aria-hidden="true" tabindex="-1"></a>                            <span class="at">:wikipedia-service</span> wikipedia-service</span>
<span id="cb51-10"><a href="#cb51-10" aria-hidden="true" tabindex="-1"></a>                            <span class="at">:pool</span>              pool}</span>
<span id="cb51-11"><a href="#cb51-11" aria-hidden="true" tabindex="-1"></a>         server            (start-server system-so-far)]</span>
<span id="cb51-12"><a href="#cb51-12" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">assoc</span> system-so-far <span class="at">:server</span> server)))</span>
<span id="cb51-13"><a href="#cb51-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb51-14"><a href="#cb51-14" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> stop-system </span></span>
<span id="cb51-15"><a href="#cb51-15" aria-hidden="true" tabindex="-1"></a>   [system]</span>
<span id="cb51-16"><a href="#cb51-16" aria-hidden="true" tabindex="-1"></a>   (stop-server (<span class="at">:server</span> system))</span>
<span id="cb51-17"><a href="#cb51-17" aria-hidden="true" tabindex="-1"></a>   (stop-connection-pool (<span class="at">:pool</span> system))</span>
<span id="cb51-18"><a href="#cb51-18" aria-hidden="true" tabindex="-1"></a>   (stop-sendgrid-service (<span class="at">:sendgrid-service</span> system)))</span></code></pre></div>
<p>A workable metaphor for this is that each component "depends on" the components that need to start before it and that these dependencies form a graph.</p>
<p>Integrant, and libraries like it, provide ways to explicitly model that graph of dependencies.</p>
<p><img src="data:image/svg+xml;base64,PHN2ZyBpZD0ibXktc3ZnIiB3aWR0aD0iMTAwJSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgc3R5bGU9Im1heC13aWR0aDogNDE1LjUzMXB4OyBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsiIHZpZXdCb3g9Ii04IC04IDQxNS41MzEyNSAyNTMiIHJvbGU9ImdyYXBoaWNzLWRvY3VtZW50IGRvY3VtZW50IiBhcmlhLXJvbGVkZXNjcmlwdGlvbj0iZmxvd2NoYXJ0LXYyIj48c3R5bGU+I215LXN2Z3tmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjE2cHg7ZmlsbDojMzMzO30jbXktc3ZnIC5lcnJvci1pY29ue2ZpbGw6IzU1MjIyMjt9I215LXN2ZyAuZXJyb3ItdGV4dHtmaWxsOiM1NTIyMjI7c3Ryb2tlOiM1NTIyMjI7fSNteS1zdmcgLmVkZ2UtdGhpY2tuZXNzLW5vcm1hbHtzdHJva2Utd2lkdGg6MnB4O30jbXktc3ZnIC5lZGdlLXRoaWNrbmVzcy10aGlja3tzdHJva2Utd2lkdGg6My41cHg7fSNteS1zdmcgLmVkZ2UtcGF0dGVybi1zb2xpZHtzdHJva2UtZGFzaGFycmF5OjA7fSNteS1zdmcgLmVkZ2UtcGF0dGVybi1kYXNoZWR7c3Ryb2tlLWRhc2hhcnJheTozO30jbXktc3ZnIC5lZGdlLXBhdHRlcm4tZG90dGVke3N0cm9rZS1kYXNoYXJyYXk6Mjt9I215LXN2ZyAubWFya2Vye2ZpbGw6IzMzMzMzMztzdHJva2U6IzMzMzMzMzt9I215LXN2ZyAubWFya2VyLmNyb3Nze3N0cm9rZTojMzMzMzMzO30jbXktc3ZnIHN2Z3tmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjE2cHg7fSNteS1zdmcgLmxhYmVse2ZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjtjb2xvcjojMzMzO30jbXktc3ZnIC5jbHVzdGVyLWxhYmVsIHRleHR7ZmlsbDojMzMzO30jbXktc3ZnIC5jbHVzdGVyLWxhYmVsIHNwYW4sI215LXN2ZyBwe2NvbG9yOiMzMzM7fSNteS1zdmcgLmxhYmVsIHRleHQsI215LXN2ZyBzcGFuLCNteS1zdmcgcHtmaWxsOiMzMzM7Y29sb3I6IzMzMzt9I215LXN2ZyAubm9kZSByZWN0LCNteS1zdmcgLm5vZGUgY2lyY2xlLCNteS1zdmcgLm5vZGUgZWxsaXBzZSwjbXktc3ZnIC5ub2RlIHBvbHlnb24sI215LXN2ZyAubm9kZSBwYXRoe2ZpbGw6I0VDRUNGRjtzdHJva2U6IzkzNzBEQjtzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5mbG93Y2hhcnQtbGFiZWwgdGV4dHt0ZXh0LWFuY2hvcjptaWRkbGU7fSNteS1zdmcgLm5vZGUgLmthdGV4IHBhdGh7ZmlsbDojMDAwO3N0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxcHg7fSNteS1zdmcgLm5vZGUgLmxhYmVse3RleHQtYWxpZ246Y2VudGVyO30jbXktc3ZnIC5ub2RlLmNsaWNrYWJsZXtjdXJzb3I6cG9pbnRlcjt9I215LXN2ZyAuYXJyb3doZWFkUGF0aHtmaWxsOiMzMzMzMzM7fSNteS1zdmcgLmVkZ2VQYXRoIC5wYXRoe3N0cm9rZTojMzMzMzMzO3N0cm9rZS13aWR0aDoyLjBweDt9I215LXN2ZyAuZmxvd2NoYXJ0LWxpbmt7c3Ryb2tlOiMzMzMzMzM7ZmlsbDpub25lO30jbXktc3ZnIC5lZGdlTGFiZWx7YmFja2dyb3VuZC1jb2xvcjojZThlOGU4O3RleHQtYWxpZ246Y2VudGVyO30jbXktc3ZnIC5lZGdlTGFiZWwgcmVjdHtvcGFjaXR5OjAuNTtiYWNrZ3JvdW5kLWNvbG9yOiNlOGU4ZTg7ZmlsbDojZThlOGU4O30jbXktc3ZnIC5sYWJlbEJrZ3tiYWNrZ3JvdW5kLWNvbG9yOnJnYmEoMjMyLCAyMzIsIDIzMiwgMC41KTt9I215LXN2ZyAuY2x1c3RlciByZWN0e2ZpbGw6I2ZmZmZkZTtzdHJva2U6I2FhYWEzMztzdHJva2Utd2lkdGg6MXB4O30jbXktc3ZnIC5jbHVzdGVyIHRleHR7ZmlsbDojMzMzO30jbXktc3ZnIC5jbHVzdGVyIHNwYW4sI215LXN2ZyBwe2NvbG9yOiMzMzM7fSNteS1zdmcgZGl2Lm1lcm1haWRUb29sdGlwe3Bvc2l0aW9uOmFic29sdXRlO3RleHQtYWxpZ246Y2VudGVyO21heC13aWR0aDoyMDBweDtwYWRkaW5nOjJweDtmb250LWZhbWlseToidHJlYnVjaGV0IG1zIix2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjEycHg7YmFja2dyb3VuZDpoc2woODAsIDEwMCUsIDk2LjI3NDUwOTgwMzklKTtib3JkZXI6MXB4IHNvbGlkICNhYWFhMzM7Ym9yZGVyLXJhZGl1czoycHg7cG9pbnRlci1ldmVudHM6bm9uZTt6LWluZGV4OjEwMDt9I215LXN2ZyAuZmxvd2NoYXJ0VGl0bGVUZXh0e3RleHQtYW5jaG9yOm1pZGRsZTtmb250LXNpemU6MThweDtmaWxsOiMzMzM7fSNteS1zdmcgOnJvb3R7LS1tZXJtYWlkLWZvbnQtZmFtaWx5OiJ0cmVidWNoZXQgbXMiLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJpZjt9PC9zdHlsZT48Zz48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LXBvaW50RW5kIiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI2IiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMiIgbWFya2VySGVpZ2h0PSIxMiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNIDAgMCBMIDEwIDUgTCAwIDEwIHoiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1wb2ludFN0YXJ0IiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI0LjUiIHJlZlk9IjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjEyIiBtYXJrZXJIZWlnaHQ9IjEyIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMCA1IEwgMTAgMTAgTCAxMCAwIHoiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jaXJjbGVFbmQiIGNsYXNzPSJtYXJrZXIgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjExIiByZWZZPSI1IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIxMSIgbWFya2VySGVpZ2h0PSIxMSIgb3JpZW50PSJhdXRvIj48Y2lyY2xlIGN4PSI1IiBjeT0iNSIgcj0iNSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNpcmNsZVN0YXJ0IiBjbGFzcz0ibWFya2VyIGZsb3djaGFydCIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSItMSIgcmVmWT0iNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PGNpcmNsZSBjeD0iNSIgY3k9IjUiIHI9IjUiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PG1hcmtlciBpZD0ibXktc3ZnX2Zsb3djaGFydC1jcm9zc0VuZCIgY2xhc3M9Im1hcmtlciBjcm9zcyBmbG93Y2hhcnQiIHZpZXdCb3g9IjAgMCAxMSAxMSIgcmVmWD0iMTIiIHJlZlk9IjUuMiIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMTEiIG1hcmtlckhlaWdodD0iMTEiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTSAxLDEgbCA5LDkgTSAxMCwxIGwgLTksOSIgY2xhc3M9ImFycm93TWFya2VyUGF0aCIgc3R5bGU9InN0cm9rZS13aWR0aDogMjsgc3Ryb2tlLWRhc2hhcnJheTogMSwgMDsiLz48L21hcmtlcj48bWFya2VyIGlkPSJteS1zdmdfZmxvd2NoYXJ0LWNyb3NzU3RhcnQiIGNsYXNzPSJtYXJrZXIgY3Jvc3MgZmxvd2NoYXJ0IiB2aWV3Qm94PSIwIDAgMTEgMTEiIHJlZlg9Ii0xIiByZWZZPSI1LjIiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjExIiBtYXJrZXJIZWlnaHQ9IjExIiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0gMSwxIGwgOSw5IE0gMTAsMSBsIC05LDkiIGNsYXNzPSJhcnJvd01hcmtlclBhdGgiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDI7IHN0cm9rZS1kYXNoYXJyYXk6IDEsIDA7Ii8+PC9tYXJrZXI+PGcgY2xhc3M9InJvb3QiPjxnIGNsYXNzPSJjbHVzdGVycyIvPjxnIGNsYXNzPSJlZGdlUGF0aHMiPjxwYXRoIGQ9Ik00Ni43NTgsMTY4TDU0LjY5MSwxNTYuODMzQzYyLjYyNSwxNDUuNjY3LDc4LjQ5MiwxMjMuMzMzLDkwLjE5NSwxMTIuMTY3QzEwMS44OTcsMTAxLDEwOS40MzUsMTAxLDExMy4yMDQsMTAxTDExNi45NzMsMTAxIiBpZD0iTC1BLUItMCIgY2xhc3M9ImVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtQSBMRS1CIiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLWVuZD0idXJsKCNteS1zdmdfZmxvd2NoYXJ0LXBvaW50RW5kKSIvPjxwYXRoIGQ9Ik0yNzguNDg0LDE3TDI4Mi42NTEsMTdDMjg2LjgxOCwxNywyOTUuMTUxLDE3LDMwNy42NjIsMzQuMzdDMzIwLjE3Miw1MS43NDEsMzM2Ljg2LDg2LjQ4MiwzNDUuMjAzLDEwMy44NTJMMzUzLjU0NywxMjEuMjIzIiBpZD0iTC1ELUMtMCIgY2xhc3M9ImVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtRCBMRS1DIiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLWVuZD0idXJsKCNteS1zdmdfZmxvd2NoYXJ0LXBvaW50RW5kKSIvPjxwYXRoIGQ9Ik0yNzUuNTcsMTAxTDI4MC4yMjMsMTAxQzI4NC44NzUsMTAxLDI5NC4xOCwxMDEsMzA0LjExMSwxMDQuNjYzQzMxNC4wNDIsMTA4LjMyNiwzMjQuNTk5LDExNS42NTIsMzI5Ljg3NywxMTkuMzE1TDMzNS4xNTYsMTIyLjk3OCIgaWQ9IkwtQi1DLTAiIGNsYXNzPSJlZGdlLXRoaWNrbmVzcy1ub3JtYWwgZWRnZS1wYXR0ZXJuLXNvbGlkIGZsb3djaGFydC1saW5rIExTLUIgTEUtQyIgc3R5bGU9ImZpbGw6bm9uZTsiIG1hcmtlci1lbmQ9InVybCgjbXktc3ZnX2Zsb3djaGFydC1wb2ludEVuZCkiLz48cGF0aCBkPSJNNjkuMzU5LDE4NUw3My41MjYsMTg1Qzc3LjY5MywxODUsODYuMDI2LDE4NSwxMDIuMTg4LDE4NUMxMTguMzUxLDE4NSwxNDIuMzQyLDE4NSwxNTQuMzM3LDE4NUwxNjYuMzMzLDE4NSIgaWQ9IkwtQS1FLTAiIGNsYXNzPSJlZGdlLXRoaWNrbmVzcy1ub3JtYWwgZWRnZS1wYXR0ZXJuLXNvbGlkIGZsb3djaGFydC1saW5rIExTLUEgTEUtRSIgc3R5bGU9ImZpbGw6bm9uZTsiIG1hcmtlci1lbmQ9InVybCgjbXktc3ZnX2Zsb3djaGFydC1wb2ludEVuZCkiLz48cGF0aCBkPSJNMjI2LjIxMSwxODVMMjM5LjA5LDE4NUMyNTEuOTY5LDE4NSwyNzcuNzI3LDE4NSwyOTUuODg0LDE4MS4zMzdDMzE0LjA0MiwxNzcuNjc0LDMyNC41OTksMTcwLjM0OCwzMjkuODc3LDE2Ni42ODVMMzM1LjE1NiwxNjMuMDIyIiBpZD0iTC1FLUMtMCIgY2xhc3M9ImVkZ2UtdGhpY2tuZXNzLW5vcm1hbCBlZGdlLXBhdHRlcm4tc29saWQgZmxvd2NoYXJ0LWxpbmsgTFMtRSBMRS1DIiBzdHlsZT0iZmlsbDpub25lOyIgbWFya2VyLWVuZD0idXJsKCNteS1zdmdfZmxvd2NoYXJ0LXBvaW50RW5kKSIvPjxwYXRoIGQ9Ik01NC4xOSwyMDJMNjAuODg1LDIwNy44MzNDNjcuNTgsMjEzLjY2Nyw4MC45NywyMjUuMzMzLDEwNS4wOTIsMjMxLjE2N0MxMjkuMjE0LDIzNywxNjQuMDY4LDIzNywxOTguOTIyLDIzN0MyMzMuNzc2LDIzNywyNjguNjMsMjM3LDI5My44NDIsMjI0LjkwOUMzMTkuMDU0LDIxMi44MTksMzM0LjYyMywxODguNjM3LDM0Mi40MDgsMTc2LjU0N0wzNTAuMTkzLDE2NC40NTYiIGlkPSJMLUEtQy0wIiBjbGFzcz0iZWRnZS10aGlja25lc3Mtbm9ybWFsIGVkZ2UtcGF0dGVybi1zb2xpZCBmbG93Y2hhcnQtbGluayBMUy1BIExFLUMiIHN0eWxlPSJmaWxsOm5vbmU7IiBtYXJrZXItZW5kPSJ1cmwoI215LXN2Z19mbG93Y2hhcnQtcG9pbnRFbmQpIi8+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWxzIj48ZyBjbGFzcz0iZWRnZUxhYmVsIj48ZyBjbGFzcz0ibGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsIDApIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMCIgaGVpZ2h0PSIwIj48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9ImVkZ2VMYWJlbCI+PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWwiPjxnIGNsYXNzPSJsYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMCkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIwIiBoZWlnaHQ9IjAiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0iZWRnZUxhYmVsIj48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbCI+PGcgY2xhc3M9ImxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAwKSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjAiIGhlaWdodD0iMCI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0iZWRnZUxhYmVsIj48ZyBjbGFzcz0ibGFiZWwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsIDApIj48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMCIgaGVpZ2h0PSIwIj48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9ImVkZ2VMYWJlbCI+PC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJlZGdlTGFiZWwiPjxnIGNsYXNzPSJsYWJlbCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMCkiPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIwIiBoZWlnaHQ9IjAiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0iZWRnZUxhYmVsIj48L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9ImVkZ2VMYWJlbCI+PGcgY2xhc3M9ImxhYmVsIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAwKSI+PGZvcmVpZ25PYmplY3Qgd2lkdGg9IjAiIGhlaWdodD0iMCI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJlZGdlTGFiZWwiPjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48L2c+PGcgY2xhc3M9Im5vZGVzIj48ZyBjbGFzcz0ibm9kZSBkZWZhdWx0IGRlZmF1bHQgZmxvd2NoYXJ0LWxhYmVsIiBpZD0iZmxvd2NoYXJ0LUEtMCIgZGF0YS1ub2RlPSJ0cnVlIiBkYXRhLWlkPSJBIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzNC42Nzk2ODc1LCAxODUpIj48cmVjdCBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIiBzdHlsZT0iIiByeD0iMCIgcnk9IjAiIHg9Ii0zNC42Nzk2ODc1IiB5PSItMTciIHdpZHRoPSI2OS4zNTkzNzUiIGhlaWdodD0iMzQiLz48ZyBjbGFzcz0ibGFiZWwiIHN0eWxlPSIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yNy4xNzk2ODc1LCAtOS41KSI+PHJlY3QvPjxmb3JlaWduT2JqZWN0IHdpZHRoPSI1NC4zNTkzNzUiIGhlaWdodD0iMTkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj46Y29uZmlnPC9zcGFuPjwvZGl2PjwvZm9yZWlnbk9iamVjdD48L2c+PC9nPjxnIGNsYXNzPSJub2RlIGRlZmF1bHQgZGVmYXVsdCBmbG93Y2hhcnQtbGFiZWwiIGlkPSJmbG93Y2hhcnQtQi0xIiBkYXRhLW5vZGU9InRydWUiIGRhdGEtaWQ9IkIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE5OC45MjE4NzUsIDEwMSkiPjxyZWN0IGNsYXNzPSJiYXNpYyBsYWJlbC1jb250YWluZXIiIHN0eWxlPSIiIHJ4PSIwIiByeT0iMCIgeD0iLTc2LjY0ODQzNzUiIHk9Ii0xNyIgd2lkdGg9IjE1My4yOTY4NzUiIGhlaWdodD0iMzQiLz48ZyBjbGFzcz0ibGFiZWwiIHN0eWxlPSIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC02OS4xNDg0Mzc1LCAtOS41KSI+PHJlY3QvPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIxMzguMjk2ODc1IiBoZWlnaHQ9IjE5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+OnNlbmRncmlkLXNlcnZpY2U8L3NwYW4+PC9kaXY+PC9mb3JlaWduT2JqZWN0PjwvZz48L2c+PGcgY2xhc3M9Im5vZGUgZGVmYXVsdCBkZWZhdWx0IGZsb3djaGFydC1sYWJlbCIgaWQ9ImZsb3djaGFydC1ELTIiIGRhdGEtbm9kZT0idHJ1ZSIgZGF0YS1pZD0iRCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTk4LjkyMTg3NSwgMTcpIj48cmVjdCBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIiBzdHlsZT0iIiByeD0iMCIgcnk9IjAiIHg9Ii03OS41NjI1IiB5PSItMTciIHdpZHRoPSIxNTkuMTI1IiBoZWlnaHQ9IjM0Ii8+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNzIuMDYyNSwgLTkuNSkiPjxyZWN0Lz48Zm9yZWlnbk9iamVjdCB3aWR0aD0iMTQ0LjEyNSIgaGVpZ2h0PSIxOSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxzcGFuIGNsYXNzPSJub2RlTGFiZWwiPjp3aWtpcGVkaWEtc2VydmljZTwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0ibm9kZSBkZWZhdWx0IGRlZmF1bHQgZmxvd2NoYXJ0LWxhYmVsIiBpZD0iZmxvd2NoYXJ0LUMtMyIgZGF0YS1ub2RlPSJ0cnVlIiBkYXRhLWlkPSJDIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzNjQuMDA3ODEyNSwgMTQzKSI+PHJlY3QgY2xhc3M9ImJhc2ljIGxhYmVsLWNvbnRhaW5lciIgc3R5bGU9IiIgcng9IjAiIHJ5PSIwIiB4PSItMzUuNTIzNDM3NSIgeT0iLTE3IiB3aWR0aD0iNzEuMDQ2ODc1IiBoZWlnaHQ9IjM0Ii8+PGcgY2xhc3M9ImxhYmVsIiBzdHlsZT0iIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMjguMDIzNDM3NSwgLTkuNSkiPjxyZWN0Lz48Zm9yZWlnbk9iamVjdCB3aWR0aD0iNTYuMDQ2ODc1IiBoZWlnaHQ9IjE5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aGl0ZS1zcGFjZTogbm93cmFwOyI+PHNwYW4gY2xhc3M9Im5vZGVMYWJlbCI+OnNlcnZlcjwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48ZyBjbGFzcz0ibm9kZSBkZWZhdWx0IGRlZmF1bHQgZmxvd2NoYXJ0LWxhYmVsIiBpZD0iZmxvd2NoYXJ0LUUtNyIgZGF0YS1ub2RlPSJ0cnVlIiBkYXRhLWlkPSJFIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxOTguOTIxODc1LCAxODUpIj48cmVjdCBjbGFzcz0iYmFzaWMgbGFiZWwtY29udGFpbmVyIiBzdHlsZT0iIiByeD0iMCIgcnk9IjAiIHg9Ii0yNy4yODkwNjI1IiB5PSItMTciIHdpZHRoPSI1NC41NzgxMjUiIGhlaWdodD0iMzQiLz48ZyBjbGFzcz0ibGFiZWwiIHN0eWxlPSIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xOS43ODkwNjI1LCAtOS41KSI+PHJlY3QvPjxmb3JlaWduT2JqZWN0IHdpZHRoPSIzOS41NzgxMjUiIGhlaWdodD0iMTkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdoaXRlLXNwYWNlOiBub3dyYXA7Ij48c3BhbiBjbGFzcz0ibm9kZUxhYmVsIj46cG9vbDwvc3Bhbj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PC9nPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=" alt="" /></p>
<p>This reduces boilerplate and potential error-prone-ness with the <code>start-system</code> and <code>stop-system</code> functions that logically need to exist.</p>
<p>In Integrant's case the dependency information is encoded into a map</p>
<div class="sourceCode" id="cb52"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb52-1"><a href="#cb52-1" aria-hidden="true" tabindex="-1"></a>{<span class="at">:config</span>            {}</span>
<span id="cb52-2"><a href="#cb52-2" aria-hidden="true" tabindex="-1"></a> <span class="at">:sendgrid-service</span>  {<span class="at">:config</span> (ig/ref <span class="at">:config</span>)}</span>
<span id="cb52-3"><a href="#cb52-3" aria-hidden="true" tabindex="-1"></a> <span class="at">:wikipedia-service</span> {}</span>
<span id="cb52-4"><a href="#cb52-4" aria-hidden="true" tabindex="-1"></a> <span class="at">:pool</span>              {<span class="at">:config</span> (ig/ref <span class="at">:config</span>)}</span>
<span id="cb52-5"><a href="#cb52-5" aria-hidden="true" tabindex="-1"></a> <span class="at">:server</span>            {<span class="at">:config</span>            (ig/ref <span class="at">:config</span>)</span>
<span id="cb52-6"><a href="#cb52-6" aria-hidden="true" tabindex="-1"></a>                     <span class="at">:sendgrid-service</span>  (ig/ref <span class="at">:sendgrid-service</span>)</span>
<span id="cb52-7"><a href="#cb52-7" aria-hidden="true" tabindex="-1"></a>                     <span class="at">:wikipedia-service</span> (ig/ref <span class="at">:wikipedia-service</span>)}}</span></code></pre></div>
<p>and the information about how each thing is started and stopped is registered with the <code>ig/init-key</code> and <code>ig/halt-key</code> multimethods.</p>
<div class="sourceCode" id="cb53"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb53-1"><a href="#cb53-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defmethod</span><span class="fu"> ig/init-key</span></span>
<span id="cb53-2"><a href="#cb53-2" aria-hidden="true" tabindex="-1"></a>  <span class="at">:pool</span></span>
<span id="cb53-3"><a href="#cb53-3" aria-hidden="true" tabindex="-1"></a>  [_ {<span class="at">:keys</span> [config]}]</span>
<span id="cb53-4"><a href="#cb53-4" aria-hidden="true" tabindex="-1"></a>  (HikariDataSource.</span>
<span id="cb53-5"><a href="#cb53-5" aria-hidden="true" tabindex="-1"></a>    (<span class="kw">doto</span> (HikariConfig.)</span>
<span id="cb53-6"><a href="#cb53-6" aria-hidden="true" tabindex="-1"></a>      (.setJdbcUrl (config/lookup config <span class="at">:JDBC</span>_URL)))))</span>
<span id="cb53-7"><a href="#cb53-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb53-8"><a href="#cb53-8" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defmethod</span><span class="fu"> ig/halt-key!</span></span>
<span id="cb53-9"><a href="#cb53-9" aria-hidden="true" tabindex="-1"></a>  <span class="at">:pool</span></span>
<span id="cb53-10"><a href="#cb53-10" aria-hidden="true" tabindex="-1"></a>  [_ pool]</span>
<span id="cb53-11"><a href="#cb53-11" aria-hidden="true" tabindex="-1"></a>  (.close pool))</span></code></pre></div>
<p>Starting the system now means calling <code>ig/init-key</code> on everything in graph traversal order and calling <code>ig/halt-key</code> in the reverse order.</p>
<p>The pieces needed for a REPL workflow can then be brought in <a href="https://github.com/weavejester/integrant-repl">via a library.</a></p>
<p>Partially because multimethod registration is global - and partially because its good practice regardless - the keys for different integrant components are generally made namespaced.</p>
<div class="sourceCode" id="cb54"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb54-1"><a href="#cb54-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">ns</span> example.system</span>
<span id="cb54-2"><a href="#cb54-2" aria-hidden="true" tabindex="-1"></a>  (<span class="at">:require</span> [integrant.core <span class="at">:as</span> ig]))</span>
<span id="cb54-3"><a href="#cb54-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb54-4"><a href="#cb54-4" aria-hidden="true" tabindex="-1"></a>(<span class="bu">def</span><span class="fu"> system-map</span></span>
<span id="cb54-5"><a href="#cb54-5" aria-hidden="true" tabindex="-1"></a>    {<span class="at">::config</span>            {}</span>
<span id="cb54-6"><a href="#cb54-6" aria-hidden="true" tabindex="-1"></a>     <span class="at">::sendgrid-service</span>  {<span class="at">::config</span> (ig/ref <span class="at">::config</span>)}</span>
<span id="cb54-7"><a href="#cb54-7" aria-hidden="true" tabindex="-1"></a>     <span class="at">::wikipedia-service</span> {}</span>
<span id="cb54-8"><a href="#cb54-8" aria-hidden="true" tabindex="-1"></a>     <span class="at">::pool</span>              {<span class="at">::config</span> (ig/ref <span class="at">::config</span>)}</span>
<span id="cb54-9"><a href="#cb54-9" aria-hidden="true" tabindex="-1"></a>     <span class="at">::server</span>            </span>
<span id="cb54-10"><a href="#cb54-10" aria-hidden="true" tabindex="-1"></a>     {<span class="at">::config</span>            (ig/ref <span class="at">::config</span>)</span>
<span id="cb54-11"><a href="#cb54-11" aria-hidden="true" tabindex="-1"></a>      <span class="at">::sendgrid-service</span>  (ig/ref <span class="at">::sendgrid-service</span>)</span>
<span id="cb54-12"><a href="#cb54-12" aria-hidden="true" tabindex="-1"></a>      <span class="at">::wikipedia-service</span> (ig/ref <span class="at">::wikipedia-service</span>)}})</span></code></pre></div>
<p>So in this context, the <code>::pool</code> syntax will expand to <code>:example.system/pool</code>.</p>
<p>This helps avoid conflicts with multimethod registration, but also can be used in conjunction with features like <a href="https://clojure.atlassian.net/browse/CLJ-2123"><code>as-alias</code></a> to add some semantic and syntactic distinction to pulling components out of the system.</p>
<div class="sourceCode" id="cb55"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb55-1"><a href="#cb55-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">ns</span> example.handlers</span>
<span id="cb55-2"><a href="#cb55-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">;; Without as-alias it would be really easy</span></span>
<span id="cb55-3"><a href="#cb55-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">;; to get circular dependencies doing this.</span></span>
<span id="cb55-4"><a href="#cb55-4" aria-hidden="true" tabindex="-1"></a>  (<span class="at">:require</span> [example.system <span class="at">:as-alias</span> system]))</span>
<span id="cb55-5"><a href="#cb55-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb55-6"><a href="#cb55-6" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> some-handler</span></span>
<span id="cb55-7"><a href="#cb55-7" aria-hidden="true" tabindex="-1"></a>  [{<span class="at">::system/keys</span> [pool server]} request]</span>
<span id="cb55-8"><a href="#cb55-8" aria-hidden="true" tabindex="-1"></a>  ...)</span></code></pre></div>
<p>Again, I find it important to note that integrant is just one of many libraries that do this "automatic wiring."</p>
<p>Many have sprung up over the years, and it seems like there are more yet to come. There are tradeoffs and quirks to all of them.</p>
<p>The important idea is just to pass things down as arguments and to start with the system maps at entry-points.</p>
<h2 id="tying-it-all-together">Tying it all together</h2>
<p>To properly structure a Clojure App</p>
<ul>
<li><strong>DO NOT</strong> have stateful components be implicit</li>
</ul>
<div class="sourceCode" id="cb56"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb56-1"><a href="#cb56-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> do-thing</span></span>
<span id="cb56-2"><a href="#cb56-2" aria-hidden="true" tabindex="-1"></a>  [<span class="kw">name</span>]</span>
<span id="cb56-3"><a href="#cb56-3" aria-hidden="true" tabindex="-1"></a>  (<span class="kw">slurp</span> (<span class="kw">str</span> <span class="st">&quot;https://website.com/get-info/&quot;</span> <span class="kw">name</span>)))</span></code></pre></div>
<ul>
<li><strong>DO NOT</strong> have stateful components be global constants</li>
</ul>
<div class="sourceCode" id="cb57"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb57-1"><a href="#cb57-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">def</span><span class="fu"> pool </span>(make-db-pool))</span>
<span id="cb57-2"><a href="#cb57-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb57-3"><a href="#cb57-3" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> lookup-chair </span></span>
<span id="cb57-4"><a href="#cb57-4" aria-hidden="true" tabindex="-1"></a>  [chair-id]</span>
<span id="cb57-5"><a href="#cb57-5" aria-hidden="true" tabindex="-1"></a>  (jdbc/execute! </span>
<span id="cb57-6"><a href="#cb57-6" aria-hidden="true" tabindex="-1"></a>    pool </span>
<span id="cb57-7"><a href="#cb57-7" aria-hidden="true" tabindex="-1"></a>    [<span class="st">&quot;SELECT * FROM chair</span></span>
<span id="cb57-8"><a href="#cb57-8" aria-hidden="true" tabindex="-1"></a><span class="st">      WHERE chair.chair_id = ?&quot;</span>]))</span></code></pre></div>
<ul>
<li><strong>DO</strong> have code be safe to reload in the REPL and have changes be reflected immediately</li>
</ul>
<div class="sourceCode" id="cb58"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb58-1"><a href="#cb58-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> root-handler</span></span>
<span id="cb58-2"><a href="#cb58-2" aria-hidden="true" tabindex="-1"></a>  [request]</span>
<span id="cb58-3"><a href="#cb58-3" aria-hidden="true" tabindex="-1"></a>  ...)</span>
<span id="cb58-4"><a href="#cb58-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb58-5"><a href="#cb58-5" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> start-server </span></span>
<span id="cb58-6"><a href="#cb58-6" aria-hidden="true" tabindex="-1"></a>  []</span>
<span id="cb58-7"><a href="#cb58-7" aria-hidden="true" tabindex="-1"></a>  (jetty/run-server <span class="va">#&#39;root-handler</span> {<span class="at">:port</span> <span class="dv">1234</span>}))</span></code></pre></div>
<ul>
<li><strong>DO</strong> provide REPL workflow helpers in comments</li>
</ul>
<div class="sourceCode" id="cb59"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb59-1"><a href="#cb59-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> root-handler</span></span>
<span id="cb59-2"><a href="#cb59-2" aria-hidden="true" tabindex="-1"></a>  [request]</span>
<span id="cb59-3"><a href="#cb59-3" aria-hidden="true" tabindex="-1"></a>  ...)</span>
<span id="cb59-4"><a href="#cb59-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb59-5"><a href="#cb59-5" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> start-server </span></span>
<span id="cb59-6"><a href="#cb59-6" aria-hidden="true" tabindex="-1"></a>  []</span>
<span id="cb59-7"><a href="#cb59-7" aria-hidden="true" tabindex="-1"></a>  ...)</span>
<span id="cb59-8"><a href="#cb59-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb59-9"><a href="#cb59-9" aria-hidden="true" tabindex="-1"></a>(<span class="kw">comment</span></span>
<span id="cb59-10"><a href="#cb59-10" aria-hidden="true" tabindex="-1"></a>  (start-server))</span></code></pre></div>
<ul>
<li><strong>DO</strong> pass stateful components explicitly as arguments.</li>
</ul>
<div class="sourceCode" id="cb60"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb60-1"><a href="#cb60-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> lookup-chair </span></span>
<span id="cb60-2"><a href="#cb60-2" aria-hidden="true" tabindex="-1"></a>  [pool chair-id]</span>
<span id="cb60-3"><a href="#cb60-3" aria-hidden="true" tabindex="-1"></a>  (jdbc/execute! </span>
<span id="cb60-4"><a href="#cb60-4" aria-hidden="true" tabindex="-1"></a>    pool </span>
<span id="cb60-5"><a href="#cb60-5" aria-hidden="true" tabindex="-1"></a>    [<span class="st">&quot;SELECT * FROM chair</span></span>
<span id="cb60-6"><a href="#cb60-6" aria-hidden="true" tabindex="-1"></a><span class="st">      WHERE chair.chair_id = ?&quot;</span>]))</span></code></pre></div>
<ul>
<li><strong>DO</strong> have a "system map" which can be threaded to entry-points</li>
</ul>
<div class="sourceCode" id="cb61"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb61-1"><a href="#cb61-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> start-system</span></span>
<span id="cb61-2"><a href="#cb61-2" aria-hidden="true" tabindex="-1"></a>  []</span>
<span id="cb61-3"><a href="#cb61-3" aria-hidden="true" tabindex="-1"></a>  (<span class="kw">let</span> [config            (load-config)</span>
<span id="cb61-4"><a href="#cb61-4" aria-hidden="true" tabindex="-1"></a>        sendgrid-service  (make-sendgrid-service config)</span>
<span id="cb61-5"><a href="#cb61-5" aria-hidden="true" tabindex="-1"></a>        wikipedia-service (make-wikipedia-service)</span>
<span id="cb61-6"><a href="#cb61-6" aria-hidden="true" tabindex="-1"></a>        pool              (make-pool config)</span>
<span id="cb61-7"><a href="#cb61-7" aria-hidden="true" tabindex="-1"></a>        system-so-far     {<span class="at">:config</span>            config</span>
<span id="cb61-8"><a href="#cb61-8" aria-hidden="true" tabindex="-1"></a>                           <span class="at">:sendgrid-service</span>  sendgrid-service</span>
<span id="cb61-9"><a href="#cb61-9" aria-hidden="true" tabindex="-1"></a>                           <span class="at">:wikipedia-service</span> wikipedia-service</span>
<span id="cb61-10"><a href="#cb61-10" aria-hidden="true" tabindex="-1"></a>                           <span class="at">:pool</span>              pool}</span>
<span id="cb61-11"><a href="#cb61-11" aria-hidden="true" tabindex="-1"></a>        server            (start-server system-so-far)]</span>
<span id="cb61-12"><a href="#cb61-12" aria-hidden="true" tabindex="-1"></a>    (<span class="kw">assoc</span> system-so-far <span class="at">:server</span> server)))</span></code></pre></div>
<ul>
<li><strong>DO</strong> have REPL helpers for working with the system.</li>
</ul>
<div class="sourceCode" id="cb62"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb62-1"><a href="#cb62-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">def</span><span class="fu"> system </span><span class="va">nil</span>)</span>
<span id="cb62-2"><a href="#cb62-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb62-3"><a href="#cb62-3" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> start-system! </span></span>
<span id="cb62-4"><a href="#cb62-4" aria-hidden="true" tabindex="-1"></a>  []</span>
<span id="cb62-5"><a href="#cb62-5" aria-hidden="true" tabindex="-1"></a>  (<span class="kw">alter-var-root</span> <span class="va">#&#39;system</span> ...))</span>
<span id="cb62-6"><a href="#cb62-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb62-7"><a href="#cb62-7" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> stop-system!</span></span>
<span id="cb62-8"><a href="#cb62-8" aria-hidden="true" tabindex="-1"></a>  []</span>
<span id="cb62-9"><a href="#cb62-9" aria-hidden="true" tabindex="-1"></a>  (<span class="kw">alter-var-root</span> <span class="va">#&#39;system</span> ...))</span>
<span id="cb62-10"><a href="#cb62-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb62-11"><a href="#cb62-11" aria-hidden="true" tabindex="-1"></a>(<span class="kw">comment</span></span>
<span id="cb62-12"><a href="#cb62-12" aria-hidden="true" tabindex="-1"></a>  (start-system!)</span>
<span id="cb62-13"><a href="#cb62-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb62-14"><a href="#cb62-14" aria-hidden="true" tabindex="-1"></a>  (stop-system!))</span></code></pre></div>
<ul>
<li><strong>DO</strong> pull out dependencies from the system using destructuring</li>
</ul>
<div class="sourceCode" id="cb63"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb63-1"><a href="#cb63-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> hello-handler </span></span>
<span id="cb63-2"><a href="#cb63-2" aria-hidden="true" tabindex="-1"></a>  [{<span class="at">:keys</span> [pool]} request]</span>
<span id="cb63-3"><a href="#cb63-3" aria-hidden="true" tabindex="-1"></a>  ...)</span></code></pre></div>
<ul>
<li><strong>DO</strong> use namespaced keys in the "system map"</li>
</ul>
<div class="sourceCode" id="cb64"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb64-1"><a href="#cb64-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">ns</span> example.system)</span>
<span id="cb64-2"><a href="#cb64-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb64-3"><a href="#cb64-3" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> start-system</span></span>
<span id="cb64-4"><a href="#cb64-4" aria-hidden="true" tabindex="-1"></a>  []</span>
<span id="cb64-5"><a href="#cb64-5" aria-hidden="true" tabindex="-1"></a>  (<span class="kw">let</span> [config            (load-config)</span>
<span id="cb64-6"><a href="#cb64-6" aria-hidden="true" tabindex="-1"></a>        sendgrid-service  (make-sendgrid-service config)</span>
<span id="cb64-7"><a href="#cb64-7" aria-hidden="true" tabindex="-1"></a>        wikipedia-service (make-wikipedia-service)</span>
<span id="cb64-8"><a href="#cb64-8" aria-hidden="true" tabindex="-1"></a>        pool              (make-pool config)</span>
<span id="cb64-9"><a href="#cb64-9" aria-hidden="true" tabindex="-1"></a>        system-so-far     {<span class="at">::config</span>            config</span>
<span id="cb64-10"><a href="#cb64-10" aria-hidden="true" tabindex="-1"></a>                           <span class="at">::sendgrid-service</span>  sendgrid-service</span>
<span id="cb64-11"><a href="#cb64-11" aria-hidden="true" tabindex="-1"></a>                           <span class="at">::wikipedia-service</span> wikipedia-service</span>
<span id="cb64-12"><a href="#cb64-12" aria-hidden="true" tabindex="-1"></a>                           <span class="at">::pool</span>              pool}</span>
<span id="cb64-13"><a href="#cb64-13" aria-hidden="true" tabindex="-1"></a>        server            (start-server system-so-far)]</span>
<span id="cb64-14"><a href="#cb64-14" aria-hidden="true" tabindex="-1"></a>    (<span class="kw">assoc</span> system-so-far <span class="at">::server</span> server)))</span></code></pre></div>
<div class="sourceCode" id="cb65"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb65-1"><a href="#cb65-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">ns</span> example.handlers</span>
<span id="cb65-2"><a href="#cb65-2" aria-hidden="true" tabindex="-1"></a>  (<span class="at">:require</span> [example.system <span class="at">:as-alias</span> system]))</span>
<span id="cb65-3"><a href="#cb65-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb65-4"><a href="#cb65-4" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> hello-handler </span></span>
<span id="cb65-5"><a href="#cb65-5" aria-hidden="true" tabindex="-1"></a>  [{<span class="at">::system/keys</span> [pool]} request]</span>
<span id="cb65-6"><a href="#cb65-6" aria-hidden="true" tabindex="-1"></a>  ...)</span></code></pre></div>
<ul>
<li><strong>MAYBE</strong> use a library like integrant to reduce boilerplate when starting and stopping the system.</li>
</ul>
<hr />
<details>
  <summary>Sidenotes</summary>

<h3 id="different-places-of-injection">Different Places of Injection</h3>
<p>A technique that was harder to show with how the code examples built up but is equally valid is attaching the system as "request context."</p>
<p>By this I mean, have some middleware which takes the system and a handler and injects the system into the request under some key.</p>
<div class="sourceCode" id="cb66"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb66-1"><a href="#cb66-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> wrap-system</span></span>
<span id="cb66-2"><a href="#cb66-2" aria-hidden="true" tabindex="-1"></a>   [system handler]</span>
<span id="cb66-3"><a href="#cb66-3" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">fn</span> [request]</span>
<span id="cb66-4"><a href="#cb66-4" aria-hidden="true" tabindex="-1"></a>      (handler (<span class="kw">assoc</span> request <span class="at">:system</span> system))))</span></code></pre></div>
<p>And then have entry-points pull what they need out from that nested key.</p>
<div class="sourceCode" id="cb67"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb67-1"><a href="#cb67-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> some-handler</span></span>
<span id="cb67-2"><a href="#cb67-2" aria-hidden="true" tabindex="-1"></a>   [request]</span>
<span id="cb67-3"><a href="#cb67-3" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">let</span> [{<span class="at">:keys</span> [pool]} (<span class="at">:system</span> request)]</span>
<span id="cb67-4"><a href="#cb67-4" aria-hidden="true" tabindex="-1"></a>      ...))</span></code></pre></div>
<p>Or even attach all the values into the request at the top level.</p>
<div class="sourceCode" id="cb68"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb68-1"><a href="#cb68-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> wrap-system</span></span>
<span id="cb68-2"><a href="#cb68-2" aria-hidden="true" tabindex="-1"></a>   [system handler]</span>
<span id="cb68-3"><a href="#cb68-3" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">fn</span> [request]</span>
<span id="cb68-4"><a href="#cb68-4" aria-hidden="true" tabindex="-1"></a>      (handler (<span class="kw">merge</span> request system))))</span></code></pre></div>
<div class="sourceCode" id="cb69"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb69-1"><a href="#cb69-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> some-handler</span></span>
<span id="cb69-2"><a href="#cb69-2" aria-hidden="true" tabindex="-1"></a>   [{<span class="at">:keys</span> [pool] <span class="at">:as</span> request}]</span>
<span id="cb69-3"><a href="#cb69-3" aria-hidden="true" tabindex="-1"></a>   ...)</span></code></pre></div>
<p>This all has the potential benefit of avoiding the need to wire the system explicitly to code that depends on it since it is now all contained in one object</p>
<p>This sort of technique - by other names and syntaxes - is pretty popular in other worlds like JavaScript and Python.</p>
<h3 id="is-testing-really-important-enough-to-do-all-this">Is testing really important enough to do all this?</h3>
<p>I will claim, without a convincing argument top of mind but with strong feelings in the core of my heart, that writing code like this makes it easier to reason about and refactor.</p>
<p>The testing argument is just easier to make since I can more clearly show mechanical deficiencies in other approaches.</p>
<h3 id="what-about-mount">What about mount?</h3>
<p>There is a library called mount which uses the namespace loading graph as its mechanism for knowing what order to start and stop things.</p>
<div class="sourceCode" id="cb70"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb70-1"><a href="#cb70-1" aria-hidden="true" tabindex="-1"></a>(mount/defstate other-thing</span>
<span id="cb70-2"><a href="#cb70-2" aria-hidden="true" tabindex="-1"></a>  <span class="at">:start</span> (make-other-thing)</span>
<span id="cb70-3"><a href="#cb70-3" aria-hidden="true" tabindex="-1"></a>  <span class="at">:stop</span>  (stop other-thing))</span>
<span id="cb70-4"><a href="#cb70-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb70-5"><a href="#cb70-5" aria-hidden="true" tabindex="-1"></a>(mount/defstate thing</span>
<span id="cb70-6"><a href="#cb70-6" aria-hidden="true" tabindex="-1"></a>  <span class="at">:start</span> (f other-thing)</span>
<span id="cb70-7"><a href="#cb70-7" aria-hidden="true" tabindex="-1"></a>  <span class="at">:stop</span>  (stop thing))</span></code></pre></div>
<p>This is better than using regular <code>def</code>s to store stateful components since you can start and stop everything from the REPL.</p>
<p>What this doesn't solve for is how call-sites get handles to the stateful components. Without discipline to not touch them directly, this will lead to an overall architecture indistinguishable from just using regular <code>def</code>s.</p>
<p>While wouldn't recommend it for those reasons, if you already have an app structured "the wrong way" it can be an incremental step in the right direction to get things REPL-able.</p>
<h3 id="contract-narrowing">Contract Narrowing</h3>
<p>In all examples I showed there are only like 5 actual stateful components. This is fine, but you might not feel the automatic wiring of integrant is "worth the cost" unless there is more than that.</p>
<p>One way that you can easily end up with more than a handful of components - even if you just have a single database - is if you practice "contract narrowing." That is - instead of passing "<code>pool</code>" to consumers, which will let them do any arbitrary operations on the database, pass an object with a "narrower contract" like a "<code>user-service</code>."</p>
<div class="sourceCode" id="cb71"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb71-1"><a href="#cb71-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defprotocol</span><span class="fu"> UserService</span></span>
<span id="cb71-2"><a href="#cb71-2" aria-hidden="true" tabindex="-1"></a>  (find-by-id [_ id]))</span>
<span id="cb71-3"><a href="#cb71-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb71-4"><a href="#cb71-4" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defrecord</span><span class="fu"> UserServiceImpl</span></span>
<span id="cb71-5"><a href="#cb71-5" aria-hidden="true" tabindex="-1"></a>  [pool]</span>
<span id="cb71-6"><a href="#cb71-6" aria-hidden="true" tabindex="-1"></a>  (find-by-id [_ id]</span>
<span id="cb71-7"><a href="#cb71-7" aria-hidden="true" tabindex="-1"></a>    (jdbc/execute! </span>
<span id="cb71-8"><a href="#cb71-8" aria-hidden="true" tabindex="-1"></a>      pool </span>
<span id="cb71-9"><a href="#cb71-9" aria-hidden="true" tabindex="-1"></a>      [<span class="st">&quot;SELECT * FROM user</span></span>
<span id="cb71-10"><a href="#cb71-10" aria-hidden="true" tabindex="-1"></a><span class="st">        WHERE user.user_id = ?&quot;</span></span>
<span id="cb71-11"><a href="#cb71-11" aria-hidden="true" tabindex="-1"></a>       id])))</span></code></pre></div>
<div class="sourceCode" id="cb72"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb72-1"><a href="#cb72-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> start-system</span></span>
<span id="cb72-2"><a href="#cb72-2" aria-hidden="true" tabindex="-1"></a>  []</span>
<span id="cb72-3"><a href="#cb72-3" aria-hidden="true" tabindex="-1"></a>  (<span class="kw">let</span> [pool         (start-pool)</span>
<span id="cb72-4"><a href="#cb72-4" aria-hidden="true" tabindex="-1"></a>        user-service (-&gt;UserServiceImpl pool)]</span>
<span id="cb72-5"><a href="#cb72-5" aria-hidden="true" tabindex="-1"></a>    {<span class="at">::pool</span>         pool </span>
<span id="cb72-6"><a href="#cb72-6" aria-hidden="true" tabindex="-1"></a>     <span class="at">::user-service</span> user-service}))</span></code></pre></div>
<div class="sourceCode" id="cb73"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb73-1"><a href="#cb73-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> user-handler</span></span>
<span id="cb73-2"><a href="#cb73-2" aria-hidden="true" tabindex="-1"></a>  [{<span class="at">::system/keys</span> [user-service]} request]</span>
<span id="cb73-3"><a href="#cb73-3" aria-hidden="true" tabindex="-1"></a>  ... (user-service/find-by-id user-service <span class="dv">123</span>) ...)</span></code></pre></div>
<p>With this sort of code it is a lot more reasonable that you would end up with enough components that manually wiring their dependencies would get troublesome.</p>
</details>

<p>Expand the section above for further elaboration. Brag about your holiday plans in the comments below.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>A Practical Advent of Code</title><link>https://mccue.dev/pages/12-3-22-practical-advent</link><description></description><pubDate>Sat, 03 Dec 0022 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>A Practical Advent of Code</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">A Practical Advent of Code</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
<meta property="og:image" content="https://mccue.dev/pages/12-3-22-santa.png" />
<meta name="twitter:image" content="https://mccue.dev/pages/12-3-22-santa.png">

<p>I've never done more than a few days of <a href="https://adventofcode.com/">Advent of Code</a>.</p>
<p>I'm sure its fun if you're the kind of person who likes doing those sorts of puzzles, but that's not really what I'm into. My jam is really finicky, relatively small problems. Problems that everyone can reasonably <em>do</em> and could come up in real code, but where it's really hard to be happy with a solution.</p>
<p>So that's what this is. I'm starting three days in, and I'm nowhere close to prepared to give a challenge a day, but I want to share the sorts of problems that keep me up at night.</p>
<h2 id="the-challenge">The Challenge</h2>
<p>The following three samples of JSON come from <a href="https://www.w3.org/TR/activitystreams-core/">the activity streams specification</a>.</p>
<p>If you have misguided dreams of making the next Twitter, maybe you've looked at this too.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;@context&quot;</span><span class="fu">:</span> <span class="st">&quot;https://www.w3.org/ns/activitystreams&quot;</span><span class="fu">,</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;summary&quot;</span><span class="fu">:</span> <span class="st">&quot;A note&quot;</span><span class="fu">,</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;type&quot;</span><span class="fu">:</span> <span class="st">&quot;Note&quot;</span><span class="fu">,</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;content&quot;</span><span class="fu">:</span> <span class="st">&quot;My dog has fleas.&quot;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="fu">}</span></span></code></pre></div>
<div class="sourceCode" id="cb2"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;@context&quot;</span><span class="fu">:</span> <span class="fu">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>     <span class="dt">&quot;@vocab&quot;</span><span class="fu">:</span> <span class="st">&quot;https://www.w3.org/ns/activitystreams&quot;</span><span class="fu">,</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>     <span class="dt">&quot;ext&quot;</span><span class="fu">:</span> <span class="st">&quot;https://canine-extension.example/terms/&quot;</span><span class="fu">,</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>     <span class="dt">&quot;@language&quot;</span><span class="fu">:</span> <span class="st">&quot;en&quot;</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>  <span class="fu">},</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;summary&quot;</span><span class="fu">:</span> <span class="st">&quot;A note&quot;</span><span class="fu">,</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;type&quot;</span><span class="fu">:</span> <span class="st">&quot;Note&quot;</span><span class="fu">,</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;content&quot;</span><span class="fu">:</span> <span class="st">&quot;My dog has fleas.&quot;</span><span class="fu">,</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;ext:nose&quot;</span><span class="fu">:</span> <span class="dv">0</span><span class="fu">,</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;ext:smell&quot;</span><span class="fu">:</span> <span class="st">&quot;terrible&quot;</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a><span class="fu">}</span></span></code></pre></div>
<div class="sourceCode" id="cb3"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;@context&quot;</span><span class="fu">:</span> <span class="ot">[</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>     <span class="st">&quot;https://www.w3.org/ns/activitystreams&quot;</span><span class="ot">,</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>     <span class="fu">{</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>      <span class="dt">&quot;css&quot;</span><span class="fu">:</span> <span class="st">&quot;http://www.w3.org/ns/oa#styledBy&quot;</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>     <span class="fu">}</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>  <span class="ot">]</span><span class="fu">,</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;summary&quot;</span><span class="fu">:</span> <span class="st">&quot;A note&quot;</span><span class="fu">,</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;type&quot;</span><span class="fu">:</span> <span class="st">&quot;Note&quot;</span><span class="fu">,</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;content&quot;</span><span class="fu">:</span> <span class="st">&quot;My dog has fleas.&quot;</span><span class="fu">,</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;css&quot;</span><span class="fu">:</span> <span class="st">&quot;http://www.csszengarden.com/217/217.css?v=8may2013&quot;</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a><span class="fu">}</span></span></code></pre></div>
<p>In all of them, there is a piece of information we will call "the vocabulary".</p>
<p>If the context is a string, the vocabulary is that string. If the context is an object, the vocabulary is under the <code>@vocab</code> key. If the context is an array, the vocabulary is a string in the first index of the array.</p>
<p>So in all of these examples the vocabulary is <code>"https://www.w3.org/ns/activitystreams"</code></p>
<p>Assume one of these shapes of JSON is in a file called <code>activity.json</code>. Your job is to extract the vocabulary out of that file and print it.</p>
<h2 id="restrictions">Restrictions</h2>
<ul>
<li>If you are employed, you need to use the JSON library you use for work.</li>
<li>You need to explain your code to St. Peter when you die.</li>
</ul>
<p>I am personally most interested in solutions on the "static" side of the world - Java, C#, Rust, etc. - because this is where the solutions really go from "obvious" to "cursed" and "magic".</p>
<p>Leave solutions in the comments below.</p>
<hr />
<details>
  <summary>My Solution</summary>

<p>I've been doodling on a JSON library for Java that I might find time to write about later, but in that my solution is the following.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.</span><span class="im">Json</span><span class="op">;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">json</span><span class="op">.</span><span class="im">decode</span><span class="op">.</span><span class="im">alpha</span><span class="op">.</span><span class="im">Decoder</span><span class="op">;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">io</span><span class="op">.</span><span class="im">IOException</span><span class="op">;</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">nio</span><span class="op">.</span><span class="im">file</span><span class="op">.</span><span class="im">Files</span><span class="op">;</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">nio</span><span class="op">.</span><span class="im">file</span><span class="op">.</span><span class="im">Path</span><span class="op">;</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>        var json <span class="op">=</span> Json<span class="op">.</span><span class="fu">readString</span><span class="op">(</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>                Files<span class="op">.</span><span class="fu">readString</span><span class="op">(</span>Path<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;activity.json&quot;</span><span class="op">))</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>        var vocab <span class="op">=</span> Decoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>                json<span class="op">,</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;@context&quot;</span><span class="op">,</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>                context <span class="op">-&gt;</span> Decoder<span class="op">.</span><span class="fu">oneOf</span><span class="op">(</span>context<span class="op">,</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>                        Decoder<span class="op">::</span>string<span class="op">,</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>                        Decoder<span class="op">.</span><span class="fu">index</span><span class="op">(</span><span class="dv">0</span><span class="op">,</span> Decoder<span class="op">::</span>string<span class="op">),</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a>                        Decoder<span class="op">.</span><span class="fu">field</span><span class="op">(</span><span class="st">&quot;@vocab&quot;</span><span class="op">,</span> Decoder<span class="op">::</span>string<span class="op">)</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a>                <span class="op">)</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>vocab<span class="op">);</span></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Try it out for yourself if you have a mind to - I would appreciate feedback.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode xml"><code class="sourceCode xml"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>&lt;<span class="ot">dependencies</span><span class="er">&gt;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;dependency&gt;</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;groupId&gt;dev.mccue&lt;/groupId&gt;</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;artifactId&gt;json&lt;/artifactId&gt;</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;version&gt;0.0.9&lt;/version&gt;</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;/dependency&gt;</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;dependency&gt;</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;groupId&gt;dev.mccue&lt;/groupId&gt;</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;artifactId&gt;json.decode.alpha&lt;/artifactId&gt;</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;version&gt;0.0.9&lt;/version&gt;</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;/dependency&gt;</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a><span class="er">&lt;/dependencies&gt;</span></span></code></pre></div>
</details>

<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Better Java logging, inspired by Clojure and Rust (II)</title><link>https://mccue.dev/pages/12-3-22-better-java-logging-2</link><description></description><pubDate>Sat, 03 Dec 0022 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Better Java logging, inspired by Clojure and Rust (II)</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Better Java logging, inspired by Clojure and Rust (II)</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
Around three months ago [I wrote a pretty long rant about a Java logging library I doodled out](https://mccue.dev/pages/9-25-22-better-java-logging).

<p>My goal was to dream up something that would fill the same ecosystem role as SLF4J but with the primary goal of supporting the logging of structured data.</p>
<p>I got an absolute mountain of good feedback. After spending some time reading and internalizing the responses, I realized a few things.</p>
<ol type="1">
<li>I need to more effectively communicate my intent. Writing about the nitty-gritty details about choices in API design is my <a href="https://www.youtube.com/watch?v=7UfiCa244XE">marmalade sandwich</a>, but I need to do that <em>after</em> explaining what I am going to do and why.</li>
<li>Going forward, I need to properly contextualize how everything would interact with OpenTelemetry. Yes, OTel provides an API for propagating context, but OTel would not be suitable to include in a library. There is still a role here for something which lets a library interact with that concept without including OTel outright.</li>
<li>All the opining about <code>ExtentLocal</code>s (now called <code>ScopedValue</code>s) was a bit tangential, but I do stand by the choice of making the API only propagate scope inside lambdas in preparation.</li>
<li>I need to be more mindful of allocations in general, but still think that having a reified but restricted set of log values is important and paying whatever cost there is to allocate those objects is worth it.</li>
<li>The API I was making was doing way too much. The ring buffer, the context stack, all the thread and timing info I was attaching to <code>Log</code> records - all of those are still valid directions to go with a logging <em>implementation</em>, but not with a logging <em>interface</em>.</li>
</ol>
<p>Related to the last two points - I've written up a new draft of the API without any of the context implementation and minimizing allocations down to just the log entries. This has required a few changes - farewell my sweet prince <code>log</code>, the method which logs a <code>Log</code> - but so far seems to be okay. I'm not entirely sold on how I am handling context now though.</p>
<p>You can find all of that on my GitHub under <a href="https://github.com/bowbahdoe/log.beta">log.beta</a>.</p>
<p>I am writing this tiny update to give myself permission to put this on <a href="https://www.youtube.com/watch?v=f84n5oFoZBc">the hammock</a> for a time and move on to some other fiddly, controversial, and fun topics. Stay tuned for that.</p>
<hr />
<p>If you want to talk about this, feel free to reach out directly by any means necessary.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Better Java logging, inspired by Clojure and Rust</title><link>https://mccue.dev/pages/9-25-22-better-java-logging</link><description></description><pubDate>Sun, 25 Sep 0022 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Better Java logging, inspired by Clojure and Rust</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Better Java logging, inspired by Clojure and Rust</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
<meta property="og:image" content="https://mccue.dev/pages/9-25-22-ill-steal-it.png" />
<meta name="twitter:image" content="https://mccue.dev/pages/9-25-22-ill-steal-it.png">

<blockquote>
<p>Existing logging libraries are based on a design from the 80s and early 90s. Most of the systems at the time where developed in standalone servers where logging messages to console or file was the predominant thing to do. Logging was mostly providing debugging information and system behavioural introspection.</p>
<p>Most of modern systems are distributed in virtualized machines that live in the cloud. These machines could disappear any time. In this context logging on the local file system isn't useful as logs are easily lost if virtual machines are destroyed. Therefore it is common practice to use log collectors and centralized log processors. The ELK stack it has been predominant in this space for years, but there are a multitude of other commercial and open-source products.</p>
<p>Most of these systems have to deal with non structured data represented as formatted strings in files. The process of extracting information out of these strings is very tedious, error prone, and definitely not fun. But the question is: why did we encode these as strings in the first place? This is just because existing log frameworks, which have been redesigned in various decades follow the same structure as when systems lived on the same single server for decades.</p>
<p>I believe we need the break free of these anachronistic designs and use event loggers, not message loggers, which are designed for dynamic distributed systems living in cloud and using centralized log aggregators.</p>
<p>- Motivation for <a href="https://cljdoc.org/d/com.brunobonacci/mulog-slack/0.9.0/doc/readme#motivation"><code>µ/log</code></a>.</p>
</blockquote>
<p>I think this description is essentially correct. Existing logging libraries, especially those in the Java ecosystem, are not <a href="https://youtu.be/A-mxj2vhVAA?t=543">"fit predators"</a> for the modern world.</p>
<p>I claim that we can do meaningfully better.</p>
<p>Whether the design I come up with at the end of this is that better solution I do not know, but if it isn't I hope it spurs <em>someone</em> to make whatever is.</p>
<h2 id="prior-work">Prior Work</h2>
<h3 id="µlog">µ/log</h3>
<p><a href="https://github.com/BrunoBonacci/mulog"><code>µ/log</code></a> is a Clojure library written by the author of the quote above.</p>
<p>Clojure is a dynamically typed functional language. Not every design choice made by <a href="https://github.com/BrunoBonacci/mulog"><code>µ/log</code></a> will make sense for the statically typed Java, but there is bound to be a lot to pull.</p>
<figure>
  <a href="https://www.youtube.com/watch?v=WhwqBUCYQO0">
    <img src="/pages/9-25-22-ill-steal-it.png" alt="I'll steal it. No one will ever know!"/>
  </a>
  <figcaption>I'll steal it. No one will ever know!</figcaption>
</figure>

<p>A logging call in <a href="https://github.com/BrunoBonacci/mulog"><code>µ/log</code></a> looks something like this.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>(μ/log <span class="at">:minesweeper.event/clicked-square</span> <span class="at">:was-bomb</span> <span class="va">true</span>)</span></code></pre></div>
<p>This first argument is the event type. It is stated best practice that the event type should have both a "namespace" and a "name". <code>minesweeper.event</code> and <code>clicked-square</code> respectively.</p>
<p>The rest of the arguments are key-value pairs of arbitrary data. The convention in Clojure would be for that arbitrary data to be made of "data primitives" instead of "named aggregates".</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="co">// In Java, data is often tied to a &quot;named aggregate&quot;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> Dog <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="bu">String</span> name<span class="op">;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">Dog</span><span class="op">(</span><span class="bu">String</span> name<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">name</span> <span class="op">=</span> name<span class="op">;</span>    </span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>    <span class="co">// And how data is accessed from that aggregate</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>    <span class="co">// is totally arbitrary, though conventions like</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>    <span class="co">// getX can allow for heuristics.</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">String</span> <span class="fu">retrieveName</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">name</span><span class="op">;</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb3"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co">;; In clojure it would be uncommon to have a named &quot;Dog&quot; object</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>(<span class="bu">deftype</span><span class="fu"> Dog </span>[<span class="kw">name</span>])</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>(μ/log <span class="at">:cool.dog/barked</span> <span class="at">:loud</span> <span class="va">true</span> <span class="at">:dog</span> (new Dog <span class="st">&quot;jenny&quot;</span>))</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="co">;; Instead, you would have a &quot;raw map&quot; with data about said doggo.</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>(μ/log <span class="at">:cool.dog/barked</span> <span class="at">:loud</span> <span class="va">true</span> <span class="at">:dog</span> {<span class="at">:name</span> <span class="st">&quot;rhodie&quot;</span>})</span></code></pre></div>
<p>So while <a href="https://cljdoc.org/d/com.brunobonacci/mulog/0.9.0/doc/howtos/how-to-json-encode-custom-java-classes">there are mechanisms to handle it</a>, serializing user defined classes is a relatively uncommon task. Downstream consumers will generally expect values to be these "base" values - lists, maps, strings, numbers - or directly decomposable into them.</p>
<p>These data are then merged with a standard set of metadata about the log.</p>
<ul>
<li>A timestamp saying when the "event" happened.</li>
<li>A UUID.</li>
</ul>
<p>The timestamp is pretty self-explanatory, but the UUID is a bit custom.</p>
<p>It isn't a standard UUIDv4, but instead a construct called a "Flake" (as in snowflake, no two alike). A Flake has the following properties.</p>
<ul>
<li>192 bits. 128 random, 64 time based.</li>
<li>New ones compare greater than older ones.</li>
<li>Comparison order is maintained in String and byte form.</li>
<li>String representation is URL safe</li>
<li>Can be created in under 50 nanoseconds</li>
</ul>
<p>An example value looks like this: <code>4lIfs0B6IRjDMHo6g2Tbgrf4lzikQNXl</code>.</p>
<p>I'll freely admit I don't understand the full scope of the problems this is intended to solve, but take it on faith that it's a good design and sensible alternative to <code>UUID.randomUUID()</code>.</p>
<p>In addition to that standard metadata, any global or local (bound within a lexical scope) context is included.</p>
<p>Global context is intended to be set at the start of the program with unchanging metadata.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>(μ/set-global-context! {<span class="at">:app-name</span> <span class="st">&quot;cool-trail-cam&quot;</span>})</span></code></pre></div>
<p>Internally this information is stored in an <a href="https://clojuredocs.org/clojure.core/atom"><code>atom</code></a> - a thin wrapper over an <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/atomic/AtomicReference.html"><code>AtomicReference</code></a>.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defonce</span><span class="fu"> </span>^{<span class="at">:doc</span> <span class="do">&quot;The global logging context is used to add properties</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="do">             which are valid for all subsequent log events.  This is</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="do">             typically set once at the beginning of the process with</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="do">             information like the app-name, version, environment, the</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="do">             pid and other similar info.&quot;</span>}</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>  global-context (<span class="kw">atom</span> {}))</span></code></pre></div>
<p>Local context is bound using the <code>μ/with-context</code> macro.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>(μ/with-context {<span class="at">:request-id</span> <span class="st">&quot;685a40fd-8740-4a2f-85ae-d6a4b2c02bb0&quot;</span>}</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>  (μ/log <span class="at">:cool.dog/barked</span> <span class="at">:loud</span> <span class="va">true</span> <span class="at">:dog</span> {<span class="at">:name</span> <span class="st">&quot;rhodie&quot;</span>}))</span></code></pre></div>
<p>By virtue of being stored and retrieved from a <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/lang/ThreadLocal.html"><code>ThreadLocal</code></a>, this context will be propagated even across function calls.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">def</span><span class="fu"> </span>^{<span class="at">:doc</span> <span class="do">&quot;The local context is local to the current thread,</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="do">             therefore all the subsequent call to log withing the</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="do">             given context will have the properties added as well. It</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="do">             is typically used to add information regarding the</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="do">             current processing in the current thread. For example</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a><span class="do">             who is the user issuing the request and so on.&quot;</span>}</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>  local-context (ut/thread-local <span class="va">nil</span>))</span></code></pre></div>
<p>All of this information merges together into a map that looks something like this.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>{<span class="at">:mulog/event-name</span> <span class="at">:cool.dog/barked</span>,</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a> <span class="at">:mulog/timestamp</span>  <span class="dv">613022400000</span>,</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a> <span class="at">:mulog/trace-id</span>   #mulog/flake <span class="st">&quot;4lIfs0B6IRjDMHo6g2Tbgrf4lzikQNXl&quot;</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a> <span class="at">:mulog/namespace</span>  <span class="st">&quot;cool.dog&quot;</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a> <span class="at">:app-name</span>         <span class="st">&quot;cool-trail-cam&quot;</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a> <span class="at">:request-id</span>       <span class="st">&quot;685a40fd-8740-4a2f-85ae-d6a4b2c02bb0&quot;</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a> <span class="at">:loud</span>             <span class="va">true</span> </span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a> <span class="at">:dog</span>              {<span class="at">:name</span> <span class="st">&quot;rhodie&quot;</span>}}</span></code></pre></div>
<p>Then this map is "published".</p>
<p>The internals of how this publishing works are <a href="https://cljdoc.org/d/com.brunobonacci/mulog/0.9.0/doc/%CE%BC-log-internals">better documented elsewhere</a>, but the gist of it is that the whole map is put into a ring buffer. An asynchronous process reads from that ring buffer and dumps to ring buffers. Any number of asynchronous processes then periodically read from these buffers and do the work of to printing to stdout, sending it to Cloudwatch, etc.</p>
<p><code>µ/log</code> calls each of these asynchronous processes which handle logs a "publisher". This can be a bit confusing in terminology, but your code "publishes" logs to a ring buffer, an unnamed process forwards these logs to more ring buffers, then "publishers" take those logs and do work with them.</p>
<figure>
  <a href="https://cljdoc.org/d/com.brunobonacci/mulog/0.9.0/doc/%CE%BC-log-internals">
    <img src="/pages/9-25-22-ring-buffer-diagram.png" alt="ring buffer publisher scheme diagram"/>
  </a>
  <figcaption>Diagram from `µ/log`'s docs.</figcaption>
</figure>

<p>The goals of this scheme are to</p>
<ol type="1">
<li>Make it possible to "log with abandon." Publishing to a ring buffer should take only a few hundred nanoseconds.</li>
<li>Make it so that adding publishers doesn't impact overall performance. They all get their own buffers and work at their own pace.</li>
<li>Make observability resilient to failures. If publishers "get behind" for whatever reason - us-west-2 is down, <a href="https://www.youtube.com/watch?v=3Huc47Dqsg8">freak gasoline fight accident</a> - a ring buffer might lose events but in exchange there won't be an infinite backlog to work through to send off more current data.</li>
</ol>
<div class="sourceCode" id="cb9"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>(μ/start-publisher! {<span class="at">:type</span> <span class="at">:console</span>})</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>(μ/start-publisher! {<span class="at">:type</span> <span class="at">:simple-file</span> </span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>                     <span class="at">:filename</span> <span class="st">&quot;/tmp/mulog/events.log&quot;</span>})</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>(μ/start-publisher!</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>  {<span class="at">:type</span> <span class="at">:elasticsearch</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>   <span class="at">:url</span>  <span class="st">&quot;http://localhost:9200/&quot;</span>})</span></code></pre></div>
<p>The final wrinkle is that in addition to logging "events" - a record of something that happened at a given point in time - <code>µ/log</code> lets you record "traces" - a record of a process that occurred over a span of time.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>(μ/trace <span class="at">:cool-dog/chasing-squirrel</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>  [<span class="at">:got-away</span> <span class="st">&quot;hope so&quot;</span>]</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>  (chase-squirrel))</span></code></pre></div>
<p>Unlike a normal log this adds metadata signifying the duration of the process, whether that process terminated with an exception, and parent traces that the current trace is nested under.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>{<span class="at">:mulog/event-name</span> <span class="at">:cool-dog/chasing-squirrel</span>,</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a> <span class="at">:mulog/timestamp</span>  <span class="dv">609652800000</span>,</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a> <span class="at">:mulog/duration</span>   <span class="dv">777600000</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a> <span class="at">:mulog/trace-id</span>   #mulog/flake <span class="st">&quot;4lLBQ0kk-mmdCFrwI8Ravb6c8S3ddpq-&quot;</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a> <span class="at">:mulog/root-trace</span> #mulog/flake <span class="st">&quot;4lLBQ0kbx1weOm_TT5Wynok6GLBllXQC&quot;</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a> <span class="at">:mulog/outcome</span>    <span class="at">:ok</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a> <span class="at">:mulog/namespace</span>  <span class="st">&quot;cool.dog&quot;</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a> <span class="at">:app-name</span>         <span class="st">&quot;cool-trail-cam&quot;</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a> <span class="at">:got-away</span>         <span class="va">true</span>}</span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a><span class="co">;; If it fails, outcome will be :error and the exception included.</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>{<span class="at">:mulog/event-name</span> <span class="at">:cool-dog/chasing-squirrel</span>,</span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a> <span class="at">:mulog/timestamp</span>  <span class="dv">609652800000</span>,</span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a> <span class="at">:mulog/duration</span>   <span class="dv">777600000</span></span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a> <span class="at">:mulog/trace-id</span>   #mulog/flake <span class="st">&quot;4lLBQ0kk-mmdCFrwI8Ravb6c8S3ddpq-&quot;</span></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true" tabindex="-1"></a> <span class="at">:mulog/root-trace</span> #mulog/flake <span class="st">&quot;4lLBQ0kbx1weOm_TT5Wynok6GLBllXQC&quot;</span></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true" tabindex="-1"></a> <span class="at">:mulog/outcome</span>    <span class="at">:error</span> </span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true" tabindex="-1"></a> <span class="at">:mulog/exception</span>  ...</span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true" tabindex="-1"></a> <span class="at">:mulog/namespace</span>  <span class="st">&quot;cool.dog&quot;</span></span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true" tabindex="-1"></a> <span class="at">:app-name</span>         <span class="st">&quot;cool-trail-cam&quot;</span></span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true" tabindex="-1"></a> <span class="at">:got-away</span>         <span class="va">true</span>}</span></code></pre></div>
<h3 id="tracing">tracing</h3>
<p><code>tracing</code> is a Rust library with holistically similar goals to <code>µ/log</code>.</p>
<p>There is a similar Rust library named <code>slog</code> which deserves mention. It has been around longer and has a stable API, but <code>tracing</code> has better support for interacting with Rust's async ecosystem and a larger active community. To quote <a href="https://github.com/slog-rs/slog#you-might-consider-using-tracing-instead"><code>slog</code>'s docs</a>.</p>
<blockquote>
<p>Please check tracing and see if it is more suitable for your use-case. It seems that it is already a go-to logging/tracing solution for Rust.</p>
</blockquote>
<p>My impression is that a lot of the broad strokes are the same, so I am going to focus mostly on <code>tracing</code>.</p>
<p><code>tracing</code> is built on top of <a href="https://docs.rs/tracing/latest/tracing/index.html#core-concepts">three core concepts</a>, spans, events, and subscribers.</p>
<p>Spans are records of a "period of time" with a beginning and an end. This is a close parallel to what <code>µ/log</code> calls a "trace".</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> span <span class="op">=</span> <span class="pp">span!</span>(<span class="pp">Level::</span>INFO<span class="op">,</span> <span class="st">&quot;toasting toast&quot;</span>)<span class="op">;</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> _guard <span class="op">=</span> span<span class="op">.</span>enter()<span class="op">;</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a><span class="co">// when _guard is dropped, the span is closed.</span></span></code></pre></div>
<p>Semantically, this makes use of a property of Rust that doesn't exist in the JVM. When a struct in Rust is no longer in lexical scope, it is immediately "dropped." Dropping can implicitly run arbitrary code such as freeing memory, closing a socket, or - in this case - doing whatever work is needed to "close" a span.</p>
<p>Spans also have a new kind of metadata attached to them in the "Level." The level serves two purposes</p>
<ol type="1">
<li>It hints to external systems how "serious" something is. If your service starts pumping out 10x as many <code>ERROR</code> spans or events, that is probably a sign something is afoot.</li>
<li>It lets internal systems make sensible decisions about "filtering". While running code locally <code>TRACE</code> spans and events might be relevant, but probably irrelevant in production.</li>
</ol>
<p>Events are records of something that happened at a single point in time. This is closest to what we would classically call a "log."</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="pp">event!</span>(<span class="pp">Level::</span>INFO<span class="op">,</span> <span class="st">&quot;toast popped in&quot;</span>)<span class="op">;</span></span></code></pre></div>
<p>Events interact with spans in that any events emitted while a span is active will be "nested" under that span.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> span <span class="op">=</span> <span class="pp">span!</span>(<span class="pp">Level::</span>INFO<span class="op">,</span> <span class="st">&quot;toasting toast&quot;</span>)<span class="op">;</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> _guard <span class="op">=</span> span<span class="op">.</span>enter()<span class="op">;</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a><span class="pp">event!</span>(<span class="pp">Level::</span>INFO<span class="op">,</span> <span class="st">&quot;toast popped in&quot;</span>)<span class="op">;</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a><span class="co">// We know that the toast burned while toasting toast</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a><span class="co">// but does a toaster toast toast or does toast toast toast?</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a><span class="pp">event!</span>(<span class="pp">Level::</span>WARN<span class="op">,</span> <span class="st">&quot;toast burned&quot;</span>)<span class="op">;</span></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a><span class="co">// when _guard is dropped, the span is closed.</span></span></code></pre></div>
<p>Spans and events are by default sent to the "global subscriber", which is meant to be set at the start of the program.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> global_subscriber <span class="op">=</span> <span class="pp">ConsoleLoggingSubscriber::</span>new()<span class="op">;</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="pp">tracing::subscriber::</span>set_global_default(global_subscriber)</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span>expect(<span class="st">&quot;Failed to set&quot;</span>)<span class="op">;</span></span></code></pre></div>
<p>This is stored inside a static mutable variable, which is prevented from being set twice or in a race by way of a global <code>AtomicUsize</code>.</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">static</span> GLOBAL_INIT<span class="op">:</span> AtomicUsize <span class="op">=</span> <span class="pp">AtomicUsize::</span>new(UNINITIALIZED)<span class="op">;</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> UNINITIALIZED<span class="op">:</span> <span class="dt">usize</span> <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> INITIALIZING<span class="op">:</span> <span class="dt">usize</span> <span class="op">=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> INITIALIZED<span class="op">:</span> <span class="dt">usize</span> <span class="op">=</span> <span class="dv">2</span><span class="op">;</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a><span class="kw">static</span> <span class="kw">mut</span> GLOBAL_DISPATCH<span class="op">:</span> <span class="dt">Option</span><span class="op">&lt;</span>Dispatch<span class="op">&gt;</span> <span class="op">=</span> <span class="cn">None</span><span class="op">;</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">fn</span> set_global_default(dispatcher<span class="op">:</span> Dispatch) <span class="op">-&gt;</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Result</span><span class="op">&lt;</span>()<span class="op">,</span> SetGlobalDefaultError<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">if</span> GLOBAL_INIT<span class="op">.</span>compare_and_swap(</span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a>        UNINITIALIZED<span class="op">,</span> </span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a>        INITIALIZING<span class="op">,</span> </span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a>        <span class="pp">Ordering::</span>SeqCst) <span class="op">==</span> UNINITIALIZED</span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a>        <span class="kw">unsafe</span> <span class="op">{</span></span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a>            GLOBAL_DISPATCH <span class="op">=</span> <span class="cn">Some</span>(dispatcher)<span class="op">;</span></span>
<span id="cb16-20"><a href="#cb16-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb16-21"><a href="#cb16-21" aria-hidden="true" tabindex="-1"></a>        GLOBAL_INIT<span class="op">.</span>store(INITIALIZED<span class="op">,</span> <span class="pp">Ordering::</span>SeqCst)<span class="op">;</span></span>
<span id="cb16-22"><a href="#cb16-22" aria-hidden="true" tabindex="-1"></a>        EXISTS<span class="op">.</span>store(<span class="cn">true</span><span class="op">,</span> <span class="pp">Ordering::</span>Release)<span class="op">;</span></span>
<span id="cb16-23"><a href="#cb16-23" aria-hidden="true" tabindex="-1"></a>        <span class="cn">Ok</span>(())</span>
<span id="cb16-24"><a href="#cb16-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="kw">else</span> <span class="op">{</span></span>
<span id="cb16-25"><a href="#cb16-25" aria-hidden="true" tabindex="-1"></a>        <span class="cn">Err</span>(SetGlobalDefaultError <span class="op">{</span> _no_construct<span class="op">:</span> () <span class="op">}</span>)</span>
<span id="cb16-26"><a href="#cb16-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-27"><a href="#cb16-27" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Subscribers are notified when an event happens, when a span is entered, when a span is exited, and a few other things.</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">trait</span> Subscriber<span class="op">:</span> <span class="ot">&#39;static</span> <span class="op">{</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> enabled(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> metadata<span class="op">:</span> <span class="op">&amp;</span>Metadata<span class="op">&lt;</span><span class="ot">&#39;_</span><span class="op">&gt;</span>) <span class="op">-&gt;</span> <span class="dt">bool</span><span class="op">;</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> new_span(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> span<span class="op">:</span> <span class="op">&amp;</span>Attributes<span class="op">&lt;</span><span class="ot">&#39;_</span><span class="op">&gt;</span>) <span class="op">-&gt;</span> Id<span class="op">;</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> record(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> span<span class="op">:</span> <span class="op">&amp;</span>Id<span class="op">,</span> values<span class="op">:</span> <span class="op">&amp;</span>Record<span class="op">&lt;</span><span class="ot">&#39;_</span><span class="op">&gt;</span>)<span class="op">;</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> record_follows_from(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> span<span class="op">:</span> <span class="op">&amp;</span>Id<span class="op">,</span> follows<span class="op">:</span> <span class="op">&amp;</span>Id)<span class="op">;</span></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> event(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> event<span class="op">:</span> <span class="op">&amp;</span>Event<span class="op">&lt;</span><span class="ot">&#39;_</span><span class="op">&gt;</span>)<span class="op">;</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> enter(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> span<span class="op">:</span> <span class="op">&amp;</span>Id)<span class="op">;</span></span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> exit(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> span<span class="op">:</span> <span class="op">&amp;</span>Id)<span class="op">;</span></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> register_callsite(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> metadata<span class="op">:</span> <span class="op">&amp;</span><span class="ot">&#39;static</span> Metadata<span class="op">&lt;</span><span class="ot">&#39;static</span><span class="op">&gt;</span>) </span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">-&gt;</span> Interest <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> max_level_hint(<span class="op">&amp;</span><span class="kw">self</span>) <span class="op">-&gt;</span> <span class="dt">Option</span><span class="op">&lt;</span>LevelFilter<span class="op">&gt;</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> event_enabled(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> event<span class="op">:</span> <span class="op">&amp;</span>Event<span class="op">&lt;</span><span class="ot">&#39;_</span><span class="op">&gt;</span>) <span class="op">-&gt;</span> <span class="dt">bool</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> clone_span(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> id<span class="op">:</span> <span class="op">&amp;</span>Id) <span class="op">-&gt;</span> Id <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> drop_span(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> _id<span class="op">:</span> Id) <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> try_close(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> id<span class="op">:</span> Id) <span class="op">-&gt;</span> <span class="dt">bool</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb17-17"><a href="#cb17-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> current_span(<span class="op">&amp;</span><span class="kw">self</span>) <span class="op">-&gt;</span> Current <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb17-18"><a href="#cb17-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">unsafe</span> <span class="kw">fn</span> downcast_raw(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> id<span class="op">:</span> TypeId) <span class="op">-&gt;</span> <span class="dt">Option</span><span class="op">&lt;*</span><span class="kw">const</span> ()<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb17-19"><a href="#cb17-19" aria-hidden="true" tabindex="-1"></a>        <span class="op">...</span> </span>
<span id="cb17-20"><a href="#cb17-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb17-21"><a href="#cb17-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Okay, maybe more than a few other things.</p>
<p>These methods are related to filtering events. Given some metadata, a subscriber can say whether they always want to be informed of an event, never want to be informed, or will need to do some runtime check to know if an event is relevant. Because of the magic of Rust, these checks can sometimes totally remove the runtime cost of recording irrelevant events.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">trait</span> Subscriber<span class="op">:</span> <span class="ot">&#39;static</span> <span class="op">{</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> enabled(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> metadata<span class="op">:</span> <span class="op">&amp;</span>Metadata<span class="op">&lt;</span><span class="ot">&#39;_</span><span class="op">&gt;</span>) <span class="op">-&gt;</span> <span class="dt">bool</span><span class="op">;</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> register_callsite(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> metadata<span class="op">:</span> <span class="op">&amp;</span><span class="ot">&#39;static</span> Metadata<span class="op">&lt;</span><span class="ot">&#39;static</span><span class="op">&gt;</span>) </span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">-&gt;</span> Interest <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> max_level_hint(<span class="op">&amp;</span><span class="kw">self</span>) <span class="op">-&gt;</span> <span class="dt">Option</span><span class="op">&lt;</span>LevelFilter<span class="op">&gt;</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> event_enabled(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> event<span class="op">:</span> <span class="op">&amp;</span>Event<span class="op">&lt;</span><span class="ot">&#39;_</span><span class="op">&gt;</span>) <span class="op">-&gt;</span> <span class="dt">bool</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>These methods allow for creating and manipulating spans. This is needed because <code>Subscriber</code>s are responsible for tracking information about spans like their start and end times.</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">trait</span> Subscriber<span class="op">:</span> <span class="ot">&#39;static</span> <span class="op">{</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> new_span(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> span<span class="op">:</span> <span class="op">&amp;</span>Attributes<span class="op">&lt;</span><span class="ot">&#39;_</span><span class="op">&gt;</span>) <span class="op">-&gt;</span> Id<span class="op">;</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> record(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> span<span class="op">:</span> <span class="op">&amp;</span>Id<span class="op">,</span> values<span class="op">:</span> <span class="op">&amp;</span>Record<span class="op">&lt;</span><span class="ot">&#39;_</span><span class="op">&gt;</span>)<span class="op">;</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> record_follows_from(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> span<span class="op">:</span> <span class="op">&amp;</span>Id<span class="op">,</span> follows<span class="op">:</span> <span class="op">&amp;</span>Id)<span class="op">;</span></span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> clone_span(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> id<span class="op">:</span> <span class="op">&amp;</span>Id) <span class="op">-&gt;</span> Id <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> drop_span(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> _id<span class="op">:</span> Id) <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> try_close(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> id<span class="op">:</span> Id) <span class="op">-&gt;</span> <span class="dt">bool</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> current_span(<span class="op">&amp;</span><span class="kw">self</span>) <span class="op">-&gt;</span> Current <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb19-12"><a href="#cb19-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Here be dragons.</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">trait</span> Subscriber<span class="op">:</span> <span class="ot">&#39;static</span> <span class="op">{</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">unsafe</span> <span class="kw">fn</span> downcast_raw(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> id<span class="op">:</span> TypeId) <span class="op">-&gt;</span> <span class="dt">Option</span><span class="op">&lt;*</span><span class="kw">const</span> ()<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">...</span> </span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And these are the more digestible ones.</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">trait</span> Subscriber<span class="op">:</span> <span class="ot">&#39;static</span> <span class="op">{</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> event(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> event<span class="op">:</span> <span class="op">&amp;</span>Event<span class="op">&lt;</span><span class="ot">&#39;_</span><span class="op">&gt;</span>)<span class="op">;</span></span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> enter(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> span<span class="op">:</span> <span class="op">&amp;</span>Id)<span class="op">;</span></span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> exit(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> span<span class="op">:</span> <span class="op">&amp;</span>Id)<span class="op">;</span></span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The values supported by this system are defined implicitly by a "visitor" trait, where each method on the trait corresponds to a kind of data.</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">trait</span> Visit <span class="op">{</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> record_debug(<span class="op">&amp;</span><span class="kw">mut</span> <span class="kw">self</span><span class="op">,</span> field<span class="op">:</span> <span class="op">&amp;</span>Field<span class="op">,</span> value<span class="op">:</span> <span class="op">&amp;</span><span class="kw">dyn</span> <span class="bu">Debug</span>)<span class="op">;</span></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> record_value(<span class="op">&amp;</span><span class="kw">mut</span> <span class="kw">self</span><span class="op">,</span> field<span class="op">:</span> <span class="op">&amp;</span>Field<span class="op">,</span> value<span class="op">:</span> Value<span class="op">&lt;</span><span class="ot">&#39;_</span><span class="op">&gt;</span>) <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> record_f64(<span class="op">&amp;</span><span class="kw">mut</span> <span class="kw">self</span><span class="op">,</span> field<span class="op">:</span> <span class="op">&amp;</span>Field<span class="op">,</span> value<span class="op">:</span> <span class="dt">f64</span>) <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> record_i64(<span class="op">&amp;</span><span class="kw">mut</span> <span class="kw">self</span><span class="op">,</span> field<span class="op">:</span> <span class="op">&amp;</span>Field<span class="op">,</span> value<span class="op">:</span> <span class="dt">i64</span>) <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> record_u64(<span class="op">&amp;</span><span class="kw">mut</span> <span class="kw">self</span><span class="op">,</span> field<span class="op">:</span> <span class="op">&amp;</span>Field<span class="op">,</span> value<span class="op">:</span> <span class="dt">u64</span>) <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> record_i128(<span class="op">&amp;</span><span class="kw">mut</span> <span class="kw">self</span><span class="op">,</span> field<span class="op">:</span> <span class="op">&amp;</span>Field<span class="op">,</span> value<span class="op">:</span> <span class="dt">i128</span>) <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> record_u128(<span class="op">&amp;</span><span class="kw">mut</span> <span class="kw">self</span><span class="op">,</span> field<span class="op">:</span> <span class="op">&amp;</span>Field<span class="op">,</span> value<span class="op">:</span> <span class="dt">u128</span>) <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> record_bool(<span class="op">&amp;</span><span class="kw">mut</span> <span class="kw">self</span><span class="op">,</span> field<span class="op">:</span> <span class="op">&amp;</span>Field<span class="op">,</span> value<span class="op">:</span> <span class="dt">bool</span>) <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> record_str(<span class="op">&amp;</span><span class="kw">mut</span> <span class="kw">self</span><span class="op">,</span> field<span class="op">:</span> <span class="op">&amp;</span>Field<span class="op">,</span> value<span class="op">:</span> <span class="op">&amp;</span><span class="dt">str</span>) <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> record_error(</span>
<span id="cb22-13"><a href="#cb22-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">&amp;</span><span class="kw">mut</span> <span class="kw">self</span><span class="op">,</span> </span>
<span id="cb22-14"><a href="#cb22-14" aria-hidden="true" tabindex="-1"></a>        field<span class="op">:</span> <span class="op">&amp;</span>Field<span class="op">,</span> </span>
<span id="cb22-15"><a href="#cb22-15" aria-hidden="true" tabindex="-1"></a>        value<span class="op">:</span> <span class="op">&amp;</span>(<span class="kw">dyn</span> <span class="bu">Error</span> <span class="op">+</span> <span class="ot">&#39;static</span>)</span>
<span id="cb22-16"><a href="#cb22-16" aria-hidden="true" tabindex="-1"></a>    ) <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb22-17"><a href="#cb22-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Values can therefore be a base numeric type (<code>f64</code>, <code>i64</code>, <code>u64</code>, <code>i128</code>, <code>u128</code>), a boolean, a string, a Rust Error, or anything that has a Debug representation. In addition, there is support for values defined via the <a href="https://docs.rs/valuable/latest/valuable/">valuable crate</a>, which allows for more arbitrary introspection.</p>
<p>This can be seen as a more "typed" version of the system in <code>µ/log</code>. Events are still made up of "plain data" but the rolodex of what is allowed has a more explicit structure.</p>
<p>Similar to the current state of things in Java, there is a large portion of the ecosystem which primarily logs text based messages, often through the <a href="https://crates.io/crates/log"><code>log</code> crate</a>. To deal with this, they provide a crate which massages the text based messages into tracing events called <a href="https://docs.rs/tracing-log/latest/tracing_log/"><code>tracing_log</code></a>.</p>
<p>For more comprehensive coverage, I recommend perusing <a href="https://www.youtube.com/watch?v=engm2Wqfgjk">this RustConf talk</a> inclusive or <a href="https://tokio.rs/blog/2019-08-tracing">this blog post</a>, both by <code>tracing</code>'s primary maintainer.</p>
<h3 id="slf4j">SLF4J</h3>
<p>The most popular logging facade for Java is <a href="https://www.slf4j.org/news.html">SLF4J</a>. Logging libraries like <a href="https://logback.qos.ch/">Logback</a> and <a href="https://logging.apache.org/log4j/2.x/">Log4J</a> provide a superset or a <a href="https://en.wikipedia.org/wiki/Log4Shell">super-dee-duperset</a> of its functionality while acting as the implementation for any code that calls <a href="https://www.slf4j.org/news.html">SLF4J</a>.</p>
<p>Nowadays, the mechanism for a library to "act as the implementation" is to provide an implementation of <a href="https://www.slf4j.org/api/org/slf4j/spi/SLF4JServiceProvider.html">org.slf4j.spi.SLF4JServiceProvider</a> via the <a href="https://mccue.dev/pages/1-20-22-service-provider-interface">service loader mechanism</a>.</p>
<p>Most Java developers only need to interact with this at the level of knowing that they need to add both the <code>slf4j-api</code> and <code>logback-classic</code> as dependencies to their project. I still think it is worth noting because this ability to pick a logging implementation at runtime has been crucial to SLF4J's success.</p>
<p>In the most common usage pattern, a <code>private static final</code> field is set to the result of calling <code>LoggerFactory.getLogger(Class&lt;?&gt;)</code>. This gets a logger where logged messages know about the class they are logged from.</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">static</span> <span class="dt">final</span> <span class="bu">Logger</span> log <span class="op">=</span> </span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>            LoggerFactory<span class="op">.</span><span class="fu">getLogger</span><span class="op">(</span>Main<span class="op">.</span><span class="fu">class</span><span class="op">);</span></span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a>        log<span class="op">.</span><span class="fu">info</span><span class="op">(</span><span class="st">&quot;Hello, world&quot;</span><span class="op">);</span></span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Log messages can be plain english.</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a>log<span class="op">.</span><span class="fu">warn</span><span class="op">(</span><span class="st">&quot;Somebody stole my plain bagel!&quot;</span><span class="op">);</span></span></code></pre></div>
<p>Or they can contain placeholders for data to be formatted into.</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a>log<span class="op">.</span><span class="fu">info</span><span class="op">(</span><span class="st">&quot;I just reached level {} in Mouse Quest&quot;</span><span class="op">,</span> <span class="dv">987413</span><span class="op">);</span></span></code></pre></div>
<p>With special support for logging exceptions.</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a>log<span class="op">.</span><span class="fu">error</span><span class="op">(</span><span class="st">&quot;Hulu gives me 5 ads in a row and I pay for it!&quot;</span><span class="op">,</span> e<span class="op">);</span></span></code></pre></div>
<p>Every log is associated with a level just like <code>tracing</code>. This functions as metadata as usual, but can also be used to avoid making potentially expensive log calls when the associated level is not enabled.</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>log<span class="op">.</span><span class="fu">isDebugEnabled</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>    log<span class="op">.</span><span class="fu">debug</span><span class="op">(</span><span class="st">&quot;expensive data here {}&quot;</span><span class="op">,</span> <span class="fu">expensiveProcesss</span><span class="op">());</span></span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Unlike tracing, data associated with the log is intended to be directly stuffed into the message. Despite the goal being ostensibly to produce english, pseudo-structured logs tend to be common.</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a>log<span class="op">.</span><span class="fu">info</span><span class="op">(</span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;Staring background process: batchId={}, startTime={}&quot;</span><span class="op">,</span></span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a>    batchId<span class="op">,</span></span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a>    startTime</span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span></code></pre></div>
<p>That being said, there <em>is</em> some support for attaching structured data via the "Mapped Diagnostic Context" (MDC) API.</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="cf">try</span> <span class="op">{</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>    MDC<span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;request_id&quot;</span><span class="op">,</span> request_id<span class="op">);</span></span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a>    log<span class="op">.</span><span class="fu">info</span><span class="op">(</span><span class="st">&quot;This will have the request id available&quot;</span><span class="op">);</span></span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="cf">finally</span> <span class="op">{</span></span>
<span id="cb29-6"><a href="#cb29-6" aria-hidden="true" tabindex="-1"></a>    MDC<span class="op">.</span><span class="fu">clear</span><span class="op">();</span></span>
<span id="cb29-7"><a href="#cb29-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>But that system is mechanically cumbersome to use and needs to be configured explicitly within the underlying logging implementation. <a href="https://grep.app/search?q=MDC.put&amp;case=true">People don't use it that often</a>.</p>
<p>It also has no way to become compatible with the upcoming <a href="https://openjdk.org/jeps/429"><code>ExtentLocal</code></a> API, so implementations are forever locked to using <a href="https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/lang/ThreadLocal.html"><code>ThreadLocal</code></a>s.</p>
<div class="sourceCode" id="cb30"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="co">// This try/finally structure cannot be adapted.</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a><span class="cf">try</span> <span class="op">{</span></span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a>    MDC<span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;something&quot;</span><span class="op">,</span> <span class="st">&quot;abc&quot;</span><span class="op">);</span></span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="cf">finally</span> <span class="op">{</span></span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a>    MDC<span class="op">.</span><span class="fu">clear</span><span class="op">();</span></span>
<span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-8"><a href="#cb30-8" aria-hidden="true" tabindex="-1"></a><span class="co">// because ExtentLocals will only be able to be set in callbacks</span></span>
<span id="cb30-9"><a href="#cb30-9" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">final</span> ExtentLocal<span class="op">&lt;</span><span class="bu">Context</span><span class="op">&gt;</span> CONTEXT <span class="op">=</span> <span class="kw">new</span> ExtentLocal<span class="op">&lt;&gt;();</span></span>
<span id="cb30-10"><a href="#cb30-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-11"><a href="#cb30-11" aria-hidden="true" tabindex="-1"></a>ExtendLocal<span class="op">.</span><span class="fu">where</span><span class="op">(</span>CONTEXT<span class="op">,</span> <span class="kw">...</span><span class="op">)</span></span>
<span id="cb30-12"><a href="#cb30-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">run</span><span class="op">(()</span> <span class="op">-&gt;</span> <span class="op">{</span> <span class="co">/* code here */</span> <span class="op">})</span></span></code></pre></div>
<p>This is a problem, or at least potentially a problem, because <a href="https://openjdk.org/jeps/429"><code>ExtentLocal</code></a>s are designed to be considerably more efficient with a high number of threads. High numbers of threads will hopefully become the norm with Java 19+, so its worth thinking about.</p>
<p>And as of the <a href="https://www.slf4j.org/news.html">very latest version</a> there is now also an api for doing structured logging directly with <a href="https://www.slf4j.org/api/org/slf4j/event/KeyValuePair.html"><code>KeyValuePair</code></a>s and the fluent logging api.</p>
<div class="sourceCode" id="cb31"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a>logger<span class="op">.</span><span class="fu">atInfo</span><span class="op">()</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">addKeyValue</span><span class="op">(</span><span class="st">&quot;cat&quot;</span><span class="op">,</span> <span class="st">&quot;fred&quot;</span><span class="op">)</span></span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">addKeyValue</span><span class="op">(</span><span class="st">&quot;snuggles&quot;</span><span class="op">,</span> <span class="kw">true</span><span class="op">)</span></span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">log</span><span class="op">(</span><span class="st">&quot;I love this cat.&quot;</span><span class="op">);</span></span></code></pre></div>
<p>I'd say <a href="https://www.reddit.com/r/java/comments/cgswxz/comment/eukttut/?utm_source=share&amp;utm_medium=web2x&amp;context=3">the jury is out</a> on whether this actually will lead to many folks doing any degree of structured logging in practice, but it is certainly a welcome addition.</p>
<h3 id="systemlogger">System.Logger</h3>
<p><a href="(https://openjdk.org/jeps/264)">Since Java 9</a>, there has actually been a logger bundled which functions somewhat similarly to SLF4J. The major points of distinction are that there are no explicit <code>info</code>, <code>warn</code>, <code>error</code>, etc. methods for logging at a particular level, there is direct support for localization via a <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/ResourceBundle.html">ResourceBundle</a>, and there is no parallel to MDC.</p>
<div class="sourceCode" id="cb32"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">interface</span> <span class="bu">Logger</span> <span class="op">{</span></span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">String</span> <span class="fu">getName</span><span class="op">();</span></span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">boolean</span> <span class="fu">isLoggable</span><span class="op">(</span><span class="bu">Level</span> level<span class="op">);</span></span>
<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="dt">void</span> <span class="fu">log</span><span class="op">(</span><span class="bu">Level</span> level<span class="op">,</span> <span class="bu">String</span> msg<span class="op">)</span> <span class="op">{</span></span>
<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb32-8"><a href="#cb32-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb32-9"><a href="#cb32-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-10"><a href="#cb32-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="dt">void</span> <span class="fu">log</span><span class="op">(</span><span class="bu">Level</span> level<span class="op">,</span> Supplier<span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> msgSupplier<span class="op">)</span> <span class="op">{</span></span>
<span id="cb32-11"><a href="#cb32-11" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb32-12"><a href="#cb32-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb32-13"><a href="#cb32-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-14"><a href="#cb32-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="dt">void</span> <span class="fu">log</span><span class="op">(</span><span class="bu">Level</span> level<span class="op">,</span> <span class="bu">Object</span> obj<span class="op">)</span> <span class="op">{</span></span>
<span id="cb32-15"><a href="#cb32-15" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb32-16"><a href="#cb32-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb32-17"><a href="#cb32-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-18"><a href="#cb32-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="dt">void</span> <span class="fu">log</span><span class="op">(</span><span class="bu">Level</span> level<span class="op">,</span> <span class="bu">String</span> msg<span class="op">,</span> <span class="bu">Throwable</span> thrown<span class="op">)</span> <span class="op">{</span></span>
<span id="cb32-19"><a href="#cb32-19" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb32-20"><a href="#cb32-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb32-21"><a href="#cb32-21" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb32-22"><a href="#cb32-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="dt">void</span> <span class="fu">log</span><span class="op">(</span><span class="bu">Level</span> level<span class="op">,</span> Supplier<span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> msgSupplier<span class="op">,</span></span>
<span id="cb32-23"><a href="#cb32-23" aria-hidden="true" tabindex="-1"></a>                     <span class="bu">Throwable</span> thrown<span class="op">)</span> <span class="op">{</span></span>
<span id="cb32-24"><a href="#cb32-24" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb32-25"><a href="#cb32-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb32-26"><a href="#cb32-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-27"><a href="#cb32-27" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="dt">void</span> <span class="fu">log</span><span class="op">(</span><span class="bu">Level</span> level<span class="op">,</span> <span class="bu">String</span> format<span class="op">,</span> <span class="bu">Object</span><span class="kw">...</span> params<span class="op">)</span> <span class="op">{</span></span>
<span id="cb32-28"><a href="#cb32-28" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb32-29"><a href="#cb32-29" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb32-30"><a href="#cb32-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-31"><a href="#cb32-31" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">log</span><span class="op">(</span><span class="bu">Level</span> level<span class="op">,</span> <span class="bu">ResourceBundle</span> bundle<span class="op">,</span> <span class="bu">String</span> msg<span class="op">,</span></span>
<span id="cb32-32"><a href="#cb32-32" aria-hidden="true" tabindex="-1"></a>             <span class="bu">Throwable</span> thrown<span class="op">);</span></span>
<span id="cb32-33"><a href="#cb32-33" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb32-34"><a href="#cb32-34" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">log</span><span class="op">(</span><span class="bu">Level</span> level<span class="op">,</span> <span class="bu">ResourceBundle</span> bundle<span class="op">,</span> <span class="bu">String</span> format<span class="op">,</span></span>
<span id="cb32-35"><a href="#cb32-35" aria-hidden="true" tabindex="-1"></a>             <span class="bu">Object</span><span class="kw">...</span> params<span class="op">);</span></span>
<span id="cb32-36"><a href="#cb32-36" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="opentelemetry">OpenTelemetry</h3>
<p><a href="https://opentelemetry.io/">OpenTelemetry</a> is definitely worth a mention, if not solely for the voice in the back of my head telling me that I am just making that but poorly and less well-thought-out.</p>
<p>OpenTelemetry defines <a href="https://github.com/open-telemetry/opentelemetry-specification">a set of language agnostic standards</a> for how "observability data" should be recorded within an application and how it should be communicated and propagated to the rest of the system.</p>
<p>I am going to make the <a href="https://www.youtube.com/watch?v=nuIw3m96jMQ">controversial, yet brave</a> decision to not explain much of it here. <a href="https://opentelemetry.io/docs/concepts/">The documentation is far more thorough than I can be</a> and enough of the concepts overlap that explaining the distinctions between what I'm writing and what the OpenTelemetry automatic and manual instrumentation libraries provide would double the size of this post.</p>
<p>My hope is that what comes out of this whole thought experiment could potentially serve as a frontend to its manual instrumentation component, but I'm not going to make that a focus.</p>
<p>It is overall pretty cool though. If I had to give anything concretely negative about it, it would be that my first experience using the automatic instrumentation library was it causing the startup time for a few services to exceed our health check grace period. That sucked.</p>
<p>As of right now though, luckily for me, <a href="https://opentelemetry.io/docs/reference/specification/logs/overview/#plain-text-formats">OpenTelemetry doesn't provide a stable way to emit structured logs</a>.</p>
<h2 id="design">Design</h2>
<p>Going in to this I want something which</p>
<ol>
    <li id="goal-1"> Hits the same general notes as `µ/log` and `tracing`. </li>
    <li id="goal-2"> Is tolerable to existing Java programmers. </li>
    <li id="goal-3"> Is suitable for inclusion in libraries just like SLF4J. </li>
</ol>

<h3 id="logger">Logger</h3>
<p>So first task on the docket is to make an interface for our logger.</p>
<div class="sourceCode" id="cb33"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="co">/**</span></span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a> <span class="co">*</span> A logger<span class="co">.</span></span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a> <span class="co">*/</span></span>
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">interface</span> <span class="bu">Logger</span> <span class="op">{</span></span>
<span id="cb33-5"><a href="#cb33-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">/**</span></span>
<span id="cb33-6"><a href="#cb33-6" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> Logs the log<span class="co">.</span></span>
<span id="cb33-7"><a href="#cb33-7" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span></span>
<span id="cb33-8"><a href="#cb33-8" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> <span class="co">@</span>param log The log to log<span class="co">.</span></span>
<span id="cb33-9"><a href="#cb33-9" aria-hidden="true" tabindex="-1"></a>     <span class="co">*/</span></span>
<span id="cb33-10"><a href="#cb33-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">log</span><span class="op">(</span>Log log<span class="op">);</span></span>
<span id="cb33-11"><a href="#cb33-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Nailed it.</p>
<p>Now, there is actually some deeper reasoning here. In <code>µ/log</code>'s design all logs are juggled between ring buffers and passed between different consumers. Doing that is a lot easier when we make a <code>Log</code> a concrete thing that can be passed around.</p>
<p><code>µ/log</code> also gets away with no equivalent of <code>tracing</code>'s <code>span_enter</code> and <code>span_exit</code>. This leads me to believe (hand wavingly) that if you aren't in the pursuit of true zero cost like rust is, it is fine to only perform actions on <code>span_exit</code> and have the logic usually covered by <code>span_enter</code> (starting the timer, assigning an id, etc.) be handled in another way.</p>
<p>So a single log method it is. Default methods can and will be added to make a more pleasant API, but that's the start.</p>
<h3 id="log">Log</h3>
<p>Now as to what constitutes a <code>Log</code>, at this stage I haven't laid out the full picture, so it's hard to talk about. I do think, however, that delineating <code>Event</code>s and <code>Span</code>s like <code>tracing</code> would be a good idea.</p>
<p><code>µ/log</code> doesn't need to care about this because it is Clojure. In a dynamic language it is an expected sort of pattern to say "if this map has <code>:mulog/root-trace</code> and <code>:mulog/duration</code> it represents a span." You can see that exact example in its <a href="https://github.com/BrunoBonacci/mulog/blob/master/mulog-zipkin/src/com/brunobonacci/mulog/publishers/zipkin.clj#L56">zipkin publisher</a></p>
<p>The best tool I know of for directly representing this is <a href="https://openjdk.org/jeps/409">sealed interfaces</a>.</p>
<div class="sourceCode" id="cb34"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> sealed <span class="kw">interface</span> Log <span class="op">{</span></span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Event</span><span class="op">()</span> <span class="kw">implements</span> Log <span class="op">{}</span></span>
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">Span</span><span class="op">()</span> <span class="kw">implements</span> Log <span class="op">{}</span></span>
<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>You can read this as "a <code>Log</code> is either an <code>Event</code> or a <code>Span</code>." Any information common to the two cases will be added to the interface as we move along.</p>
<h3 id="level">Level</h3>
<p><code>tracing</code> has log levels and <code>µ/log</code> does not.</p>
<p>The way I see it, there are ways to think about levels.</p>
<ol type="1">
<li>Log levels aren't intrinsically special. If you want a standard way to indicate "severity" you can always agree on a standard for your codebase, but it's not something to force on the user.</li>
<li>Log levels are intrinsically special. It is a type of metadata you basically always want, and they act as a good first pass for filtering noisy events out of production.</li>
</ol>
<p>I bounced back and forth for a bit, but <a href="#goal-2">Goal #2</a> tips the scales. Java programmers are used to levels, let them have levels.</p>
<div class="sourceCode" id="cb35"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="bu">Level</span> <span class="op">{</span></span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a>    TRACE<span class="op">,</span></span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a>    DEBUG<span class="op">,</span></span>
<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a>    INFO<span class="op">,</span></span>
<span id="cb35-5"><a href="#cb35-5" aria-hidden="true" tabindex="-1"></a>    WARN<span class="op">,</span></span>
<span id="cb35-6"><a href="#cb35-6" aria-hidden="true" tabindex="-1"></a>    ERROR</span>
<span id="cb35-7"><a href="#cb35-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>If there are situations that arise in practice where no log level is appropriate a dedicated "unspecified" level could make sense, but I'm putting that in my back pocket for now.</p>
<div class="sourceCode" id="cb36"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="bu">Level</span> <span class="op">{</span></span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a>    UNSPECIFIED<span class="op">,</span></span>
<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a>    TRACE<span class="op">,</span></span>
<span id="cb36-4"><a href="#cb36-4" aria-hidden="true" tabindex="-1"></a>    DEBUG<span class="op">,</span></span>
<span id="cb36-5"><a href="#cb36-5" aria-hidden="true" tabindex="-1"></a>    INFO<span class="op">,</span></span>
<span id="cb36-6"><a href="#cb36-6" aria-hidden="true" tabindex="-1"></a>    WARN<span class="op">,</span></span>
<span id="cb36-7"><a href="#cb36-7" aria-hidden="true" tabindex="-1"></a>    ERROR</span>
<span id="cb36-8"><a href="#cb36-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>If not for <a href="#goal-2">Goal #2</a> there is no intrinsic reason these need to be the log levels either, but c'est la vie.</p>
<div class="sourceCode" id="cb37"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="bu">Level</span> <span class="op">{</span></span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a>    DEVELOPMENT_ONLY<span class="op">,</span></span>
<span id="cb37-3"><a href="#cb37-3" aria-hidden="true" tabindex="-1"></a>    FIX_DURING_WORK_HOURS<span class="op">,</span></span>
<span id="cb37-4"><a href="#cb37-4" aria-hidden="true" tabindex="-1"></a>    WAKE_ME_UP_IN_THE_MIDDLE_OF_THE_NIGHT</span>
<span id="cb37-5"><a href="#cb37-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>I am also choosing to nest this enum inside the <code>Log</code> interface.</p>
<div class="sourceCode" id="cb38"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> sealed <span class="kw">interface</span> Log <span class="op">{</span></span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Event</span><span class="op">()</span> <span class="kw">implements</span> Log <span class="op">{}</span></span>
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">Span</span><span class="op">()</span> <span class="kw">implements</span> Log <span class="op">{}</span></span>
<span id="cb38-4"><a href="#cb38-4" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb38-5"><a href="#cb38-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">enum</span> <span class="bu">Level</span> <span class="op">{</span></span>
<span id="cb38-6"><a href="#cb38-6" aria-hidden="true" tabindex="-1"></a>        TRACE<span class="op">,</span></span>
<span id="cb38-7"><a href="#cb38-7" aria-hidden="true" tabindex="-1"></a>        DEBUG<span class="op">,</span></span>
<span id="cb38-8"><a href="#cb38-8" aria-hidden="true" tabindex="-1"></a>        INFO<span class="op">,</span></span>
<span id="cb38-9"><a href="#cb38-9" aria-hidden="true" tabindex="-1"></a>        WARN<span class="op">,</span></span>
<span id="cb38-10"><a href="#cb38-10" aria-hidden="true" tabindex="-1"></a>        ERROR</span>
<span id="cb38-11"><a href="#cb38-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb38-12"><a href="#cb38-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This is a stylistic choice more than anything, but I like being able to refer to <code>Log.Level</code> as such. Not only does the pattern give one place for discovery - just type <code>Log.</code> in your IDE to see the full set of log related types - it can save me from having to add <code>Log</code> as a prefix to class names.</p>
<p>Both <code>Event</code>s and <code>Span</code>s should have log levels, so that is represented like so.</p>
<div class="sourceCode" id="cb39"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> sealed <span class="kw">interface</span> Log <span class="op">{</span></span>
<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Level</span> <span class="fu">level</span><span class="op">();</span></span>
<span id="cb39-3"><a href="#cb39-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb39-4"><a href="#cb39-4" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Event</span><span class="op">(</span></span>
<span id="cb39-5"><a href="#cb39-5" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Level</span> level</span>
<span id="cb39-6"><a href="#cb39-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">implements</span> Log <span class="op">{}</span></span>
<span id="cb39-7"><a href="#cb39-7" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb39-8"><a href="#cb39-8" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">Span</span><span class="op">(</span></span>
<span id="cb39-9"><a href="#cb39-9" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Level</span> level</span>
<span id="cb39-10"><a href="#cb39-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">implements</span> Log <span class="op">{}</span></span>
<span id="cb39-11"><a href="#cb39-11" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb39-12"><a href="#cb39-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">enum</span> <span class="bu">Level</span> <span class="op">{</span></span>
<span id="cb39-13"><a href="#cb39-13" aria-hidden="true" tabindex="-1"></a>        TRACE<span class="op">,</span></span>
<span id="cb39-14"><a href="#cb39-14" aria-hidden="true" tabindex="-1"></a>        DEBUG<span class="op">,</span></span>
<span id="cb39-15"><a href="#cb39-15" aria-hidden="true" tabindex="-1"></a>        INFO<span class="op">,</span></span>
<span id="cb39-16"><a href="#cb39-16" aria-hidden="true" tabindex="-1"></a>        WARN<span class="op">,</span></span>
<span id="cb39-17"><a href="#cb39-17" aria-hidden="true" tabindex="-1"></a>        ERROR</span>
<span id="cb39-18"><a href="#cb39-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb39-19"><a href="#cb39-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="categories">Categories</h3>
<p>I think <code>µ/log</code> had the right idea. Most logs should have both a "namespace" and a "name" component as their identifier. It is a pattern I think is pretty common in systems meant to take in structured data.</p>
<p>One example: Cloudwatch wants both a <a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/CloudWatchEventsandEventPatterns.html">"source" and "detail-type"</a> for their events.</p>
<div class="sourceCode" id="cb40"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span></span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;version&quot;</span><span class="fu">:</span> <span class="st">&quot;0&quot;</span><span class="fu">,</span></span>
<span id="cb40-3"><a href="#cb40-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;id&quot;</span><span class="fu">:</span> <span class="st">&quot;6a7e8feb-b491-4cf7-a9f1-bf3703467718&quot;</span><span class="fu">,</span></span>
<span id="cb40-4"><a href="#cb40-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;detail-type&quot;</span><span class="fu">:</span> <span class="st">&quot;EC2 Instance State-change Notification&quot;</span><span class="fu">,</span></span>
<span id="cb40-5"><a href="#cb40-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;source&quot;</span><span class="fu">:</span> <span class="st">&quot;aws.ec2&quot;</span><span class="fu">,</span></span>
<span id="cb40-6"><a href="#cb40-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;account&quot;</span><span class="fu">:</span> <span class="st">&quot;111122223333&quot;</span><span class="fu">,</span></span>
<span id="cb40-7"><a href="#cb40-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;time&quot;</span><span class="fu">:</span> <span class="st">&quot;2017-12-22T18:43:48Z&quot;</span><span class="fu">,</span></span>
<span id="cb40-8"><a href="#cb40-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;region&quot;</span><span class="fu">:</span> <span class="st">&quot;us-west-1&quot;</span><span class="fu">,</span></span>
<span id="cb40-9"><a href="#cb40-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;resources&quot;</span><span class="fu">:</span> <span class="ot">[</span></span>
<span id="cb40-10"><a href="#cb40-10" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;arn:aws:ec2:us-west-1:123456789012:instance/ i-1234567890abcdef0&quot;</span></span>
<span id="cb40-11"><a href="#cb40-11" aria-hidden="true" tabindex="-1"></a>  <span class="ot">]</span><span class="fu">,</span></span>
<span id="cb40-12"><a href="#cb40-12" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;detail&quot;</span><span class="fu">:</span> <span class="fu">{</span></span>
<span id="cb40-13"><a href="#cb40-13" aria-hidden="true" tabindex="-1"></a>    <span class="dt">&quot;instance-id&quot;</span><span class="fu">:</span> <span class="st">&quot; i-1234567890abcdef0&quot;</span><span class="fu">,</span></span>
<span id="cb40-14"><a href="#cb40-14" aria-hidden="true" tabindex="-1"></a>    <span class="dt">&quot;state&quot;</span><span class="fu">:</span> <span class="st">&quot;terminated&quot;</span></span>
<span id="cb40-15"><a href="#cb40-15" aria-hidden="true" tabindex="-1"></a>  <span class="fu">}</span></span>
<span id="cb40-16"><a href="#cb40-16" aria-hidden="true" tabindex="-1"></a><span class="fu">}</span></span></code></pre></div>
<p>It also gives a convenient analogue to the "class doing the logging" and "log message" that programmers are already used to. I'll call the pair of these two pieces the log's "category."</p>
<div class="sourceCode" id="cb41"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> sealed <span class="kw">interface</span> Log <span class="op">{</span></span>
<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb41-3"><a href="#cb41-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb41-4"><a href="#cb41-4" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">Category</span><span class="op">(</span><span class="bu">String</span> namespace<span class="op">,</span> <span class="bu">String</span> name<span class="op">)</span> <span class="op">{</span></span>
<span id="cb41-5"><a href="#cb41-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb41-6"><a href="#cb41-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb41-7"><a href="#cb41-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>I can't imagine <code>Event</code>s having categories but <code>Span</code>s not having them so they both get them.</p>
<div class="sourceCode" id="cb42"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb42-1"><a href="#cb42-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> sealed <span class="kw">interface</span> Log <span class="op">{</span></span>
<span id="cb42-2"><a href="#cb42-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Level</span> <span class="fu">level</span><span class="op">();</span></span>
<span id="cb42-3"><a href="#cb42-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb42-4"><a href="#cb42-4" aria-hidden="true" tabindex="-1"></a>    Category <span class="fu">category</span><span class="op">();</span></span>
<span id="cb42-5"><a href="#cb42-5" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb42-6"><a href="#cb42-6" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Event</span><span class="op">(</span></span>
<span id="cb42-7"><a href="#cb42-7" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb42-8"><a href="#cb42-8" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Category category</span>
<span id="cb42-9"><a href="#cb42-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">implements</span> Log <span class="op">{}</span></span>
<span id="cb42-10"><a href="#cb42-10" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb42-11"><a href="#cb42-11" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">Span</span><span class="op">(</span></span>
<span id="cb42-12"><a href="#cb42-12" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb42-13"><a href="#cb42-13" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Category category</span>
<span id="cb42-14"><a href="#cb42-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">implements</span> Log <span class="op">{}</span></span>
<span id="cb42-15"><a href="#cb42-15" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb42-16"><a href="#cb42-16" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb42-17"><a href="#cb42-17" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb42-18"><a href="#cb42-18" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">Category</span><span class="op">(</span><span class="bu">String</span> namespace<span class="op">,</span> <span class="bu">String</span> name<span class="op">)</span> <span class="op">{</span></span>
<span id="cb42-19"><a href="#cb42-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-20"><a href="#cb42-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb42-21"><a href="#cb42-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="loggernamespaced">Logger.Namespaced</h3>
<p>At this point we can start to sketch out what logging would look like.</p>
<div class="sourceCode" id="cb43"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb43-1"><a href="#cb43-1" aria-hidden="true" tabindex="-1"></a><span class="bu">Logger</span> log <span class="op">=</span> <span class="kw">...</span><span class="op">;</span></span>
<span id="cb43-2"><a href="#cb43-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb43-3"><a href="#cb43-3" aria-hidden="true" tabindex="-1"></a>log<span class="op">.</span><span class="fu">log</span><span class="op">(</span></span>
<span id="cb43-4"><a href="#cb43-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">new</span> Log<span class="op">.</span><span class="fu">Event</span><span class="op">(</span></span>
<span id="cb43-5"><a href="#cb43-5" aria-hidden="true" tabindex="-1"></a>        Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">INFO</span><span class="op">,</span> </span>
<span id="cb43-6"><a href="#cb43-6" aria-hidden="true" tabindex="-1"></a>        <span class="kw">new</span> Log<span class="op">.</span><span class="fu">Category</span><span class="op">(</span><span class="st">&quot;some.Thing&quot;</span><span class="op">,</span> <span class="st">&quot;thing-happened&quot;</span><span class="op">)</span></span>
<span id="cb43-7"><a href="#cb43-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span></span>
<span id="cb43-8"><a href="#cb43-8" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span></code></pre></div>
<p>Hideous.</p>
<p>So clearly some helper methods are in order.</p>
<p>To start, one helper method for logging an event. Spans can come later.</p>
<div class="sourceCode" id="cb44"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb44-1"><a href="#cb44-1" aria-hidden="true" tabindex="-1"></a><span class="co">/**</span></span>
<span id="cb44-2"><a href="#cb44-2" aria-hidden="true" tabindex="-1"></a> <span class="co">*</span> A logger<span class="co">.</span></span>
<span id="cb44-3"><a href="#cb44-3" aria-hidden="true" tabindex="-1"></a> <span class="co">*/</span></span>
<span id="cb44-4"><a href="#cb44-4" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">interface</span> <span class="bu">Logger</span> <span class="op">{</span></span>
<span id="cb44-5"><a href="#cb44-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">/**</span></span>
<span id="cb44-6"><a href="#cb44-6" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> Logs the log<span class="co">.</span></span>
<span id="cb44-7"><a href="#cb44-7" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span></span>
<span id="cb44-8"><a href="#cb44-8" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> <span class="co">@</span>param log The log to log<span class="co">.</span></span>
<span id="cb44-9"><a href="#cb44-9" aria-hidden="true" tabindex="-1"></a>     <span class="co">*/</span></span>
<span id="cb44-10"><a href="#cb44-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">log</span><span class="op">(</span>Log log<span class="op">);</span></span>
<span id="cb44-11"><a href="#cb44-11" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb44-12"><a href="#cb44-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="dt">void</span> <span class="fu">event</span><span class="op">(</span></span>
<span id="cb44-13"><a href="#cb44-13" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Level</span> level<span class="op">,</span></span>
<span id="cb44-14"><a href="#cb44-14" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Category</span> category</span>
<span id="cb44-15"><a href="#cb44-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb44-16"><a href="#cb44-16" aria-hidden="true" tabindex="-1"></a>        <span class="fu">log</span><span class="op">(</span><span class="kw">new</span> Log<span class="op">.</span><span class="fu">Event</span><span class="op">(</span>level<span class="op">,</span> category<span class="op">));</span></span>
<span id="cb44-17"><a href="#cb44-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb44-18"><a href="#cb44-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>So now the verbose <code>new Log.Event</code> call is not needed.</p>
<div class="sourceCode" id="cb45"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb45-1"><a href="#cb45-1" aria-hidden="true" tabindex="-1"></a><span class="bu">Logger</span> log <span class="op">=</span> <span class="kw">...</span><span class="op">;</span></span>
<span id="cb45-2"><a href="#cb45-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb45-3"><a href="#cb45-3" aria-hidden="true" tabindex="-1"></a>log<span class="op">.</span><span class="fu">event</span><span class="op">(</span></span>
<span id="cb45-4"><a href="#cb45-4" aria-hidden="true" tabindex="-1"></a>    Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">INFO</span><span class="op">,</span> </span>
<span id="cb45-5"><a href="#cb45-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">new</span> Log<span class="op">.</span><span class="fu">Category</span><span class="op">(</span><span class="st">&quot;some.Thing&quot;</span><span class="op">,</span> <span class="st">&quot;thing-happened&quot;</span><span class="op">)</span></span>
<span id="cb45-6"><a href="#cb45-6" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span></code></pre></div>
<p>Next, it is common to have a dedicated method for each log level.</p>
<div class="sourceCode" id="cb46"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb46-1"><a href="#cb46-1" aria-hidden="true" tabindex="-1"></a><span class="co">/**</span></span>
<span id="cb46-2"><a href="#cb46-2" aria-hidden="true" tabindex="-1"></a> <span class="co">*</span> A logger<span class="co">.</span></span>
<span id="cb46-3"><a href="#cb46-3" aria-hidden="true" tabindex="-1"></a> <span class="co">*/</span></span>
<span id="cb46-4"><a href="#cb46-4" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">interface</span> <span class="bu">Logger</span> <span class="op">{</span></span>
<span id="cb46-5"><a href="#cb46-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">/**</span></span>
<span id="cb46-6"><a href="#cb46-6" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> Logs the log<span class="co">.</span></span>
<span id="cb46-7"><a href="#cb46-7" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span></span>
<span id="cb46-8"><a href="#cb46-8" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> <span class="co">@</span>param log The log to log<span class="co">.</span></span>
<span id="cb46-9"><a href="#cb46-9" aria-hidden="true" tabindex="-1"></a>     <span class="co">*/</span></span>
<span id="cb46-10"><a href="#cb46-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">log</span><span class="op">(</span>Log log<span class="op">);</span></span>
<span id="cb46-11"><a href="#cb46-11" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb46-12"><a href="#cb46-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="dt">void</span> <span class="fu">event</span><span class="op">(</span></span>
<span id="cb46-13"><a href="#cb46-13" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Level</span> level<span class="op">,</span></span>
<span id="cb46-14"><a href="#cb46-14" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Category</span> category</span>
<span id="cb46-15"><a href="#cb46-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb46-16"><a href="#cb46-16" aria-hidden="true" tabindex="-1"></a>        <span class="fu">log</span><span class="op">(</span><span class="kw">new</span> Log<span class="op">.</span><span class="fu">Event</span><span class="op">(</span>level<span class="op">,</span> category<span class="op">));</span></span>
<span id="cb46-17"><a href="#cb46-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb46-18"><a href="#cb46-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-19"><a href="#cb46-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="dt">void</span> <span class="fu">trace</span><span class="op">(</span></span>
<span id="cb46-20"><a href="#cb46-20" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Category</span> category</span>
<span id="cb46-21"><a href="#cb46-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb46-22"><a href="#cb46-22" aria-hidden="true" tabindex="-1"></a>        <span class="fu">event</span><span class="op">(</span>Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">TRACE</span><span class="op">,</span> category<span class="op">);</span></span>
<span id="cb46-23"><a href="#cb46-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb46-24"><a href="#cb46-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-25"><a href="#cb46-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="dt">void</span> <span class="fu">debug</span><span class="op">(</span></span>
<span id="cb46-26"><a href="#cb46-26" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Category</span> category</span>
<span id="cb46-27"><a href="#cb46-27" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb46-28"><a href="#cb46-28" aria-hidden="true" tabindex="-1"></a>        <span class="fu">event</span><span class="op">(</span>Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">DEBUG</span><span class="op">,</span> category<span class="op">);</span></span>
<span id="cb46-29"><a href="#cb46-29" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb46-30"><a href="#cb46-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-31"><a href="#cb46-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="dt">void</span> <span class="fu">info</span><span class="op">(</span></span>
<span id="cb46-32"><a href="#cb46-32" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Category</span> category</span>
<span id="cb46-33"><a href="#cb46-33" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb46-34"><a href="#cb46-34" aria-hidden="true" tabindex="-1"></a>        <span class="fu">event</span><span class="op">(</span>Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">INFO</span><span class="op">,</span> category<span class="op">);</span></span>
<span id="cb46-35"><a href="#cb46-35" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb46-36"><a href="#cb46-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-37"><a href="#cb46-37" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="dt">void</span> <span class="fu">warn</span><span class="op">(</span></span>
<span id="cb46-38"><a href="#cb46-38" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Category</span> category</span>
<span id="cb46-39"><a href="#cb46-39" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb46-40"><a href="#cb46-40" aria-hidden="true" tabindex="-1"></a>        <span class="fu">event</span><span class="op">(</span>Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">WARN</span><span class="op">,</span> category<span class="op">);</span></span>
<span id="cb46-41"><a href="#cb46-41" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb46-42"><a href="#cb46-42" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-43"><a href="#cb46-43" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="dt">void</span> <span class="fu">error</span><span class="op">(</span></span>
<span id="cb46-44"><a href="#cb46-44" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Category</span> category</span>
<span id="cb46-45"><a href="#cb46-45" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb46-46"><a href="#cb46-46" aria-hidden="true" tabindex="-1"></a>        <span class="fu">event</span><span class="op">(</span>Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">ERROR</span><span class="op">,</span> category<span class="op">);</span></span>
<span id="cb46-47"><a href="#cb46-47" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb46-48"><a href="#cb46-48" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb47"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb47-1"><a href="#cb47-1" aria-hidden="true" tabindex="-1"></a><span class="bu">Logger</span> log <span class="op">=</span> <span class="kw">...</span><span class="op">;</span></span>
<span id="cb47-2"><a href="#cb47-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb47-3"><a href="#cb47-3" aria-hidden="true" tabindex="-1"></a>log<span class="op">.</span><span class="fu">info</span><span class="op">(</span><span class="kw">new</span> Log<span class="op">.</span><span class="fu">Category</span><span class="op">(</span><span class="st">&quot;some.Thing&quot;</span><span class="op">,</span> <span class="st">&quot;thing-happened&quot;</span><span class="op">));</span></span></code></pre></div>
<p>This is better still, but the <code>new Log.Category</code> still feels like a lot to ask of folks on every single call.</p>
<p>For most applications, the namespace component of logs emitted from any particular class is likely to stay constant. It is probably going to be the class name.</p>
<p>As such, I think that there should be two types. <code>Logger</code> and <code>Logger.Namespaced</code>. <code>Logger</code> will let folks log while specifying the full <code>Log.Category</code> and <code>Logger.Namespaced</code> will have the namespace part of the category pre-filled.</p>
<div class="sourceCode" id="cb48"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb48-1"><a href="#cb48-1" aria-hidden="true" tabindex="-1"></a><span class="co">/**</span></span>
<span id="cb48-2"><a href="#cb48-2" aria-hidden="true" tabindex="-1"></a> <span class="co">*</span> A logger<span class="co">.</span></span>
<span id="cb48-3"><a href="#cb48-3" aria-hidden="true" tabindex="-1"></a> <span class="co">*/</span></span>
<span id="cb48-4"><a href="#cb48-4" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">interface</span> <span class="bu">Logger</span> <span class="op">{</span></span>
<span id="cb48-5"><a href="#cb48-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">/**</span></span>
<span id="cb48-6"><a href="#cb48-6" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> Logs the log<span class="co">.</span></span>
<span id="cb48-7"><a href="#cb48-7" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span></span>
<span id="cb48-8"><a href="#cb48-8" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> <span class="co">@</span>param log The log to log<span class="co">.</span></span>
<span id="cb48-9"><a href="#cb48-9" aria-hidden="true" tabindex="-1"></a>     <span class="co">*/</span></span>
<span id="cb48-10"><a href="#cb48-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">log</span><span class="op">(</span>Log log<span class="op">);</span></span>
<span id="cb48-11"><a href="#cb48-11" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb48-12"><a href="#cb48-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="dt">void</span> <span class="fu">event</span><span class="op">(</span></span>
<span id="cb48-13"><a href="#cb48-13" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Level</span> level<span class="op">,</span></span>
<span id="cb48-14"><a href="#cb48-14" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Category</span> category</span>
<span id="cb48-15"><a href="#cb48-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb48-16"><a href="#cb48-16" aria-hidden="true" tabindex="-1"></a>        <span class="fu">log</span><span class="op">(</span><span class="kw">new</span> Log<span class="op">.</span><span class="fu">Event</span><span class="op">(</span>level<span class="op">,</span> category<span class="op">));</span></span>
<span id="cb48-17"><a href="#cb48-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb48-18"><a href="#cb48-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb48-19"><a href="#cb48-19" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb48-20"><a href="#cb48-20" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb48-21"><a href="#cb48-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> Namespaced <span class="fu">namespaced</span><span class="op">(</span><span class="bu">String</span> namespace<span class="op">)</span> <span class="op">{</span></span>
<span id="cb48-22"><a href="#cb48-22" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">NamespacedLogger</span><span class="op">(</span>namespace<span class="op">,</span> <span class="kw">this</span><span class="op">);</span></span>
<span id="cb48-23"><a href="#cb48-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb48-24"><a href="#cb48-24" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb48-25"><a href="#cb48-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">interface</span> Namespaced <span class="op">{</span></span>
<span id="cb48-26"><a href="#cb48-26" aria-hidden="true" tabindex="-1"></a>        <span class="dt">void</span> <span class="fu">event</span><span class="op">(</span>Log<span class="op">.</span><span class="fu">Level</span> level<span class="op">,</span> <span class="bu">String</span> name<span class="op">);</span></span>
<span id="cb48-27"><a href="#cb48-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb48-28"><a href="#cb48-28" aria-hidden="true" tabindex="-1"></a>        <span class="kw">default</span> <span class="dt">void</span> <span class="fu">trace</span><span class="op">(</span></span>
<span id="cb48-29"><a href="#cb48-29" aria-hidden="true" tabindex="-1"></a>                <span class="bu">String</span> name</span>
<span id="cb48-30"><a href="#cb48-30" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="op">{</span></span>
<span id="cb48-31"><a href="#cb48-31" aria-hidden="true" tabindex="-1"></a>            <span class="fu">event</span><span class="op">(</span>Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">TRACE</span><span class="op">,</span> name<span class="op">);</span></span>
<span id="cb48-32"><a href="#cb48-32" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb48-33"><a href="#cb48-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb48-34"><a href="#cb48-34" aria-hidden="true" tabindex="-1"></a>        <span class="kw">default</span> <span class="dt">void</span> <span class="fu">debug</span><span class="op">(</span></span>
<span id="cb48-35"><a href="#cb48-35" aria-hidden="true" tabindex="-1"></a>                <span class="bu">String</span> name</span>
<span id="cb48-36"><a href="#cb48-36" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="op">{</span></span>
<span id="cb48-37"><a href="#cb48-37" aria-hidden="true" tabindex="-1"></a>            <span class="fu">event</span><span class="op">(</span>Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">DEBUG</span><span class="op">,</span> name<span class="op">);</span></span>
<span id="cb48-38"><a href="#cb48-38" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb48-39"><a href="#cb48-39" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb48-40"><a href="#cb48-40" aria-hidden="true" tabindex="-1"></a>        <span class="kw">default</span> <span class="dt">void</span> <span class="fu">info</span><span class="op">(</span></span>
<span id="cb48-41"><a href="#cb48-41" aria-hidden="true" tabindex="-1"></a>                <span class="bu">String</span> name</span>
<span id="cb48-42"><a href="#cb48-42" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="op">{</span></span>
<span id="cb48-43"><a href="#cb48-43" aria-hidden="true" tabindex="-1"></a>            <span class="fu">event</span><span class="op">(</span>Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">INFO</span><span class="op">,</span> name<span class="op">);</span></span>
<span id="cb48-44"><a href="#cb48-44" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb48-45"><a href="#cb48-45" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb48-46"><a href="#cb48-46" aria-hidden="true" tabindex="-1"></a>        <span class="kw">default</span> <span class="dt">void</span> <span class="fu">warn</span><span class="op">(</span></span>
<span id="cb48-47"><a href="#cb48-47" aria-hidden="true" tabindex="-1"></a>                <span class="bu">String</span> name</span>
<span id="cb48-48"><a href="#cb48-48" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="op">{</span></span>
<span id="cb48-49"><a href="#cb48-49" aria-hidden="true" tabindex="-1"></a>            <span class="fu">event</span><span class="op">(</span>Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">WARN</span><span class="op">,</span> name<span class="op">);</span></span>
<span id="cb48-50"><a href="#cb48-50" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb48-51"><a href="#cb48-51" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb48-52"><a href="#cb48-52" aria-hidden="true" tabindex="-1"></a>        <span class="kw">default</span> <span class="dt">void</span> <span class="fu">error</span><span class="op">(</span></span>
<span id="cb48-53"><a href="#cb48-53" aria-hidden="true" tabindex="-1"></a>                <span class="bu">String</span> name</span>
<span id="cb48-54"><a href="#cb48-54" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="op">{</span></span>
<span id="cb48-55"><a href="#cb48-55" aria-hidden="true" tabindex="-1"></a>            <span class="fu">event</span><span class="op">(</span>Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">ERROR</span><span class="op">,</span> name<span class="op">);</span></span>
<span id="cb48-56"><a href="#cb48-56" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb48-57"><a href="#cb48-57" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb48-58"><a href="#cb48-58" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb49"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb49-1"><a href="#cb49-1" aria-hidden="true" tabindex="-1"></a><span class="co">// The implementation is trivial</span></span>
<span id="cb49-2"><a href="#cb49-2" aria-hidden="true" tabindex="-1"></a>record <span class="fu">NamespacedLogger</span><span class="op">(</span><span class="bu">String</span> namespace<span class="op">,</span> <span class="bu">Logger</span> logger<span class="op">)</span> </span>
<span id="cb49-3"><a href="#cb49-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">implements</span> <span class="bu">Logger</span><span class="op">.</span><span class="fu">Namespaced</span> <span class="op">{</span></span>
<span id="cb49-4"><a href="#cb49-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">event</span><span class="op">(</span>Log<span class="op">.</span><span class="fu">Level</span> level<span class="op">,</span> <span class="bu">String</span> name<span class="op">)</span> <span class="op">{</span></span>
<span id="cb49-5"><a href="#cb49-5" aria-hidden="true" tabindex="-1"></a>        logger<span class="op">.</span><span class="fu">event</span><span class="op">(</span></span>
<span id="cb49-6"><a href="#cb49-6" aria-hidden="true" tabindex="-1"></a>                level<span class="op">,</span> </span>
<span id="cb49-7"><a href="#cb49-7" aria-hidden="true" tabindex="-1"></a>                <span class="kw">new</span> Log<span class="op">.</span><span class="fu">Category</span><span class="op">(</span><span class="kw">this</span><span class="op">.</span><span class="fu">namespace</span><span class="op">,</span> name<span class="op">)</span></span>
<span id="cb49-8"><a href="#cb49-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb49-9"><a href="#cb49-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb49-10"><a href="#cb49-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="occurrence">Occurrence</h3>
<p>Before adding support for spans to the logger, we need to take a minor detour. The key difference between an <code>Event</code> and a <code>Span</code> is that an <code>Event</code> happens at a singular point in time while a <code>Span</code> takes place over a span of time.</p>
<p>This could be represented directly, by having <code>Event</code>s track when they happened and having <code>Span</code>s track their start time and how long they lasted.</p>
<div class="sourceCode" id="cb50"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb50-1"><a href="#cb50-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> sealed <span class="kw">interface</span> Log <span class="op">{</span></span>
<span id="cb50-2"><a href="#cb50-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Level</span> <span class="fu">level</span><span class="op">();</span></span>
<span id="cb50-3"><a href="#cb50-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb50-4"><a href="#cb50-4" aria-hidden="true" tabindex="-1"></a>    Category <span class="fu">category</span><span class="op">();</span></span>
<span id="cb50-5"><a href="#cb50-5" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb50-6"><a href="#cb50-6" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Event</span><span class="op">(</span></span>
<span id="cb50-7"><a href="#cb50-7" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb50-8"><a href="#cb50-8" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Category category<span class="op">,</span></span>
<span id="cb50-9"><a href="#cb50-9" aria-hidden="true" tabindex="-1"></a>            Instant happenedAt</span>
<span id="cb50-10"><a href="#cb50-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">implements</span> Log <span class="op">{}</span></span>
<span id="cb50-11"><a href="#cb50-11" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb50-12"><a href="#cb50-12" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">Span</span><span class="op">(</span></span>
<span id="cb50-13"><a href="#cb50-13" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb50-14"><a href="#cb50-14" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Category category<span class="op">,</span></span>
<span id="cb50-15"><a href="#cb50-15" aria-hidden="true" tabindex="-1"></a>            Instant startedAt<span class="op">,</span></span>
<span id="cb50-16"><a href="#cb50-16" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Duration</span> lasted</span>
<span id="cb50-17"><a href="#cb50-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">implements</span> Log <span class="op">{}</span></span>
<span id="cb50-18"><a href="#cb50-18" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb50-19"><a href="#cb50-19" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb50-20"><a href="#cb50-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Personally though, I find it more interesting to unify the concepts a little. Every log occurs at some time that is either a singular point of time or a span of time.</p>
<div class="sourceCode" id="cb51"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb51-1"><a href="#cb51-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> sealed <span class="kw">interface</span> Log <span class="op">{</span></span>
<span id="cb51-2"><a href="#cb51-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb51-3"><a href="#cb51-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb51-4"><a href="#cb51-4" aria-hidden="true" tabindex="-1"></a>    sealed <span class="kw">interface</span> Occurrence <span class="op">{</span></span>
<span id="cb51-5"><a href="#cb51-5" aria-hidden="true" tabindex="-1"></a>        record <span class="fu">PointInTime</span><span class="op">(</span></span>
<span id="cb51-6"><a href="#cb51-6" aria-hidden="true" tabindex="-1"></a>                java<span class="op">.</span><span class="fu">time</span><span class="op">.</span><span class="fu">Instant</span> happenedAt</span>
<span id="cb51-7"><a href="#cb51-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="kw">implements</span> Occurrence <span class="op">{</span></span>
<span id="cb51-8"><a href="#cb51-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb51-9"><a href="#cb51-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb51-10"><a href="#cb51-10" aria-hidden="true" tabindex="-1"></a>        record <span class="fu">SpanOfTime</span><span class="op">(</span></span>
<span id="cb51-11"><a href="#cb51-11" aria-hidden="true" tabindex="-1"></a>                java<span class="op">.</span><span class="fu">time</span><span class="op">.</span><span class="fu">Instant</span> startedAt<span class="op">,</span> </span>
<span id="cb51-12"><a href="#cb51-12" aria-hidden="true" tabindex="-1"></a>                java<span class="op">.</span><span class="fu">time</span><span class="op">.</span><span class="fu">Duration</span> lasted</span>
<span id="cb51-13"><a href="#cb51-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="kw">implements</span> Occurrence <span class="op">{</span></span>
<span id="cb51-14"><a href="#cb51-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb51-15"><a href="#cb51-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb51-16"><a href="#cb51-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This lets us put <code>Occurrence</code> on the <code>Log</code> interface directly, while still having <code>Event</code> and <code>Span</code> only have the data they want.</p>
<div class="sourceCode" id="cb52"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb52-1"><a href="#cb52-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> sealed <span class="kw">interface</span> Log <span class="op">{</span></span>
<span id="cb52-2"><a href="#cb52-2" aria-hidden="true" tabindex="-1"></a>    Occurrence <span class="fu">occurrence</span><span class="op">();</span></span>
<span id="cb52-3"><a href="#cb52-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb52-4"><a href="#cb52-4" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Level</span> <span class="fu">level</span><span class="op">();</span></span>
<span id="cb52-5"><a href="#cb52-5" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb52-6"><a href="#cb52-6" aria-hidden="true" tabindex="-1"></a>    Category <span class="fu">category</span><span class="op">();</span></span>
<span id="cb52-7"><a href="#cb52-7" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb52-8"><a href="#cb52-8" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Event</span><span class="op">(</span></span>
<span id="cb52-9"><a href="#cb52-9" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Occurrence<span class="op">.</span><span class="fu">PointInTime</span> occurrence<span class="op">,</span></span>
<span id="cb52-10"><a href="#cb52-10" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb52-11"><a href="#cb52-11" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Category category</span>
<span id="cb52-12"><a href="#cb52-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">implements</span> Log <span class="op">{}</span></span>
<span id="cb52-13"><a href="#cb52-13" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb52-14"><a href="#cb52-14" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">Span</span><span class="op">(</span></span>
<span id="cb52-15"><a href="#cb52-15" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Occurrence<span class="op">.</span><span class="fu">SpanOfTime</span> occurrence<span class="op">,</span></span>
<span id="cb52-16"><a href="#cb52-16" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb52-17"><a href="#cb52-17" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Category category</span>
<span id="cb52-18"><a href="#cb52-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">implements</span> Log <span class="op">{}</span></span>
<span id="cb52-19"><a href="#cb52-19" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb52-20"><a href="#cb52-20" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb52-21"><a href="#cb52-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb52-22"><a href="#cb52-22" aria-hidden="true" tabindex="-1"></a>    sealed <span class="kw">interface</span> Occurrence <span class="op">{</span></span>
<span id="cb52-23"><a href="#cb52-23" aria-hidden="true" tabindex="-1"></a>        record <span class="fu">PointInTime</span><span class="op">(</span></span>
<span id="cb52-24"><a href="#cb52-24" aria-hidden="true" tabindex="-1"></a>                java<span class="op">.</span><span class="fu">time</span><span class="op">.</span><span class="fu">Instant</span> happenedAt</span>
<span id="cb52-25"><a href="#cb52-25" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="kw">implements</span> Occurrence <span class="op">{</span></span>
<span id="cb52-26"><a href="#cb52-26" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb52-27"><a href="#cb52-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb52-28"><a href="#cb52-28" aria-hidden="true" tabindex="-1"></a>        record <span class="fu">SpanOfTime</span><span class="op">(</span></span>
<span id="cb52-29"><a href="#cb52-29" aria-hidden="true" tabindex="-1"></a>                java<span class="op">.</span><span class="fu">time</span><span class="op">.</span><span class="fu">Instant</span> startedAt<span class="op">,</span></span>
<span id="cb52-30"><a href="#cb52-30" aria-hidden="true" tabindex="-1"></a>                java<span class="op">.</span><span class="fu">time</span><span class="op">.</span><span class="fu">Duration</span> lasted</span>
<span id="cb52-31"><a href="#cb52-31" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="kw">implements</span> Occurrence <span class="op">{</span></span>
<span id="cb52-32"><a href="#cb52-32" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb52-33"><a href="#cb52-33" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb52-34"><a href="#cb52-34" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>For <code>Event</code>s, we can make it a bit easier by adding a constructor which sets the occurrence to the current point in time.</p>
<div class="sourceCode" id="cb53"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb53-1"><a href="#cb53-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> sealed <span class="kw">interface</span> Log <span class="op">{</span></span>
<span id="cb53-2"><a href="#cb53-2" aria-hidden="true" tabindex="-1"></a>    Occurrence <span class="fu">occurrence</span><span class="op">();</span></span>
<span id="cb53-3"><a href="#cb53-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb53-4"><a href="#cb53-4" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Level</span> <span class="fu">level</span><span class="op">();</span></span>
<span id="cb53-5"><a href="#cb53-5" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb53-6"><a href="#cb53-6" aria-hidden="true" tabindex="-1"></a>    Category <span class="fu">category</span><span class="op">();</span></span>
<span id="cb53-7"><a href="#cb53-7" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb53-8"><a href="#cb53-8" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Event</span><span class="op">(</span></span>
<span id="cb53-9"><a href="#cb53-9" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Occurrence<span class="op">.</span><span class="fu">PointInTime</span> occurrence<span class="op">,</span></span>
<span id="cb53-10"><a href="#cb53-10" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb53-11"><a href="#cb53-11" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Category category</span>
<span id="cb53-12"><a href="#cb53-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">implements</span> Log <span class="op">{</span></span>
<span id="cb53-13"><a href="#cb53-13" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="bu">Event</span><span class="op">(</span></span>
<span id="cb53-14"><a href="#cb53-14" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb53-15"><a href="#cb53-15" aria-hidden="true" tabindex="-1"></a>                Category category</span>
<span id="cb53-16"><a href="#cb53-16" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="op">{</span></span>
<span id="cb53-17"><a href="#cb53-17" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">(</span>Instant<span class="op">.</span><span class="fu">now</span><span class="op">(),</span> level<span class="op">,</span> category<span class="op">);</span></span>
<span id="cb53-18"><a href="#cb53-18" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb53-19"><a href="#cb53-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb53-20"><a href="#cb53-20" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb53-21"><a href="#cb53-21" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">Span</span><span class="op">(</span></span>
<span id="cb53-22"><a href="#cb53-22" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Occurrence<span class="op">.</span><span class="fu">SpanOfTime</span> occurrence<span class="op">,</span></span>
<span id="cb53-23"><a href="#cb53-23" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb53-24"><a href="#cb53-24" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Category category</span>
<span id="cb53-25"><a href="#cb53-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">implements</span> Log <span class="op">{}</span></span>
<span id="cb53-26"><a href="#cb53-26" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb53-27"><a href="#cb53-27" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb53-28"><a href="#cb53-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb53-29"><a href="#cb53-29" aria-hidden="true" tabindex="-1"></a>    sealed <span class="kw">interface</span> Occurrence <span class="op">{</span></span>
<span id="cb53-30"><a href="#cb53-30" aria-hidden="true" tabindex="-1"></a>        record <span class="fu">PointInTime</span><span class="op">(</span></span>
<span id="cb53-31"><a href="#cb53-31" aria-hidden="true" tabindex="-1"></a>                java<span class="op">.</span><span class="fu">time</span><span class="op">.</span><span class="fu">Instant</span> happenedAt</span>
<span id="cb53-32"><a href="#cb53-32" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="kw">implements</span> Occurrence <span class="op">{</span></span>
<span id="cb53-33"><a href="#cb53-33" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb53-34"><a href="#cb53-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb53-35"><a href="#cb53-35" aria-hidden="true" tabindex="-1"></a>        record <span class="fu">SpanOfTime</span><span class="op">(</span></span>
<span id="cb53-36"><a href="#cb53-36" aria-hidden="true" tabindex="-1"></a>                java<span class="op">.</span><span class="fu">time</span><span class="op">.</span><span class="fu">Instant</span> startedAt<span class="op">,</span></span>
<span id="cb53-37"><a href="#cb53-37" aria-hidden="true" tabindex="-1"></a>                java<span class="op">.</span><span class="fu">time</span><span class="op">.</span><span class="fu">Duration</span> lasted</span>
<span id="cb53-38"><a href="#cb53-38" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="kw">implements</span> Occurrence <span class="op">{</span></span>
<span id="cb53-39"><a href="#cb53-39" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb53-40"><a href="#cb53-40" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb53-41"><a href="#cb53-41" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>For <code>Span</code>s that doesn't make quite as much sense, so auto-timing logic will probably end up being in the logger.</p>
<p>There are two general strategies that would work for adding <code>Span</code>s to the <code>Logger</code> and <code>Logger.Namespaced</code> interfaces.</p>
<p>The first is for a method to return something closeable. When that something is closed, the span is finished.</p>
<div class="sourceCode" id="cb54"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb54-1"><a href="#cb54-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">interface</span> <span class="bu">Logger</span> <span class="op">{</span></span>
<span id="cb54-2"><a href="#cb54-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">log</span><span class="op">(</span>Log log<span class="op">);</span></span>
<span id="cb54-3"><a href="#cb54-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb54-4"><a href="#cb54-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb54-5"><a href="#cb54-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb54-6"><a href="#cb54-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">interface</span> SpanHandle <span class="kw">extends</span> AutoCloseable <span class="op">{</span></span>
<span id="cb54-7"><a href="#cb54-7" aria-hidden="true" tabindex="-1"></a>        <span class="dt">void</span> <span class="fu">close</span><span class="op">();</span></span>
<span id="cb54-8"><a href="#cb54-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb54-9"><a href="#cb54-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb54-10"><a href="#cb54-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> SpanHandle <span class="fu">span</span><span class="op">(</span></span>
<span id="cb54-11"><a href="#cb54-11" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Level</span> level<span class="op">,</span></span>
<span id="cb54-12"><a href="#cb54-12" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Category</span> category</span>
<span id="cb54-13"><a href="#cb54-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb54-14"><a href="#cb54-14" aria-hidden="true" tabindex="-1"></a>        var start <span class="op">=</span> Instant<span class="op">.</span><span class="fu">now</span><span class="op">();</span></span>
<span id="cb54-15"><a href="#cb54-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb54-16"><a href="#cb54-16" aria-hidden="true" tabindex="-1"></a>            var end <span class="op">=</span> Instant<span class="op">.</span><span class="fu">now</span><span class="op">();</span></span>
<span id="cb54-17"><a href="#cb54-17" aria-hidden="true" tabindex="-1"></a>            <span class="fu">log</span><span class="op">(</span></span>
<span id="cb54-18"><a href="#cb54-18" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">new</span> Log<span class="op">.</span><span class="fu">Span</span><span class="op">(</span></span>
<span id="cb54-19"><a href="#cb54-19" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">new</span> Occurance<span class="op">.</span><span class="fu">SpanOfTime</span><span class="op">(</span></span>
<span id="cb54-20"><a href="#cb54-20" aria-hidden="true" tabindex="-1"></a>                                start<span class="op">,</span> </span>
<span id="cb54-21"><a href="#cb54-21" aria-hidden="true" tabindex="-1"></a>                                <span class="bu">Duration</span><span class="op">.</span><span class="fu">between</span><span class="op">(</span>start<span class="op">,</span> end<span class="op">)</span></span>
<span id="cb54-22"><a href="#cb54-22" aria-hidden="true" tabindex="-1"></a>                        <span class="op">)</span></span>
<span id="cb54-23"><a href="#cb54-23" aria-hidden="true" tabindex="-1"></a>                    <span class="op">),</span></span>
<span id="cb54-24"><a href="#cb54-24" aria-hidden="true" tabindex="-1"></a>                    level<span class="op">,</span></span>
<span id="cb54-25"><a href="#cb54-25" aria-hidden="true" tabindex="-1"></a>                    category</span>
<span id="cb54-26"><a href="#cb54-26" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb54-27"><a href="#cb54-27" aria-hidden="true" tabindex="-1"></a>        <span class="op">};</span></span>
<span id="cb54-28"><a href="#cb54-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb54-29"><a href="#cb54-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb54-30"><a href="#cb54-30" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb54-31"><a href="#cb54-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb55"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb55-1"><a href="#cb55-1" aria-hidden="true" tabindex="-1"></a><span class="cf">try</span> <span class="op">(</span>var handle <span class="op">=</span> log<span class="op">.</span><span class="fu">span</span><span class="op">(</span></span>
<span id="cb55-2"><a href="#cb55-2" aria-hidden="true" tabindex="-1"></a>        Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">INFO</span><span class="op">,</span> </span>
<span id="cb55-3"><a href="#cb55-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">new</span> Log<span class="op">.</span><span class="fu">Category</span><span class="op">(</span><span class="st">&quot;something&quot;</span><span class="op">,</span> <span class="st">&quot;happened&quot;</span><span class="op">)))</span> <span class="op">{</span></span>
<span id="cb55-4"><a href="#cb55-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Span open here</span></span>
<span id="cb55-5"><a href="#cb55-5" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;I am in the span!&quot;</span><span class="op">);</span></span>
<span id="cb55-6"><a href="#cb55-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb55-7"><a href="#cb55-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb55-8"><a href="#cb55-8" aria-hidden="true" tabindex="-1"></a><span class="co">// Closed when you exit</span></span></code></pre></div>
<p>This is convenient to use with the try-with-resources syntax and has the nice benefit of playing well with checked exceptions.</p>
<p>By that I mean, if the code within the span wants to throw a checked exception upwards a level or to be handled in a certain way, it is trivial to propagate that exception up.</p>
<div class="sourceCode" id="cb56"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb56-1"><a href="#cb56-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">func</span><span class="op">()</span> <span class="kw">throws</span> <span class="bu">IOException</span><span class="op">,</span> <span class="bu">SQLException</span> <span class="op">{</span></span>
<span id="cb56-2"><a href="#cb56-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">try</span> <span class="op">(</span>var handle <span class="op">=</span> log<span class="op">.</span><span class="fu">span</span><span class="op">(</span></span>
<span id="cb56-3"><a href="#cb56-3" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">INFO</span><span class="op">,</span> </span>
<span id="cb56-4"><a href="#cb56-4" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> Log<span class="op">.</span><span class="fu">Category</span><span class="op">(</span><span class="st">&quot;something&quot;</span><span class="op">,</span> <span class="st">&quot;happened&quot;</span><span class="op">)))</span> <span class="op">{</span></span>
<span id="cb56-5"><a href="#cb56-5" aria-hidden="true" tabindex="-1"></a>        <span class="fu">codeThatThrowsIOExceptionOrSqlException</span><span class="op">();</span></span>
<span id="cb56-6"><a href="#cb56-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> </span>
<span id="cb56-7"><a href="#cb56-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Closed when you exit</span></span>
<span id="cb56-8"><a href="#cb56-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The other way is to directly take some code to run as a callback.</p>
<div class="sourceCode" id="cb57"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb57-1"><a href="#cb57-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">interface</span> <span class="bu">Logger</span> <span class="op">{</span></span>
<span id="cb57-2"><a href="#cb57-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">log</span><span class="op">(</span>Log log<span class="op">);</span></span>
<span id="cb57-3"><a href="#cb57-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb57-4"><a href="#cb57-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb57-5"><a href="#cb57-5" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb57-6"><a href="#cb57-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="op">&lt;</span>T<span class="op">&gt;</span> T <span class="fu">span</span><span class="op">(</span></span>
<span id="cb57-7"><a href="#cb57-7" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Level</span> level<span class="op">,</span></span>
<span id="cb57-8"><a href="#cb57-8" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Category</span> category<span class="op">,</span></span>
<span id="cb57-9"><a href="#cb57-9" aria-hidden="true" tabindex="-1"></a>            Supplier<span class="op">&lt;</span>T<span class="op">&gt;</span> code</span>
<span id="cb57-10"><a href="#cb57-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb57-11"><a href="#cb57-11" aria-hidden="true" tabindex="-1"></a>        var start <span class="op">=</span> Instant<span class="op">.</span><span class="fu">now</span><span class="op">();</span></span>
<span id="cb57-12"><a href="#cb57-12" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb57-13"><a href="#cb57-13" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> code<span class="op">.</span><span class="fu">get</span><span class="op">();</span></span>
<span id="cb57-14"><a href="#cb57-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span><span class="bu">Throwable</span> t<span class="op">)</span> <span class="op">{</span></span>
<span id="cb57-15"><a href="#cb57-15" aria-hidden="true" tabindex="-1"></a>            var end <span class="op">=</span> Instant<span class="op">.</span><span class="fu">now</span><span class="op">();</span></span>
<span id="cb57-16"><a href="#cb57-16" aria-hidden="true" tabindex="-1"></a>            <span class="fu">log</span><span class="op">(</span></span>
<span id="cb57-17"><a href="#cb57-17" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">new</span> Log<span class="op">.</span><span class="fu">Span</span><span class="op">(</span></span>
<span id="cb57-18"><a href="#cb57-18" aria-hidden="true" tabindex="-1"></a>                            <span class="kw">new</span> Occurance<span class="op">.</span><span class="fu">SpanOfTime</span><span class="op">(</span></span>
<span id="cb57-19"><a href="#cb57-19" aria-hidden="true" tabindex="-1"></a>                                    start<span class="op">,</span></span>
<span id="cb57-20"><a href="#cb57-20" aria-hidden="true" tabindex="-1"></a>                                    <span class="bu">Duration</span><span class="op">.</span><span class="fu">between</span><span class="op">(</span>start<span class="op">,</span> end<span class="op">)</span></span>
<span id="cb57-21"><a href="#cb57-21" aria-hidden="true" tabindex="-1"></a>                            <span class="op">)</span></span>
<span id="cb57-22"><a href="#cb57-22" aria-hidden="true" tabindex="-1"></a>                    <span class="op">),</span></span>
<span id="cb57-23"><a href="#cb57-23" aria-hidden="true" tabindex="-1"></a>                    level<span class="op">,</span></span>
<span id="cb57-24"><a href="#cb57-24" aria-hidden="true" tabindex="-1"></a>                    category</span>
<span id="cb57-25"><a href="#cb57-25" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb57-26"><a href="#cb57-26" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb57-27"><a href="#cb57-27" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb57-28"><a href="#cb57-28" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb57-29"><a href="#cb57-29" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="dt">void</span> <span class="fu">span</span><span class="op">(</span></span>
<span id="cb57-30"><a href="#cb57-30" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Level</span> level<span class="op">,</span></span>
<span id="cb57-31"><a href="#cb57-31" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Category</span> category<span class="op">,</span></span>
<span id="cb57-32"><a href="#cb57-32" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Runnable</span> code</span>
<span id="cb57-33"><a href="#cb57-33" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb57-34"><a href="#cb57-34" aria-hidden="true" tabindex="-1"></a>        <span class="fu">span</span><span class="op">(</span>level<span class="op">,</span> category<span class="op">,</span> <span class="op">()</span> <span class="op">-&gt;</span> <span class="op">{</span> </span>
<span id="cb57-35"><a href="#cb57-35" aria-hidden="true" tabindex="-1"></a>            code<span class="op">.</span><span class="fu">run</span><span class="op">();</span></span>
<span id="cb57-36"><a href="#cb57-36" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb57-37"><a href="#cb57-37" aria-hidden="true" tabindex="-1"></a>        <span class="op">});</span></span>
<span id="cb57-38"><a href="#cb57-38" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb57-39"><a href="#cb57-39" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb57-40"><a href="#cb57-40" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb57-41"><a href="#cb57-41" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This has some major downsides - for one, we now can't do things like return early from a function within a span.</p>
<div class="sourceCode" id="cb58"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb58-1"><a href="#cb58-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">func</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb58-2"><a href="#cb58-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> x <span class="op">=</span> <span class="dv">8</span><span class="op">;</span></span>
<span id="cb58-3"><a href="#cb58-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb58-4"><a href="#cb58-4" aria-hidden="true" tabindex="-1"></a>    log<span class="op">.</span><span class="fu">span</span><span class="op">(</span></span>
<span id="cb58-5"><a href="#cb58-5" aria-hidden="true" tabindex="-1"></a>        Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">INFO</span><span class="op">,</span></span>
<span id="cb58-6"><a href="#cb58-6" aria-hidden="true" tabindex="-1"></a>        <span class="kw">new</span> Log<span class="op">.</span><span class="fu">Category</span><span class="op">(</span><span class="st">&quot;space&quot;</span><span class="op">,</span> <span class="st">&quot;hit-debris&quot;</span><span class="op">),</span></span>
<span id="cb58-7"><a href="#cb58-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb58-8"><a href="#cb58-8" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>x <span class="op">==</span> <span class="dv">8</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb58-9"><a href="#cb58-9" aria-hidden="true" tabindex="-1"></a>                <span class="co">// Can only return directly from this lambda,</span></span>
<span id="cb58-10"><a href="#cb58-10" aria-hidden="true" tabindex="-1"></a>                <span class="co">// not the whole method.</span></span>
<span id="cb58-11"><a href="#cb58-11" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span><span class="op">;</span></span>
<span id="cb58-12"><a href="#cb58-12" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb58-13"><a href="#cb58-13" aria-hidden="true" tabindex="-1"></a>            <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Inside the span!&quot;</span><span class="op">);</span></span>
<span id="cb58-14"><a href="#cb58-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb58-15"><a href="#cb58-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb58-16"><a href="#cb58-16" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Will get here&quot;</span><span class="op">);</span></span>
<span id="cb58-17"><a href="#cb58-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And we also cannot automatically handle checked exceptions in the general case.</p>
<p>Like, hypothetically the callback interface could look like this.</p>
<div class="sourceCode" id="cb59"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb59-1"><a href="#cb59-1" aria-hidden="true" tabindex="-1"></a><span class="kw">interface</span> SpanCallback<span class="op">&lt;</span>E <span class="kw">extends</span> <span class="bu">Throwable</span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb59-2"><a href="#cb59-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">run</span><span class="op">()</span> <span class="kw">throws</span> E<span class="op">;</span></span>
<span id="cb59-3"><a href="#cb59-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Which would allow us to write code which throws one kind of checked exception.</p>
<div class="sourceCode" id="cb60"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb60-1"><a href="#cb60-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">func</span><span class="op">()</span> <span class="kw">throws</span> <span class="bu">IOException</span> <span class="op">{</span></span>
<span id="cb60-2"><a href="#cb60-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Correctly throws IOException</span></span>
<span id="cb60-3"><a href="#cb60-3" aria-hidden="true" tabindex="-1"></a>    log<span class="op">.</span><span class="fu">span</span><span class="op">(</span></span>
<span id="cb60-4"><a href="#cb60-4" aria-hidden="true" tabindex="-1"></a>        Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">INFO</span><span class="op">,</span></span>
<span id="cb60-5"><a href="#cb60-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">new</span> Log<span class="op">.</span><span class="fu">Category</span><span class="op">(</span><span class="st">&quot;space&quot;</span><span class="op">,</span> <span class="st">&quot;hit-debris&quot;</span><span class="op">),</span></span>
<span id="cb60-6"><a href="#cb60-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb60-7"><a href="#cb60-7" aria-hidden="true" tabindex="-1"></a>            <span class="cf">throw</span> <span class="kw">new</span> <span class="bu">IOException</span><span class="op">();</span></span>
<span id="cb60-8"><a href="#cb60-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb60-9"><a href="#cb60-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb60-10"><a href="#cb60-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>But if code needed to throw multiple disjoint kinds of exceptions, that would be a problem since the <code>throws E</code> needs to resolve to a single type.</p>
<p>So if the code wrapped in the span throws both <code>IOException</code> and <code>SQLException</code>, the only common type would be <code>Exception</code>.</p>
<div class="sourceCode" id="cb61"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb61-1"><a href="#cb61-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Would want this to be throws IOException, SQLException...</span></span>
<span id="cb61-2"><a href="#cb61-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">func</span><span class="op">()</span> <span class="kw">throws</span> <span class="bu">Exception</span> <span class="op">{</span></span>
<span id="cb61-3"><a href="#cb61-3" aria-hidden="true" tabindex="-1"></a>    log<span class="op">.</span><span class="fu">span</span><span class="op">(</span></span>
<span id="cb61-4"><a href="#cb61-4" aria-hidden="true" tabindex="-1"></a>        Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">INFO</span><span class="op">,</span></span>
<span id="cb61-5"><a href="#cb61-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">new</span> Log<span class="op">.</span><span class="fu">Category</span><span class="op">(</span><span class="st">&quot;space&quot;</span><span class="op">,</span> <span class="st">&quot;hit-debris&quot;</span><span class="op">),</span></span>
<span id="cb61-6"><a href="#cb61-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb61-7"><a href="#cb61-7" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span><span class="bu">Math</span><span class="op">.</span><span class="fu">random</span><span class="op">()</span> <span class="op">&gt;</span> <span class="fl">0.5</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb61-8"><a href="#cb61-8" aria-hidden="true" tabindex="-1"></a>                <span class="cf">throw</span> <span class="kw">new</span> <span class="bu">IOException</span><span class="op">();</span></span>
<span id="cb61-9"><a href="#cb61-9" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb61-10"><a href="#cb61-10" aria-hidden="true" tabindex="-1"></a>            <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb61-11"><a href="#cb61-11" aria-hidden="true" tabindex="-1"></a>                <span class="cf">throw</span> <span class="kw">new</span> <span class="bu">SQLException</span><span class="op">();</span></span>
<span id="cb61-12"><a href="#cb61-12" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb61-13"><a href="#cb61-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb61-14"><a href="#cb61-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb61-15"><a href="#cb61-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>There are some solutions depending on sensibilities, but none are perfect.</p>
<ul>
<li>You can wrap in a <code>RuntimeException</code> subclass</li>
<li><a href="https://projectlombok.org/features/SneakyThrows">Sneaky throw</a></li>
<li><a href="https://mccue.dev/pages/11-1-21-smuggling-checked-exceptions">Smuggle the exception</a></li>
</ul>
<p>Even given these issues, I think the callback system is the better of the two. <a href="https://openjdk.org/jeps/429"><code>ExtentLocal</code></a>s basically mandate it and, as a tiny spoiler, <code>Span</code>s are going to need to propagate context to nested logs. It also isn't possible to mess up. try-with-resources is good and IDEs will warn if you don't close a returned auto-closeable, but there are still some cursed situations that can arise if you do not.</p>
<p>So with that settled both <code>Logger</code> and <code>Logger.Namespaced</code> are due their full complement of <code>span</code> methods for each log level.</p>
<div class="sourceCode" id="cb62"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb62-1"><a href="#cb62-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">interface</span> <span class="bu">Logger</span> <span class="op">{</span></span>
<span id="cb62-2"><a href="#cb62-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">log</span><span class="op">(</span>Log log<span class="op">);</span></span>
<span id="cb62-3"><a href="#cb62-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb62-4"><a href="#cb62-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb62-5"><a href="#cb62-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb62-6"><a href="#cb62-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="op">&lt;</span>T<span class="op">&gt;</span> T <span class="fu">span</span><span class="op">(</span></span>
<span id="cb62-7"><a href="#cb62-7" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Level</span> level<span class="op">,</span></span>
<span id="cb62-8"><a href="#cb62-8" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Category</span> category<span class="op">,</span></span>
<span id="cb62-9"><a href="#cb62-9" aria-hidden="true" tabindex="-1"></a>            Supplier<span class="op">&lt;</span>T<span class="op">&gt;</span> code</span>
<span id="cb62-10"><a href="#cb62-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb62-11"><a href="#cb62-11" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb62-12"><a href="#cb62-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb62-13"><a href="#cb62-13" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb62-14"><a href="#cb62-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="dt">void</span> <span class="fu">span</span><span class="op">(</span></span>
<span id="cb62-15"><a href="#cb62-15" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Level</span> level<span class="op">,</span></span>
<span id="cb62-16"><a href="#cb62-16" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Category</span> category<span class="op">,</span></span>
<span id="cb62-17"><a href="#cb62-17" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Runnable</span> code</span>
<span id="cb62-18"><a href="#cb62-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb62-19"><a href="#cb62-19" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb62-20"><a href="#cb62-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb62-21"><a href="#cb62-21" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb62-22"><a href="#cb62-22" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb62-23"><a href="#cb62-23" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb62-24"><a href="#cb62-24" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="op">&lt;</span>T<span class="op">&gt;</span> T <span class="fu">infoSpan</span><span class="op">(</span></span>
<span id="cb62-25"><a href="#cb62-25" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Category</span> category<span class="op">,</span></span>
<span id="cb62-26"><a href="#cb62-26" aria-hidden="true" tabindex="-1"></a>            Supplier<span class="op">&lt;</span>T<span class="op">&gt;</span> code</span>
<span id="cb62-27"><a href="#cb62-27" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb62-28"><a href="#cb62-28" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fu">span</span><span class="op">(</span>Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">INFO</span><span class="op">,</span> category<span class="op">,</span> code<span class="op">);</span></span>
<span id="cb62-29"><a href="#cb62-29" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb62-30"><a href="#cb62-30" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb62-31"><a href="#cb62-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="dt">void</span> <span class="fu">infoSpan</span><span class="op">(</span></span>
<span id="cb62-32"><a href="#cb62-32" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Category</span> category<span class="op">,</span></span>
<span id="cb62-33"><a href="#cb62-33" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Runnable</span> code</span>
<span id="cb62-34"><a href="#cb62-34" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb62-35"><a href="#cb62-35" aria-hidden="true" tabindex="-1"></a>        <span class="fu">span</span><span class="op">(</span>Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">INFO</span><span class="op">,</span> category<span class="op">,</span> code<span class="op">);</span></span>
<span id="cb62-36"><a href="#cb62-36" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb62-37"><a href="#cb62-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb62-38"><a href="#cb62-38" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="op">&lt;</span>T<span class="op">&gt;</span> T <span class="fu">warnSpan</span><span class="op">(</span></span>
<span id="cb62-39"><a href="#cb62-39" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Category</span> category<span class="op">,</span></span>
<span id="cb62-40"><a href="#cb62-40" aria-hidden="true" tabindex="-1"></a>            Supplier<span class="op">&lt;</span>T<span class="op">&gt;</span> code</span>
<span id="cb62-41"><a href="#cb62-41" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb62-42"><a href="#cb62-42" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fu">span</span><span class="op">(</span>Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">WARN</span><span class="op">,</span> category<span class="op">,</span> code<span class="op">);</span></span>
<span id="cb62-43"><a href="#cb62-43" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb62-44"><a href="#cb62-44" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb62-45"><a href="#cb62-45" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="dt">void</span> <span class="fu">warnSpan</span><span class="op">(</span></span>
<span id="cb62-46"><a href="#cb62-46" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Category</span> category<span class="op">,</span></span>
<span id="cb62-47"><a href="#cb62-47" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Runnable</span> code</span>
<span id="cb62-48"><a href="#cb62-48" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb62-49"><a href="#cb62-49" aria-hidden="true" tabindex="-1"></a>        <span class="fu">span</span><span class="op">(</span>Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">WARN</span><span class="op">,</span> category<span class="op">,</span> code<span class="op">);</span></span>
<span id="cb62-50"><a href="#cb62-50" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb62-51"><a href="#cb62-51" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb62-52"><a href="#cb62-52" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb62-53"><a href="#cb62-53" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb62-54"><a href="#cb62-54" aria-hidden="true" tabindex="-1"></a>    <span class="kw">interface</span> Namepaced <span class="op">{</span></span>
<span id="cb62-55"><a href="#cb62-55" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb62-56"><a href="#cb62-56" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb62-57"><a href="#cb62-57" aria-hidden="true" tabindex="-1"></a>        <span class="op">&lt;</span>T<span class="op">&gt;</span> T <span class="fu">span</span><span class="op">(</span></span>
<span id="cb62-58"><a href="#cb62-58" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Level</span> level<span class="op">,</span></span>
<span id="cb62-59"><a href="#cb62-59" aria-hidden="true" tabindex="-1"></a>            <span class="bu">String</span> name<span class="op">,</span></span>
<span id="cb62-60"><a href="#cb62-60" aria-hidden="true" tabindex="-1"></a>            Supplier<span class="op">&lt;</span>T<span class="op">&gt;</span> code</span>
<span id="cb62-61"><a href="#cb62-61" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb62-62"><a href="#cb62-62" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb62-63"><a href="#cb62-63" aria-hidden="true" tabindex="-1"></a>        <span class="kw">default</span> <span class="dt">void</span> <span class="fu">span</span><span class="op">(</span></span>
<span id="cb62-64"><a href="#cb62-64" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Level</span> level<span class="op">,</span></span>
<span id="cb62-65"><a href="#cb62-65" aria-hidden="true" tabindex="-1"></a>            <span class="bu">String</span> name<span class="op">,</span></span>
<span id="cb62-66"><a href="#cb62-66" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Runnable</span> code</span>
<span id="cb62-67"><a href="#cb62-67" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="op">{</span></span>
<span id="cb62-68"><a href="#cb62-68" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="fu">span</span><span class="op">(</span>level<span class="op">,</span> name<span class="op">,</span> <span class="op">()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb62-69"><a href="#cb62-69" aria-hidden="true" tabindex="-1"></a>                code<span class="op">.</span><span class="fu">run</span><span class="op">();</span></span>
<span id="cb62-70"><a href="#cb62-70" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb62-71"><a href="#cb62-71" aria-hidden="true" tabindex="-1"></a>            <span class="op">});</span></span>
<span id="cb62-72"><a href="#cb62-72" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb62-73"><a href="#cb62-73" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb62-74"><a href="#cb62-74" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb62-75"><a href="#cb62-75" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb62-76"><a href="#cb62-76" aria-hidden="true" tabindex="-1"></a>        <span class="kw">default</span> <span class="op">&lt;</span>T<span class="op">&gt;</span> T <span class="fu">infoSpan</span><span class="op">(</span></span>
<span id="cb62-77"><a href="#cb62-77" aria-hidden="true" tabindex="-1"></a>            <span class="bu">String</span> name<span class="op">,</span></span>
<span id="cb62-78"><a href="#cb62-78" aria-hidden="true" tabindex="-1"></a>            Supplier<span class="op">&lt;</span>T<span class="op">&gt;</span> code</span>
<span id="cb62-79"><a href="#cb62-79" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="op">{</span></span>
<span id="cb62-80"><a href="#cb62-80" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="fu">span</span><span class="op">(</span>Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">INFO</span><span class="op">,</span> name<span class="op">,</span> code<span class="op">);</span></span>
<span id="cb62-81"><a href="#cb62-81" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb62-82"><a href="#cb62-82" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb62-83"><a href="#cb62-83" aria-hidden="true" tabindex="-1"></a>        <span class="kw">default</span> <span class="dt">void</span> <span class="fu">infoSpan</span><span class="op">(</span></span>
<span id="cb62-84"><a href="#cb62-84" aria-hidden="true" tabindex="-1"></a>            <span class="bu">String</span> name<span class="op">,</span></span>
<span id="cb62-85"><a href="#cb62-85" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Runnable</span> code</span>
<span id="cb62-86"><a href="#cb62-86" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="op">{</span></span>
<span id="cb62-87"><a href="#cb62-87" aria-hidden="true" tabindex="-1"></a>            <span class="fu">span</span><span class="op">(</span>Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">INFO</span><span class="op">,</span> name<span class="op">,</span> code<span class="op">);</span></span>
<span id="cb62-88"><a href="#cb62-88" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb62-89"><a href="#cb62-89" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb62-90"><a href="#cb62-90" aria-hidden="true" tabindex="-1"></a>        <span class="kw">default</span> <span class="op">&lt;</span>T<span class="op">&gt;</span> T <span class="fu">warnSpan</span><span class="op">(</span></span>
<span id="cb62-91"><a href="#cb62-91" aria-hidden="true" tabindex="-1"></a>            <span class="bu">String</span> name<span class="op">,</span></span>
<span id="cb62-92"><a href="#cb62-92" aria-hidden="true" tabindex="-1"></a>            Supplier<span class="op">&lt;</span>T<span class="op">&gt;</span> code</span>
<span id="cb62-93"><a href="#cb62-93" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="op">{</span></span>
<span id="cb62-94"><a href="#cb62-94" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="fu">span</span><span class="op">(</span>Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">WARN</span><span class="op">,</span> name<span class="op">,</span> code<span class="op">);</span></span>
<span id="cb62-95"><a href="#cb62-95" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb62-96"><a href="#cb62-96" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb62-97"><a href="#cb62-97" aria-hidden="true" tabindex="-1"></a>        <span class="kw">default</span> <span class="dt">void</span> <span class="fu">warnSpan</span><span class="op">(</span></span>
<span id="cb62-98"><a href="#cb62-98" aria-hidden="true" tabindex="-1"></a>            <span class="bu">String</span> name<span class="op">,</span></span>
<span id="cb62-99"><a href="#cb62-99" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Runnable</span> code</span>
<span id="cb62-100"><a href="#cb62-100" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="op">{</span></span>
<span id="cb62-101"><a href="#cb62-101" aria-hidden="true" tabindex="-1"></a>            <span class="fu">span</span><span class="op">(</span>Log<span class="op">.</span><span class="fu">Level</span><span class="op">.</span><span class="fu">WARN</span><span class="op">,</span> name<span class="op">,</span> code<span class="op">);</span></span>
<span id="cb62-102"><a href="#cb62-102" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb62-103"><a href="#cb62-103" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb62-104"><a href="#cb62-104" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb62-105"><a href="#cb62-105" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb62-106"><a href="#cb62-106" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb62-107"><a href="#cb62-107" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="entry">Entry</h3>
<p>To be useful, logs often need to carry some dynamic information. What user is making the request? What is the database record that is about to be altered?</p>
<p>These are the "log entries." The representation for this seems to be pretty universally key-value pairs, so that is what I am going with.</p>
<div class="sourceCode" id="cb63"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb63-1"><a href="#cb63-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Log <span class="op">{</span></span>
<span id="cb63-2"><a href="#cb63-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb63-3"><a href="#cb63-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb63-4"><a href="#cb63-4" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">Entry</span><span class="op">(</span><span class="bu">String</span> key<span class="op">,</span> Value value<span class="op">)</span> <span class="op">{}</span></span>
<span id="cb63-5"><a href="#cb63-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>It follows that logs will get some list of log entries.</p>
<div class="sourceCode" id="cb64"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb64-1"><a href="#cb64-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> sealed <span class="kw">interface</span> Log <span class="op">{</span></span>
<span id="cb64-2"><a href="#cb64-2" aria-hidden="true" tabindex="-1"></a>    Occurrence <span class="fu">occurrence</span><span class="op">();</span></span>
<span id="cb64-3"><a href="#cb64-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb64-4"><a href="#cb64-4" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Level</span> <span class="fu">level</span><span class="op">();</span></span>
<span id="cb64-5"><a href="#cb64-5" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb64-6"><a href="#cb64-6" aria-hidden="true" tabindex="-1"></a>    Category <span class="fu">category</span><span class="op">();</span></span>
<span id="cb64-7"><a href="#cb64-7" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb64-8"><a href="#cb64-8" aria-hidden="true" tabindex="-1"></a>    <span class="bu">List</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> <span class="fu">entries</span><span class="op">();</span></span>
<span id="cb64-9"><a href="#cb64-9" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb64-10"><a href="#cb64-10" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Event</span><span class="op">(</span></span>
<span id="cb64-11"><a href="#cb64-11" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Occurrence<span class="op">.</span><span class="fu">PointInTime</span> occurrence<span class="op">,</span></span>
<span id="cb64-12"><a href="#cb64-12" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb64-13"><a href="#cb64-13" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Category category<span class="op">,</span></span>
<span id="cb64-14"><a href="#cb64-14" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">List</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> entries</span>
<span id="cb64-15"><a href="#cb64-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">implements</span> Log <span class="op">{</span></span>
<span id="cb64-16"><a href="#cb64-16" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="bu">Event</span><span class="op">(</span></span>
<span id="cb64-17"><a href="#cb64-17" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb64-18"><a href="#cb64-18" aria-hidden="true" tabindex="-1"></a>                Category category</span>
<span id="cb64-19"><a href="#cb64-19" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="op">{</span></span>
<span id="cb64-20"><a href="#cb64-20" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">(</span></span>
<span id="cb64-21"><a href="#cb64-21" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">new</span> Occurrence<span class="op">.</span><span class="fu">PointInTime</span><span class="op">(</span>Instant<span class="op">.</span><span class="fu">now</span><span class="op">()),</span> </span>
<span id="cb64-22"><a href="#cb64-22" aria-hidden="true" tabindex="-1"></a>                    level<span class="op">,</span></span>
<span id="cb64-23"><a href="#cb64-23" aria-hidden="true" tabindex="-1"></a>                    category</span>
<span id="cb64-24"><a href="#cb64-24" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb64-25"><a href="#cb64-25" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb64-26"><a href="#cb64-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb64-27"><a href="#cb64-27" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb64-28"><a href="#cb64-28" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">Span</span><span class="op">(</span></span>
<span id="cb64-29"><a href="#cb64-29" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Occurrence<span class="op">.</span><span class="fu">SpanOfTime</span> occurrence<span class="op">,</span></span>
<span id="cb64-30"><a href="#cb64-30" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb64-31"><a href="#cb64-31" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Category category<span class="op">,</span></span>
<span id="cb64-32"><a href="#cb64-32" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">List</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> entries</span>
<span id="cb64-33"><a href="#cb64-33" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">implements</span> Log <span class="op">{}</span></span>
<span id="cb64-34"><a href="#cb64-34" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb64-35"><a href="#cb64-35" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb64-36"><a href="#cb64-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb64-37"><a href="#cb64-37" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">Entry</span><span class="op">(</span><span class="bu">String</span> key<span class="op">,</span> Value value<span class="op">)</span> <span class="op">{}</span></span>
<span id="cb64-38"><a href="#cb64-38" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><code>µ/log</code> merges its log entries immediately into a map, but I don't think this is necessary.</p>
<p>For one, we are going to be adding semantics to <code>Log.Entry</code> that don't exist in <code>Map.Entry</code> like requiring that the key and value be non-null.</p>
<div class="sourceCode" id="cb65"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb65-1"><a href="#cb65-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> sealed <span class="kw">interface</span> Log <span class="op">{</span></span>
<span id="cb65-2"><a href="#cb65-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb65-3"><a href="#cb65-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb65-4"><a href="#cb65-4" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">Entry</span><span class="op">(</span><span class="bu">String</span> key<span class="op">,</span> Value value<span class="op">)</span> <span class="op">{</span></span>
<span id="cb65-5"><a href="#cb65-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Entry <span class="op">{</span></span>
<span id="cb65-6"><a href="#cb65-6" aria-hidden="true" tabindex="-1"></a>            Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span></span>
<span id="cb65-7"><a href="#cb65-7" aria-hidden="true" tabindex="-1"></a>                    key<span class="op">,</span></span>
<span id="cb65-8"><a href="#cb65-8" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;key must not be null&quot;</span></span>
<span id="cb65-9"><a href="#cb65-9" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb65-10"><a href="#cb65-10" aria-hidden="true" tabindex="-1"></a>            Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span></span>
<span id="cb65-11"><a href="#cb65-11" aria-hidden="true" tabindex="-1"></a>                    value<span class="op">,</span></span>
<span id="cb65-12"><a href="#cb65-12" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;value must not be null&quot;</span></span>
<span id="cb65-13"><a href="#cb65-13" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb65-14"><a href="#cb65-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb65-15"><a href="#cb65-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb65-16"><a href="#cb65-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Also, the most common operation that is going to be performed is iterating over the full list of entries to build some JSON or similar. All the pieces of the logs that have semantic significance - like the level or when they occurred - have dedicated methods and places in the objects for them.</p>
<p><code>µ/log</code> is also slightly special in that the keys in its maps generally wouldn't be <code>String</code>s. It is idiomatic in clojure to use <a href="https://clojuredocs.org/clojure.core/keyword"><code>keywords</code></a> and <a href="https://clojuredocs.org/clojure.core/keyword"><code>keywords</code></a> have the distinction of having a precomputed hash code. If the internal representation were a <code>Map&lt;String, Value&gt;</code> then there would be a constant and probably pointless cost for doing that hashing.</p>
<p>Both <code>Logger</code> and <code>Logger.Namespaced</code> need to be updated as well.</p>
<div class="sourceCode" id="cb66"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb66-1"><a href="#cb66-1" aria-hidden="true" tabindex="-1"></a><span class="kw">interface</span> <span class="bu">Logger</span> <span class="op">{</span></span>
<span id="cb66-2"><a href="#cb66-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb66-3"><a href="#cb66-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb66-4"><a href="#cb66-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="dt">void</span> <span class="fu">info</span><span class="op">(</span></span>
<span id="cb66-5"><a href="#cb66-5" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Category</span> category<span class="op">,</span></span>
<span id="cb66-6"><a href="#cb66-6" aria-hidden="true" tabindex="-1"></a>            <span class="bu">List</span><span class="op">&lt;</span>Log<span class="op">.</span><span class="fu">Entry</span><span class="op">&gt;</span> entries</span>
<span id="cb66-7"><a href="#cb66-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb66-8"><a href="#cb66-8" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb66-9"><a href="#cb66-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb66-10"><a href="#cb66-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb66-11"><a href="#cb66-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="op">&lt;</span>T<span class="op">&gt;</span> T <span class="fu">infoSpan</span><span class="op">(</span></span>
<span id="cb66-12"><a href="#cb66-12" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Category</span> category<span class="op">,</span></span>
<span id="cb66-13"><a href="#cb66-13" aria-hidden="true" tabindex="-1"></a>            <span class="bu">List</span><span class="op">&lt;</span>Log<span class="op">.</span><span class="fu">Entry</span><span class="op">&gt;</span> entries<span class="op">,</span></span>
<span id="cb66-14"><a href="#cb66-14" aria-hidden="true" tabindex="-1"></a>            Supplier<span class="op">&lt;</span>T<span class="op">&gt;</span> code</span>
<span id="cb66-15"><a href="#cb66-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb66-16"><a href="#cb66-16" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb66-17"><a href="#cb66-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb66-18"><a href="#cb66-18" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb66-19"><a href="#cb66-19" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb66-20"><a href="#cb66-20" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb66-21"><a href="#cb66-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">interface</span> Namespaced <span class="op">{</span></span>
<span id="cb66-22"><a href="#cb66-22" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb66-23"><a href="#cb66-23" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb66-24"><a href="#cb66-24" aria-hidden="true" tabindex="-1"></a>        <span class="kw">default</span> <span class="dt">void</span> <span class="fu">info</span><span class="op">(</span></span>
<span id="cb66-25"><a href="#cb66-25" aria-hidden="true" tabindex="-1"></a>                <span class="bu">String</span> name<span class="op">,</span></span>
<span id="cb66-26"><a href="#cb66-26" aria-hidden="true" tabindex="-1"></a>                <span class="bu">List</span><span class="op">&lt;</span>Log<span class="op">.</span><span class="fu">Entry</span><span class="op">&gt;</span> entries</span>
<span id="cb66-27"><a href="#cb66-27" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="op">{</span></span>
<span id="cb66-28"><a href="#cb66-28" aria-hidden="true" tabindex="-1"></a>            <span class="co">// ...</span></span>
<span id="cb66-29"><a href="#cb66-29" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb66-30"><a href="#cb66-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb66-31"><a href="#cb66-31" aria-hidden="true" tabindex="-1"></a>        <span class="kw">default</span> <span class="op">&lt;</span>T<span class="op">&gt;</span> T <span class="fu">infoSpan</span><span class="op">(</span></span>
<span id="cb66-32"><a href="#cb66-32" aria-hidden="true" tabindex="-1"></a>                <span class="bu">String</span> name<span class="op">,</span></span>
<span id="cb66-33"><a href="#cb66-33" aria-hidden="true" tabindex="-1"></a>                <span class="bu">List</span><span class="op">&lt;</span>Log<span class="op">.</span><span class="fu">Entry</span><span class="op">&gt;</span> entries<span class="op">,</span></span>
<span id="cb66-34"><a href="#cb66-34" aria-hidden="true" tabindex="-1"></a>                Supplier<span class="op">&lt;</span>T<span class="op">&gt;</span> code</span>
<span id="cb66-35"><a href="#cb66-35" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="op">{</span></span>
<span id="cb66-36"><a href="#cb66-36" aria-hidden="true" tabindex="-1"></a>            <span class="co">// ...</span></span>
<span id="cb66-37"><a href="#cb66-37" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb66-38"><a href="#cb66-38" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb66-39"><a href="#cb66-39" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb66-40"><a href="#cb66-40" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb66-41"><a href="#cb66-41" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Using <code>List.of()</code> to manually make lists is a bit tedious and this parameter does often come at the end of the arguments list, so a varargs overload feels a good idea.</p>
<div class="sourceCode" id="cb67"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb67-1"><a href="#cb67-1" aria-hidden="true" tabindex="-1"></a><span class="kw">interface</span> <span class="bu">Logger</span> <span class="op">{</span></span>
<span id="cb67-2"><a href="#cb67-2" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb67-3"><a href="#cb67-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb67-4"><a href="#cb67-4" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb67-5"><a href="#cb67-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">interface</span> Namespaced <span class="op">{</span></span>
<span id="cb67-6"><a href="#cb67-6" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb67-7"><a href="#cb67-7" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb67-8"><a href="#cb67-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">default</span> <span class="dt">void</span> <span class="fu">info</span><span class="op">(</span></span>
<span id="cb67-9"><a href="#cb67-9" aria-hidden="true" tabindex="-1"></a>                <span class="bu">String</span> name<span class="op">,</span></span>
<span id="cb67-10"><a href="#cb67-10" aria-hidden="true" tabindex="-1"></a>                <span class="bu">List</span><span class="op">&lt;</span>Log<span class="op">.</span><span class="fu">Entry</span><span class="op">&gt;</span> entries</span>
<span id="cb67-11"><a href="#cb67-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="op">{</span></span>
<span id="cb67-12"><a href="#cb67-12" aria-hidden="true" tabindex="-1"></a>            <span class="co">// ...</span></span>
<span id="cb67-13"><a href="#cb67-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb67-14"><a href="#cb67-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb67-15"><a href="#cb67-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">default</span> <span class="dt">void</span> <span class="fu">info</span><span class="op">(</span></span>
<span id="cb67-16"><a href="#cb67-16" aria-hidden="true" tabindex="-1"></a>                <span class="bu">String</span> name<span class="op">,</span></span>
<span id="cb67-17"><a href="#cb67-17" aria-hidden="true" tabindex="-1"></a>                Log<span class="op">.</span><span class="fu">Entry</span><span class="kw">...</span> entries</span>
<span id="cb67-18"><a href="#cb67-18" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="op">{</span></span>
<span id="cb67-19"><a href="#cb67-19" aria-hidden="true" tabindex="-1"></a>            <span class="fu">info</span><span class="op">(</span>name<span class="op">,</span> <span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>entries<span class="op">));</span></span>
<span id="cb67-20"><a href="#cb67-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb67-21"><a href="#cb67-21" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb67-22"><a href="#cb67-22" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb67-23"><a href="#cb67-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb67-24"><a href="#cb67-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Syntactically we can stop there, but if you take a gander at <a href="https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/util/List.html#of()">the docs for <code>List.of()</code></a> you will see everything up to a ten argument overload. This is pretty plainly to avoid allocating the array for varargs, so it might make sense to do that for this API too.</p>
<p>Five log levels plus one base <code>event</code> method in <code>Logger</code> and also in <code>Logger.Namespaced</code>. If I gave each all ten argument overloads to match the overloads of <code>List.of()</code> that would be extra 120 methods plus carpal tunnel. For the hypothetical performance of something no one is using yet.</p>
<p>I'm not going to do that.</p>
<p>Which just leaves open the question, what exactly is a <code>Value</code>?</p>
<h3 id="value">Value</h3>
<p>Taking a page from <code>tracing</code>, I am going to restrict what is allowed as a <code>Value</code>.</p>
<p>So long as strings, numbers, booleans, lists, and maps are represented anything is probably acceptable, but I am going to be a bit liberal with what is allowed.</p>
<p>A good place to start might be to put my foot down and say that booleans are allowed.</p>
<div class="sourceCode" id="cb68"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb68-1"><a href="#cb68-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Value <span class="op">{</span></span>
<span id="cb68-2"><a href="#cb68-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb68-3"><a href="#cb68-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb68-4"><a href="#cb68-4" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Boolean</span><span class="op">(</span><span class="dt">boolean</span> value<span class="op">)</span> <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb68-5"><a href="#cb68-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb68-6"><a href="#cb68-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb68-7"><a href="#cb68-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb68-8"><a href="#cb68-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Any of the primitive numeric types are okay.</p>
<div class="sourceCode" id="cb69"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb69-1"><a href="#cb69-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Value <span class="op">{</span></span>
<span id="cb69-2"><a href="#cb69-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb69-3"><a href="#cb69-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb69-4"><a href="#cb69-4" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Byte</span><span class="op">(</span><span class="dt">byte</span> value<span class="op">)</span> <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb69-5"><a href="#cb69-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb69-6"><a href="#cb69-6" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb69-7"><a href="#cb69-7" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Character</span><span class="op">(</span><span class="dt">char</span> value<span class="op">)</span> <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb69-8"><a href="#cb69-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb69-9"><a href="#cb69-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb69-10"><a href="#cb69-10" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Short</span><span class="op">(</span><span class="dt">short</span> value<span class="op">)</span> <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb69-11"><a href="#cb69-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb69-12"><a href="#cb69-12" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb69-13"><a href="#cb69-13" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Integer</span><span class="op">(</span><span class="dt">int</span> value<span class="op">)</span> <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb69-14"><a href="#cb69-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb69-15"><a href="#cb69-15" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb69-16"><a href="#cb69-16" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Long</span><span class="op">(</span><span class="dt">long</span> value<span class="op">)</span> <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb69-17"><a href="#cb69-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb69-18"><a href="#cb69-18" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb69-19"><a href="#cb69-19" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Float</span><span class="op">(</span><span class="dt">float</span> value<span class="op">)</span> <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb69-20"><a href="#cb69-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb69-21"><a href="#cb69-21" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb69-22"><a href="#cb69-22" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Double</span><span class="op">(</span><span class="dt">double</span> value<span class="op">)</span> <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb69-23"><a href="#cb69-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb69-24"><a href="#cb69-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb69-25"><a href="#cb69-25" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb69-26"><a href="#cb69-26" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And <code>String</code>s seem pretty cool too.</p>
<div class="sourceCode" id="cb70"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb70-1"><a href="#cb70-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Value <span class="op">{</span></span>
<span id="cb70-2"><a href="#cb70-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb70-3"><a href="#cb70-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb70-4"><a href="#cb70-4" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">String</span><span class="op">(</span>java<span class="op">.</span><span class="fu">lang</span><span class="op">.</span><span class="fu">String</span> value<span class="op">)</span> <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb70-5"><a href="#cb70-5" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb70-6"><a href="#cb70-6" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb70-7"><a href="#cb70-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="bu">String</span> <span class="op">{</span></span>
<span id="cb70-8"><a href="#cb70-8" aria-hidden="true" tabindex="-1"></a>            Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>value<span class="op">,</span> <span class="st">&quot;value must not be null&quot;</span><span class="op">);</span></span>
<span id="cb70-9"><a href="#cb70-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb70-10"><a href="#cb70-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb70-11"><a href="#cb70-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb70-12"><a href="#cb70-12" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb70-13"><a href="#cb70-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>UUIDs are relatively common to come across and are immutable and pretty trivially translatable to a string.</p>
<div class="sourceCode" id="cb71"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb71-1"><a href="#cb71-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Value <span class="op">{</span></span>
<span id="cb71-2"><a href="#cb71-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb71-3"><a href="#cb71-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb71-4"><a href="#cb71-4" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">UUID</span><span class="op">(</span>java<span class="op">.</span><span class="fu">util</span><span class="op">.</span><span class="fu">UUID</span> value<span class="op">)</span> <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb71-5"><a href="#cb71-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="bu">UUID</span> <span class="op">{</span></span>
<span id="cb71-6"><a href="#cb71-6" aria-hidden="true" tabindex="-1"></a>            Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>value<span class="op">,</span> <span class="st">&quot;value must not be null&quot;</span><span class="op">);</span></span>
<span id="cb71-7"><a href="#cb71-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb71-8"><a href="#cb71-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb71-9"><a href="#cb71-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb71-10"><a href="#cb71-10" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb71-11"><a href="#cb71-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>URIs <a href="https://brian.pontarelli.com/2006/12/05/mr-gosling-why-did-you-make-url-equals-suck/">(not URLs!)</a> are equally simple and come up quite a bit when making web services.</p>
<div class="sourceCode" id="cb72"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb72-1"><a href="#cb72-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Value <span class="op">{</span></span>
<span id="cb72-2"><a href="#cb72-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb72-3"><a href="#cb72-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb72-4"><a href="#cb72-4" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">URI</span><span class="op">(</span>java<span class="op">.</span><span class="fu">net</span><span class="op">.</span><span class="fu">URI</span> value<span class="op">)</span> <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb72-5"><a href="#cb72-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="bu">URI</span> <span class="op">{</span></span>
<span id="cb72-6"><a href="#cb72-6" aria-hidden="true" tabindex="-1"></a>            Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>value<span class="op">,</span> <span class="st">&quot;value must not be null&quot;</span><span class="op">);</span></span>
<span id="cb72-7"><a href="#cb72-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb72-8"><a href="#cb72-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb72-9"><a href="#cb72-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb72-10"><a href="#cb72-10" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb72-11"><a href="#cb72-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The types in <code>java.time</code> are pretty crucial.</p>
<div class="sourceCode" id="cb73"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb73-1"><a href="#cb73-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Value <span class="op">{</span></span>
<span id="cb73-2"><a href="#cb73-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb73-3"><a href="#cb73-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb73-4"><a href="#cb73-4" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">Instant</span><span class="op">(</span>java<span class="op">.</span><span class="fu">time</span><span class="op">.</span><span class="fu">Instant</span> value<span class="op">)</span> <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb73-5"><a href="#cb73-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Instant <span class="op">{</span></span>
<span id="cb73-6"><a href="#cb73-6" aria-hidden="true" tabindex="-1"></a>            Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>value<span class="op">,</span> <span class="st">&quot;value must not be null&quot;</span><span class="op">);</span></span>
<span id="cb73-7"><a href="#cb73-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb73-8"><a href="#cb73-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb73-9"><a href="#cb73-9" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb73-10"><a href="#cb73-10" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">LocalDateTime</span><span class="op">(</span>java<span class="op">.</span><span class="fu">time</span><span class="op">.</span><span class="fu">LocalDateTime</span> value<span class="op">)</span> <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb73-11"><a href="#cb73-11" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> LocalDateTime <span class="op">{</span></span>
<span id="cb73-12"><a href="#cb73-12" aria-hidden="true" tabindex="-1"></a>            Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>value<span class="op">,</span> <span class="st">&quot;value must not be null&quot;</span><span class="op">);</span></span>
<span id="cb73-13"><a href="#cb73-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb73-14"><a href="#cb73-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb73-15"><a href="#cb73-15" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb73-16"><a href="#cb73-16" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">LocalDate</span><span class="op">(</span>java<span class="op">.</span><span class="fu">time</span><span class="op">.</span><span class="fu">LocalDate</span> value<span class="op">)</span> <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb73-17"><a href="#cb73-17" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> LocalDate <span class="op">{</span></span>
<span id="cb73-18"><a href="#cb73-18" aria-hidden="true" tabindex="-1"></a>            Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>value<span class="op">,</span> <span class="st">&quot;value must not be null&quot;</span><span class="op">);</span></span>
<span id="cb73-19"><a href="#cb73-19" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb73-20"><a href="#cb73-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb73-21"><a href="#cb73-21" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb73-22"><a href="#cb73-22" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">LocalTime</span><span class="op">(</span>java<span class="op">.</span><span class="fu">time</span><span class="op">.</span><span class="fu">LocalTime</span> value<span class="op">)</span> <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb73-23"><a href="#cb73-23" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> LocalTime <span class="op">{</span></span>
<span id="cb73-24"><a href="#cb73-24" aria-hidden="true" tabindex="-1"></a>            Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>value<span class="op">,</span> <span class="st">&quot;value must not be null&quot;</span><span class="op">);</span></span>
<span id="cb73-25"><a href="#cb73-25" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb73-26"><a href="#cb73-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb73-27"><a href="#cb73-27" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb73-28"><a href="#cb73-28" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Duration</span><span class="op">(</span>java<span class="op">.</span><span class="fu">time</span><span class="op">.</span><span class="fu">Duration</span> value<span class="op">)</span> <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb73-29"><a href="#cb73-29" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="bu">Duration</span> <span class="op">{</span></span>
<span id="cb73-30"><a href="#cb73-30" aria-hidden="true" tabindex="-1"></a>            Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>value<span class="op">,</span> <span class="st">&quot;value must not be null&quot;</span><span class="op">);</span></span>
<span id="cb73-31"><a href="#cb73-31" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb73-32"><a href="#cb73-32" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb73-33"><a href="#cb73-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb73-34"><a href="#cb73-34" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb73-35"><a href="#cb73-35" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And <code>Exception</code>s must be in the top 10 things to want to log.</p>
<div class="sourceCode" id="cb74"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb74-1"><a href="#cb74-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Value <span class="op">{</span></span>
<span id="cb74-2"><a href="#cb74-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb74-3"><a href="#cb74-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb74-4"><a href="#cb74-4" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Throwable</span><span class="op">(</span>java<span class="op">.</span><span class="fu">lang</span><span class="op">.</span><span class="fu">Throwable</span> value<span class="op">)</span> <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb74-5"><a href="#cb74-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="bu">Throwable</span> <span class="op">{</span></span>
<span id="cb74-6"><a href="#cb74-6" aria-hidden="true" tabindex="-1"></a>            Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>value<span class="op">,</span> <span class="st">&quot;value must not be null&quot;</span><span class="op">);</span></span>
<span id="cb74-7"><a href="#cb74-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb74-8"><a href="#cb74-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb74-9"><a href="#cb74-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb74-10"><a href="#cb74-10" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb74-11"><a href="#cb74-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Logging Lists is one of the things that we need to support to keep parity with <code>µ/log</code> and <code>tracing</code></p>
<div class="sourceCode" id="cb75"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb75-1"><a href="#cb75-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Value <span class="op">{</span></span>
<span id="cb75-2"><a href="#cb75-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb75-3"><a href="#cb75-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb75-4"><a href="#cb75-4" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">List</span><span class="op">(</span>java<span class="op">.</span><span class="fu">util</span><span class="op">.</span><span class="fu">List</span><span class="op">&lt;</span>Value<span class="op">&gt;</span> value<span class="op">)</span> <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb75-5"><a href="#cb75-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb75-6"><a href="#cb75-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb75-7"><a href="#cb75-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb75-8"><a href="#cb75-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>At which point, we need to talk about null.</p>
<p>In all the cases so far, I've added an <code>Objects.requireNonNull</code> to the canonical constructor for each of these cases. To me this tracks because it wouldn't make much sense to have both a "String" and an "Instant" with null values allowed.</p>
<div class="sourceCode" id="cb76"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb76-1"><a href="#cb76-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Should this be true or false? </span></span>
<span id="cb76-2"><a href="#cb76-2" aria-hidden="true" tabindex="-1"></a><span class="co">// If it should be true that will require some wacky equals method.</span></span>
<span id="cb76-3"><a href="#cb76-3" aria-hidden="true" tabindex="-1"></a>Objects<span class="op">.</span><span class="fu">equals</span><span class="op">(</span></span>
<span id="cb76-4"><a href="#cb76-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">new</span> Log<span class="op">.</span><span class="fu">Entry</span><span class="op">.</span><span class="fu">Value</span><span class="op">.</span><span class="fu">String</span><span class="op">(</span><span class="kw">null</span><span class="op">),</span></span>
<span id="cb76-5"><a href="#cb76-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">new</span> Log<span class="op">.</span><span class="fu">Entry</span><span class="op">.</span><span class="fu">Value</span><span class="op">.</span><span class="fu">Instant</span><span class="op">(</span><span class="kw">null</span><span class="op">),</span></span>
<span id="cb76-6"><a href="#cb76-6" aria-hidden="true" tabindex="-1"></a><span class="op">)</span></span></code></pre></div>
<p>The problem is, people end up with null values pretty much constantly. Logging that you are about to perform some operation on an entity and that entity is unexpectedly null is unbelievably common.</p>
<div class="sourceCode" id="cb77"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb77-1"><a href="#cb77-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Sorry, we crashed because of a log!</span></span>
<span id="cb77-2"><a href="#cb77-2" aria-hidden="true" tabindex="-1"></a><span class="kw">new</span> Log<span class="op">.</span><span class="fu">Entry</span><span class="op">.</span><span class="fu">Value</span><span class="op">.</span><span class="fu">String</span><span class="op">(</span>s<span class="op">);</span></span></code></pre></div>
<p>To remedy this, I could add constructor functions to <code>Log.Entry.Value</code> which automatically handle null values.</p>
<div class="sourceCode" id="cb78"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb78-1"><a href="#cb78-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Value <span class="op">{</span></span>
<span id="cb78-2"><a href="#cb78-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb78-3"><a href="#cb78-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb78-4"><a href="#cb78-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> Value<span class="op">.</span><span class="fu">String</span> <span class="fu">of</span><span class="op">(</span>java<span class="op">.</span><span class="fu">lang</span><span class="op">.</span><span class="fu">String</span> value<span class="op">)</span> <span class="op">{</span></span>
<span id="cb78-5"><a href="#cb78-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>value <span class="op">==</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb78-6"><a href="#cb78-6" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb78-7"><a href="#cb78-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb78-8"><a href="#cb78-8" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb78-9"><a href="#cb78-9" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">new</span> <span class="bu">String</span><span class="op">(</span>value<span class="op">);</span></span>
<span id="cb78-10"><a href="#cb78-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb78-11"><a href="#cb78-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb78-12"><a href="#cb78-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb78-13"><a href="#cb78-13" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">String</span><span class="op">(</span>java<span class="op">.</span><span class="fu">lang</span><span class="op">.</span><span class="fu">String</span> value<span class="op">)</span> <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb78-14"><a href="#cb78-14" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb78-15"><a href="#cb78-15" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb78-16"><a href="#cb78-16" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="bu">String</span> <span class="op">{</span></span>
<span id="cb78-17"><a href="#cb78-17" aria-hidden="true" tabindex="-1"></a>            Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>value<span class="op">,</span> <span class="st">&quot;value must not be null&quot;</span><span class="op">);</span></span>
<span id="cb78-18"><a href="#cb78-18" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb78-19"><a href="#cb78-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb78-20"><a href="#cb78-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb78-21"><a href="#cb78-21" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb78-22"><a href="#cb78-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>For the primitive types it will be a little pointless, but it can help avoid errors with their wrappers.</p>
<div class="sourceCode" id="cb79"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb79-1"><a href="#cb79-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Value <span class="op">{</span></span>
<span id="cb79-2"><a href="#cb79-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb79-3"><a href="#cb79-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb79-4"><a href="#cb79-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> Value<span class="op">.</span><span class="fu">Boolean</span> <span class="fu">of</span><span class="op">(</span><span class="dt">boolean</span> value<span class="op">)</span> <span class="op">{</span></span>
<span id="cb79-5"><a href="#cb79-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="bu">Boolean</span><span class="op">(</span>value<span class="op">);</span></span>
<span id="cb79-6"><a href="#cb79-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb79-7"><a href="#cb79-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb79-8"><a href="#cb79-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> Value<span class="op">.</span><span class="fu">Boolean</span> <span class="fu">of</span><span class="op">(</span>java<span class="op">.</span><span class="fu">lang</span><span class="op">.</span><span class="fu">Boolean</span> value<span class="op">)</span> <span class="op">{</span></span>
<span id="cb79-9"><a href="#cb79-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>value <span class="op">==</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb79-10"><a href="#cb79-10" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb79-11"><a href="#cb79-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb79-12"><a href="#cb79-12" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb79-13"><a href="#cb79-13" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">new</span> <span class="bu">Boolean</span><span class="op">(</span>value<span class="op">);</span></span>
<span id="cb79-14"><a href="#cb79-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb79-15"><a href="#cb79-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb79-16"><a href="#cb79-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb79-17"><a href="#cb79-17" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Boolean</span><span class="op">(</span><span class="dt">boolean</span> value<span class="op">)</span> <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb79-18"><a href="#cb79-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb79-19"><a href="#cb79-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb79-20"><a href="#cb79-20" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb79-21"><a href="#cb79-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>But with lists, there is another foot gun we have just loaded. Lists made with <code>List.of</code> do not support <code>null</code> elements, so it is more than likely folks will end up with seemingly okay code and an inexplicable crash.</p>
<div class="sourceCode" id="cb80"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb80-1"><a href="#cb80-1" aria-hidden="true" tabindex="-1"></a><span class="co">// If null, will still crash!</span></span>
<span id="cb80-2"><a href="#cb80-2" aria-hidden="true" tabindex="-1"></a>Log<span class="op">.</span><span class="fu">Entry</span><span class="op">.</span><span class="fu">Value</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb80-3"><a href="#cb80-3" aria-hidden="true" tabindex="-1"></a>    Log<span class="op">.</span><span class="fu">Entry</span><span class="op">.</span><span class="fu">Value</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>someString<span class="op">)</span></span>
<span id="cb80-4"><a href="#cb80-4" aria-hidden="true" tabindex="-1"></a><span class="op">))</span></span></code></pre></div>
<p>So to sidestep this, we need to make our own null. It feels contrived, I know.</p>
<div class="sourceCode" id="cb81"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb81-1"><a href="#cb81-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Value <span class="op">{</span></span>
<span id="cb81-2"><a href="#cb81-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">enum</span> Null <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb81-3"><a href="#cb81-3" aria-hidden="true" tabindex="-1"></a>        INSTANCE<span class="op">;</span></span>
<span id="cb81-4"><a href="#cb81-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb81-5"><a href="#cb81-5" aria-hidden="true" tabindex="-1"></a>        <span class="at">@Override</span></span>
<span id="cb81-6"><a href="#cb81-6" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> java<span class="op">.</span><span class="fu">lang</span><span class="op">.</span><span class="fu">String</span> <span class="fu">toString</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb81-7"><a href="#cb81-7" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="st">&quot;Null&quot;</span><span class="op">;</span></span>
<span id="cb81-8"><a href="#cb81-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb81-9"><a href="#cb81-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb81-10"><a href="#cb81-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Then for all the constructor functions, this becomes the fallback.</p>
<div class="sourceCode" id="cb82"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb82-1"><a href="#cb82-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Value <span class="op">{</span></span>
<span id="cb82-2"><a href="#cb82-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb82-3"><a href="#cb82-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb82-4"><a href="#cb82-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> Value <span class="fu">of</span><span class="op">(</span>java<span class="op">.</span><span class="fu">lang</span><span class="op">.</span><span class="fu">String</span> value<span class="op">)</span> <span class="op">{</span></span>
<span id="cb82-5"><a href="#cb82-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>value <span class="op">==</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb82-6"><a href="#cb82-6" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> Null<span class="op">.</span><span class="fu">INSTANCE</span><span class="op">;</span></span>
<span id="cb82-7"><a href="#cb82-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb82-8"><a href="#cb82-8" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb82-9"><a href="#cb82-9" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">new</span> <span class="bu">String</span><span class="op">(</span>value<span class="op">);</span></span>
<span id="cb82-10"><a href="#cb82-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb82-11"><a href="#cb82-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb82-12"><a href="#cb82-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb82-13"><a href="#cb82-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">enum</span> Null <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb82-14"><a href="#cb82-14" aria-hidden="true" tabindex="-1"></a>        INSTANCE<span class="op">;</span></span>
<span id="cb82-15"><a href="#cb82-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb82-16"><a href="#cb82-16" aria-hidden="true" tabindex="-1"></a>        <span class="at">@Override</span></span>
<span id="cb82-17"><a href="#cb82-17" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> java<span class="op">.</span><span class="fu">lang</span><span class="op">.</span><span class="fu">String</span> <span class="fu">toString</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb82-18"><a href="#cb82-18" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="st">&quot;Null&quot;</span><span class="op">;</span></span>
<span id="cb82-19"><a href="#cb82-19" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb82-20"><a href="#cb82-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb82-21"><a href="#cb82-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb82-22"><a href="#cb82-22" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">String</span><span class="op">(</span>java<span class="op">.</span><span class="fu">lang</span><span class="op">.</span><span class="fu">String</span> value<span class="op">)</span> <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb82-23"><a href="#cb82-23" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb82-24"><a href="#cb82-24" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb82-25"><a href="#cb82-25" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="bu">String</span> <span class="op">{</span></span>
<span id="cb82-26"><a href="#cb82-26" aria-hidden="true" tabindex="-1"></a>            Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>value<span class="op">,</span> <span class="st">&quot;value must not be null&quot;</span><span class="op">);</span></span>
<span id="cb82-27"><a href="#cb82-27" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb82-28"><a href="#cb82-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb82-29"><a href="#cb82-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb82-30"><a href="#cb82-30" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb82-31"><a href="#cb82-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Which solves our current issue fairly neatly.</p>
<div class="sourceCode" id="cb83"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb83-1"><a href="#cb83-1" aria-hidden="true" tabindex="-1"></a><span class="bu">String</span> s1 <span class="op">=</span> <span class="st">&quot;abc&quot;</span><span class="op">;</span></span>
<span id="cb83-2"><a href="#cb83-2" aria-hidden="true" tabindex="-1"></a><span class="bu">String</span> s2 <span class="op">=</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb83-3"><a href="#cb83-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb83-4"><a href="#cb83-4" aria-hidden="true" tabindex="-1"></a><span class="co">// Our &quot;Null&quot; isn&#39;t &quot;null&quot;, so all is well.</span></span>
<span id="cb83-5"><a href="#cb83-5" aria-hidden="true" tabindex="-1"></a>Log<span class="op">.</span><span class="fu">Entry</span><span class="op">.</span><span class="fu">Value</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb83-6"><a href="#cb83-6" aria-hidden="true" tabindex="-1"></a>    Log<span class="op">.</span><span class="fu">Entry</span><span class="op">.</span><span class="fu">Value</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>s1<span class="op">),</span></span>
<span id="cb83-7"><a href="#cb83-7" aria-hidden="true" tabindex="-1"></a>    Log<span class="op">.</span><span class="fu">Entry</span><span class="op">.</span><span class="fu">Value</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>s2<span class="op">)</span>  </span>
<span id="cb83-8"><a href="#cb83-8" aria-hidden="true" tabindex="-1"></a><span class="op">))</span></span></code></pre></div>
<p>The remaining kinds of data to consider are maps and sets. Both would have had the same issues with null and their convenient constructor functions in <code>Map.of()</code> and <code>Set.of()</code> so it is good to have that resolved.</p>
<div class="sourceCode" id="cb84"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb84-1"><a href="#cb84-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Value <span class="op">{</span></span>
<span id="cb84-2"><a href="#cb84-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb84-3"><a href="#cb84-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb84-4"><a href="#cb84-4" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Map</span><span class="op">(</span>java<span class="op">.</span><span class="fu">util</span><span class="op">.</span><span class="fu">Map</span><span class="op">&lt;</span>java<span class="op">.</span><span class="fu">lang</span><span class="op">.</span><span class="fu">String</span><span class="op">,</span> Value<span class="op">&gt;</span> value<span class="op">)</span> </span>
<span id="cb84-5"><a href="#cb84-5" aria-hidden="true" tabindex="-1"></a>            <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb84-6"><a href="#cb84-6" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="bu">Map</span><span class="op">(</span>java<span class="op">.</span><span class="fu">util</span><span class="op">.</span><span class="fu">Map</span><span class="op">&lt;</span>java<span class="op">.</span><span class="fu">lang</span><span class="op">.</span><span class="fu">String</span><span class="op">,</span> Value<span class="op">&gt;</span> value<span class="op">)</span> <span class="op">{</span></span>
<span id="cb84-7"><a href="#cb84-7" aria-hidden="true" tabindex="-1"></a>            Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>value<span class="op">,</span> <span class="st">&quot;value must not be null&quot;</span><span class="op">);</span></span>
<span id="cb84-8"><a href="#cb84-8" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">value</span> <span class="op">=</span> value<span class="op">.</span><span class="fu">entrySet</span><span class="op">()</span></span>
<span id="cb84-9"><a href="#cb84-9" aria-hidden="true" tabindex="-1"></a>                    <span class="op">.</span><span class="fu">stream</span><span class="op">()</span></span>
<span id="cb84-10"><a href="#cb84-10" aria-hidden="true" tabindex="-1"></a>                    <span class="op">.</span><span class="fu">collect</span><span class="op">(</span>Collectors<span class="op">.</span><span class="fu">toUnmodifiableMap</span><span class="op">(</span></span>
<span id="cb84-11"><a href="#cb84-11" aria-hidden="true" tabindex="-1"></a>                            java<span class="op">.</span><span class="fu">util</span><span class="op">.</span><span class="fu">Map</span><span class="op">.</span><span class="fu">Entry</span><span class="op">::</span>getKey<span class="op">,</span></span>
<span id="cb84-12"><a href="#cb84-12" aria-hidden="true" tabindex="-1"></a>                            entry <span class="op">-&gt;</span> entry<span class="op">.</span><span class="fu">getValue</span><span class="op">()</span> <span class="op">==</span> <span class="kw">null</span></span>
<span id="cb84-13"><a href="#cb84-13" aria-hidden="true" tabindex="-1"></a>                                    <span class="op">?</span> Null<span class="op">.</span><span class="fu">INSTANCE</span> </span>
<span id="cb84-14"><a href="#cb84-14" aria-hidden="true" tabindex="-1"></a>                                    <span class="op">:</span> entry<span class="op">.</span><span class="fu">getValue</span><span class="op">()</span></span>
<span id="cb84-15"><a href="#cb84-15" aria-hidden="true" tabindex="-1"></a>                    <span class="op">));</span></span>
<span id="cb84-16"><a href="#cb84-16" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb84-17"><a href="#cb84-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb84-18"><a href="#cb84-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb84-19"><a href="#cb84-19" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Set</span><span class="op">(</span>java<span class="op">.</span><span class="fu">util</span><span class="op">.</span><span class="fu">Set</span><span class="op">&lt;</span>Value<span class="op">&gt;</span> value<span class="op">)</span> <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb84-20"><a href="#cb84-20" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="bu">Set</span><span class="op">(</span>java<span class="op">.</span><span class="fu">util</span><span class="op">.</span><span class="fu">Set</span><span class="op">&lt;</span>Value<span class="op">&gt;</span> value<span class="op">)</span> <span class="op">{</span></span>
<span id="cb84-21"><a href="#cb84-21" aria-hidden="true" tabindex="-1"></a>            Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>value<span class="op">,</span> <span class="st">&quot;value must not be null&quot;</span><span class="op">);</span></span>
<span id="cb84-22"><a href="#cb84-22" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">value</span> <span class="op">=</span> value<span class="op">.</span><span class="fu">stream</span><span class="op">()</span></span>
<span id="cb84-23"><a href="#cb84-23" aria-hidden="true" tabindex="-1"></a>                    <span class="op">.</span><span class="fu">map</span><span class="op">(</span>v <span class="op">-&gt;</span> v <span class="op">==</span> <span class="kw">null</span> <span class="op">?</span> Null<span class="op">.</span><span class="fu">INSTANCE</span> <span class="op">:</span> v<span class="op">)</span></span>
<span id="cb84-24"><a href="#cb84-24" aria-hidden="true" tabindex="-1"></a>                    <span class="op">.</span><span class="fu">collect</span><span class="op">(</span>Collectors<span class="op">.</span><span class="fu">toUnmodifiableSet</span><span class="op">());</span></span>
<span id="cb84-25"><a href="#cb84-25" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb84-26"><a href="#cb84-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb84-27"><a href="#cb84-27" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>For <code>Map</code>s there is no intrinsic reason it has to be this way, but I chose to restrict the keys to be <code>String</code>s. This is both more convenient for eventual serialization to JSON and avoids issues like having two keys which would serialize to the same form if string-ified.</p>
<div class="sourceCode" id="cb85"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb85-1"><a href="#cb85-1" aria-hidden="true" tabindex="-1"></a><span class="co">// This would be annoying to handle in JSON</span></span>
<span id="cb85-2"><a href="#cb85-2" aria-hidden="true" tabindex="-1"></a>Log<span class="op">.</span><span class="fu">Entry</span><span class="op">.</span><span class="fu">Value</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="bu">Map</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb85-3"><a href="#cb85-3" aria-hidden="true" tabindex="-1"></a>    Log<span class="op">.</span><span class="fu">Entry</span><span class="op">.</span><span class="fu">Value</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="dv">123</span><span class="op">),</span> Log<span class="op">.</span><span class="fu">Entry</span><span class="op">.</span><span class="fu">Value</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;abc&quot;</span><span class="op">),</span></span>
<span id="cb85-4"><a href="#cb85-4" aria-hidden="true" tabindex="-1"></a>    Log<span class="op">.</span><span class="fu">Entry</span><span class="op">.</span><span class="fu">Value</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;123&quot;</span><span class="op">),</span> Log<span class="op">.</span><span class="fu">Entry</span><span class="op">.</span><span class="fu">Value</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;def&quot;</span><span class="op">),</span></span>
<span id="cb85-5"><a href="#cb85-5" aria-hidden="true" tabindex="-1"></a><span class="op">))</span></span></code></pre></div>
<p>Now for the last value kind, I promise. Occasionally producing the value for a log might be either expensive, intrinsically fallible, or both - like fetching a value from a remote server. For this, we want to provide a way to lazily compute a value.</p>
<p>I took the implementation of this from a combo of <a href="https://javadoc.io/doc/io.vavr/vavr/0.9.2/io/vavr/Lazy.html">vavr's Lazy</a> and <a href="https://clojuredocs.org/clojure.core/delay">Clojure's delay</a>.</p>
<div class="sourceCode" id="cb86"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb86-1"><a href="#cb86-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Value <span class="op">{</span></span>
<span id="cb86-2"><a href="#cb86-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb86-3"><a href="#cb86-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb86-4"><a href="#cb86-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">final</span> <span class="kw">class</span> Lazy <span class="kw">implements</span> Value <span class="op">{</span></span>
<span id="cb86-5"><a href="#cb86-5" aria-hidden="true" tabindex="-1"></a>        <span class="co">// Implementation based off of clojure&#39;s Delay + vavr&#39;s Lazy</span></span>
<span id="cb86-6"><a href="#cb86-6" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="kw">volatile</span> Supplier<span class="op">&lt;?</span> <span class="kw">extends</span> Value<span class="op">&gt;</span> supplier<span class="op">;</span></span>
<span id="cb86-7"><a href="#cb86-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> Value value<span class="op">;</span></span>
<span id="cb86-8"><a href="#cb86-8" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb86-9"><a href="#cb86-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="fu">Lazy</span><span class="op">(</span>Supplier<span class="op">&lt;?</span> <span class="kw">extends</span> Value<span class="op">&gt;</span> supplier<span class="op">)</span> <span class="op">{</span></span>
<span id="cb86-10"><a href="#cb86-10" aria-hidden="true" tabindex="-1"></a>            Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span></span>
<span id="cb86-11"><a href="#cb86-11" aria-hidden="true" tabindex="-1"></a>                    supplier<span class="op">,</span> </span>
<span id="cb86-12"><a href="#cb86-12" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;supplier must not be null&quot;</span></span>
<span id="cb86-13"><a href="#cb86-13" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb86-14"><a href="#cb86-14" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">supplier</span> <span class="op">=</span> supplier<span class="op">;</span></span>
<span id="cb86-15"><a href="#cb86-15" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">value</span> <span class="op">=</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb86-16"><a href="#cb86-16" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb86-17"><a href="#cb86-17" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb86-18"><a href="#cb86-18" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Value <span class="fu">value</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb86-19"><a href="#cb86-19" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>supplier <span class="op">!=</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb86-20"><a href="#cb86-20" aria-hidden="true" tabindex="-1"></a>                <span class="kw">synchronized</span> <span class="op">(</span><span class="kw">this</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb86-21"><a href="#cb86-21" aria-hidden="true" tabindex="-1"></a>                    <span class="dt">final</span> var s <span class="op">=</span> supplier<span class="op">;</span></span>
<span id="cb86-22"><a href="#cb86-22" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">if</span> <span class="op">(</span>s <span class="op">!=</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb86-23"><a href="#cb86-23" aria-hidden="true" tabindex="-1"></a>                        <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb86-24"><a href="#cb86-24" aria-hidden="true" tabindex="-1"></a>                            <span class="kw">this</span><span class="op">.</span><span class="fu">value</span> <span class="op">=</span> Objects<span class="op">.</span><span class="fu">requireNonNullElse</span><span class="op">(</span></span>
<span id="cb86-25"><a href="#cb86-25" aria-hidden="true" tabindex="-1"></a>                                    s<span class="op">.</span><span class="fu">get</span><span class="op">(),</span> </span>
<span id="cb86-26"><a href="#cb86-26" aria-hidden="true" tabindex="-1"></a>                                    Null<span class="op">.</span><span class="fu">INSTANCE</span></span>
<span id="cb86-27"><a href="#cb86-27" aria-hidden="true" tabindex="-1"></a>                            <span class="op">);</span></span>
<span id="cb86-28"><a href="#cb86-28" aria-hidden="true" tabindex="-1"></a>                        <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span>java<span class="op">.</span><span class="fu">lang</span><span class="op">.</span><span class="fu">Throwable</span> throwable<span class="op">)</span> <span class="op">{</span></span>
<span id="cb86-29"><a href="#cb86-29" aria-hidden="true" tabindex="-1"></a>                            <span class="kw">this</span><span class="op">.</span><span class="fu">value</span> <span class="op">=</span> <span class="kw">new</span> <span class="bu">Throwable</span><span class="op">(</span>throwable<span class="op">);</span></span>
<span id="cb86-30"><a href="#cb86-30" aria-hidden="true" tabindex="-1"></a>                        <span class="op">}</span></span>
<span id="cb86-31"><a href="#cb86-31" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">this</span><span class="op">.</span><span class="fu">supplier</span> <span class="op">=</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb86-32"><a href="#cb86-32" aria-hidden="true" tabindex="-1"></a>                    <span class="op">}</span></span>
<span id="cb86-33"><a href="#cb86-33" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb86-34"><a href="#cb86-34" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb86-35"><a href="#cb86-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb86-36"><a href="#cb86-36" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">value</span><span class="op">;</span></span>
<span id="cb86-37"><a href="#cb86-37" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb86-38"><a href="#cb86-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb86-39"><a href="#cb86-39" aria-hidden="true" tabindex="-1"></a>        <span class="at">@Override</span></span>
<span id="cb86-40"><a href="#cb86-40" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> java<span class="op">.</span><span class="fu">lang</span><span class="op">.</span><span class="fu">String</span> <span class="fu">toString</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb86-41"><a href="#cb86-41" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>supplier <span class="op">!=</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb86-42"><a href="#cb86-42" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="st">&quot;Lazy[pending]&quot;</span><span class="op">;</span></span>
<span id="cb86-43"><a href="#cb86-43" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb86-44"><a href="#cb86-44" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="st">&quot;Lazy[realized: value=&quot;</span> <span class="op">+</span> <span class="fu">value</span><span class="op">()</span> <span class="op">+</span> <span class="st">&quot;]&quot;</span><span class="op">;</span></span>
<span id="cb86-45"><a href="#cb86-45" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb86-46"><a href="#cb86-46" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb86-47"><a href="#cb86-47" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb86-48"><a href="#cb86-48" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And this gets its own <code>ofLazy</code> factory functions of course.</p>
<div class="sourceCode" id="cb87"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb87-1"><a href="#cb87-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Value <span class="op">{</span></span>
<span id="cb87-2"><a href="#cb87-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb87-3"><a href="#cb87-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb87-4"><a href="#cb87-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> Value <span class="fu">ofLazy</span><span class="op">(</span>Supplier<span class="op">&lt;</span>Value<span class="op">&gt;</span> valueSupplier<span class="op">)</span> <span class="op">{</span></span>
<span id="cb87-5"><a href="#cb87-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> Value<span class="op">.</span><span class="fu">Lazy</span><span class="op">(</span>valueSupplier<span class="op">);</span></span>
<span id="cb87-6"><a href="#cb87-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb87-7"><a href="#cb87-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb87-8"><a href="#cb87-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="op">&lt;</span>T<span class="op">&gt;</span> Value <span class="fu">ofLazy</span><span class="op">(</span>T value<span class="op">,</span> Function<span class="op">&lt;</span>T<span class="op">,</span> Value<span class="op">&gt;</span> toValue<span class="op">)</span> <span class="op">{</span></span>
<span id="cb87-9"><a href="#cb87-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> Value<span class="op">.</span><span class="fu">Lazy</span><span class="op">(()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb87-10"><a href="#cb87-10" aria-hidden="true" tabindex="-1"></a>            var v <span class="op">=</span> toValue<span class="op">.</span><span class="fu">apply</span><span class="op">(</span>value<span class="op">);</span></span>
<span id="cb87-11"><a href="#cb87-11" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> v <span class="op">==</span> <span class="kw">null</span> <span class="op">?</span> Value<span class="op">.</span><span class="fu">Null</span><span class="op">.</span><span class="fu">INSTANCE</span> <span class="op">:</span> v<span class="op">;</span></span>
<span id="cb87-12"><a href="#cb87-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">});</span></span>
<span id="cb87-13"><a href="#cb87-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb87-14"><a href="#cb87-14" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb87-15"><a href="#cb87-15" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb87-16"><a href="#cb87-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Now to make a log it will look like this.</p>
<div class="sourceCode" id="cb88"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb88-1"><a href="#cb88-1" aria-hidden="true" tabindex="-1"></a>log<span class="op">.</span><span class="fu">info</span><span class="op">(</span><span class="st">&quot;dog-barked&quot;</span><span class="op">,</span> <span class="kw">new</span> Log<span class="op">.</span><span class="fu">Entry</span><span class="op">(</span></span>
<span id="cb88-2"><a href="#cb88-2" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;name&quot;</span><span class="op">,</span></span>
<span id="cb88-3"><a href="#cb88-3" aria-hidden="true" tabindex="-1"></a>        Log<span class="op">.</span><span class="fu">Entry</span><span class="op">.</span><span class="fu">Value</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;gunny&quot;</span><span class="op">)</span></span>
<span id="cb88-4"><a href="#cb88-4" aria-hidden="true" tabindex="-1"></a><span class="op">));</span></span></code></pre></div>
<p>Which is still a bit too verbose, so for all of those Value constructor functions I will add a matching one in <code>Log.Entry</code>.</p>
<div class="sourceCode" id="cb89"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb89-1"><a href="#cb89-1" aria-hidden="true" tabindex="-1"></a>log<span class="op">.</span><span class="fu">info</span><span class="op">(</span><span class="st">&quot;dog-barked&quot;</span><span class="op">,</span> Log<span class="op">.</span><span class="fu">Entry</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;name&quot;</span><span class="op">,</span> <span class="st">&quot;gunny&quot;</span><span class="op">));</span></span></code></pre></div>
<p>Which is finally terse enough that I could believe your average Jane or Joe writing it.</p>
<h3 id="flake">Flake</h3>
<p>Now a bit of a roundup, I am giving logs the <code>Flake</code> from <code>µ/log</code>. I actually copied the class exactly as written.</p>
<div class="sourceCode" id="cb90"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb90-1"><a href="#cb90-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> sealed <span class="kw">interface</span> Log <span class="op">{</span></span>
<span id="cb90-2"><a href="#cb90-2" aria-hidden="true" tabindex="-1"></a>    Flake <span class="fu">flake</span><span class="op">();</span></span>
<span id="cb90-3"><a href="#cb90-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb90-4"><a href="#cb90-4" aria-hidden="true" tabindex="-1"></a>    Occurrence <span class="fu">occurrence</span><span class="op">();</span></span>
<span id="cb90-5"><a href="#cb90-5" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb90-6"><a href="#cb90-6" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Level</span> <span class="fu">level</span><span class="op">();</span></span>
<span id="cb90-7"><a href="#cb90-7" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb90-8"><a href="#cb90-8" aria-hidden="true" tabindex="-1"></a>    Category <span class="fu">category</span><span class="op">();</span></span>
<span id="cb90-9"><a href="#cb90-9" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb90-10"><a href="#cb90-10" aria-hidden="true" tabindex="-1"></a>    <span class="bu">List</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> <span class="fu">entries</span><span class="op">();</span></span>
<span id="cb90-11"><a href="#cb90-11" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb90-12"><a href="#cb90-12" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Event</span><span class="op">(</span></span>
<span id="cb90-13"><a href="#cb90-13" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Flake flake<span class="op">,</span></span>
<span id="cb90-14"><a href="#cb90-14" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Occurrence<span class="op">.</span><span class="fu">PointInTime</span> occurrence<span class="op">,</span></span>
<span id="cb90-15"><a href="#cb90-15" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb90-16"><a href="#cb90-16" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Category category<span class="op">,</span></span>
<span id="cb90-17"><a href="#cb90-17" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">List</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> entries</span>
<span id="cb90-18"><a href="#cb90-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">implements</span> Log <span class="op">{</span></span>
<span id="cb90-19"><a href="#cb90-19" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="bu">Event</span><span class="op">(</span></span>
<span id="cb90-20"><a href="#cb90-20" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb90-21"><a href="#cb90-21" aria-hidden="true" tabindex="-1"></a>                Category category</span>
<span id="cb90-22"><a href="#cb90-22" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="op">{</span></span>
<span id="cb90-23"><a href="#cb90-23" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">(</span></span>
<span id="cb90-24"><a href="#cb90-24" aria-hidden="true" tabindex="-1"></a>                    Flake<span class="op">.</span><span class="fu">create</span><span class="op">(),</span> </span>
<span id="cb90-25"><a href="#cb90-25" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">new</span> Occurrence<span class="op">.</span><span class="fu">PointInTime</span><span class="op">(</span>Instant<span class="op">.</span><span class="fu">now</span><span class="op">()),</span></span>
<span id="cb90-26"><a href="#cb90-26" aria-hidden="true" tabindex="-1"></a>                    level<span class="op">,</span> </span>
<span id="cb90-27"><a href="#cb90-27" aria-hidden="true" tabindex="-1"></a>                    category</span>
<span id="cb90-28"><a href="#cb90-28" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb90-29"><a href="#cb90-29" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb90-30"><a href="#cb90-30" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb90-31"><a href="#cb90-31" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb90-32"><a href="#cb90-32" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">Span</span><span class="op">(</span></span>
<span id="cb90-33"><a href="#cb90-33" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Flake flake<span class="op">,</span></span>
<span id="cb90-34"><a href="#cb90-34" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Occurrence<span class="op">.</span><span class="fu">SpanOfTime</span> occurrence<span class="op">,</span></span>
<span id="cb90-35"><a href="#cb90-35" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb90-36"><a href="#cb90-36" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Category category<span class="op">,</span></span>
<span id="cb90-37"><a href="#cb90-37" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">List</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> entries</span>
<span id="cb90-38"><a href="#cb90-38" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">implements</span> Log <span class="op">{}</span></span>
<span id="cb90-39"><a href="#cb90-39" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb90-40"><a href="#cb90-40" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb90-41"><a href="#cb90-41" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="thread">Thread</h3>
<p>Apparently, getting the current thread is <a href="https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/5069">basically free</a> and since the ultimate goal is to allow sending logs around to different threads than when they originated gathering that for metadata feels appropriate.</p>
<div class="sourceCode" id="cb91"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb91-1"><a href="#cb91-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> sealed <span class="kw">interface</span> Log <span class="op">{</span></span>
<span id="cb91-2"><a href="#cb91-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Thread</span> <span class="fu">thread</span><span class="op">();</span></span>
<span id="cb91-3"><a href="#cb91-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb91-4"><a href="#cb91-4" aria-hidden="true" tabindex="-1"></a>    Flake <span class="fu">flake</span><span class="op">();</span></span>
<span id="cb91-5"><a href="#cb91-5" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb91-6"><a href="#cb91-6" aria-hidden="true" tabindex="-1"></a>    Occurrence <span class="fu">occurrence</span><span class="op">();</span></span>
<span id="cb91-7"><a href="#cb91-7" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb91-8"><a href="#cb91-8" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Level</span> <span class="fu">level</span><span class="op">();</span></span>
<span id="cb91-9"><a href="#cb91-9" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb91-10"><a href="#cb91-10" aria-hidden="true" tabindex="-1"></a>    Category <span class="fu">category</span><span class="op">();</span></span>
<span id="cb91-11"><a href="#cb91-11" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb91-12"><a href="#cb91-12" aria-hidden="true" tabindex="-1"></a>    <span class="bu">List</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> <span class="fu">entries</span><span class="op">();</span></span>
<span id="cb91-13"><a href="#cb91-13" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb91-14"><a href="#cb91-14" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Event</span><span class="op">(</span></span>
<span id="cb91-15"><a href="#cb91-15" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Thread</span> thread<span class="op">,</span></span>
<span id="cb91-16"><a href="#cb91-16" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Flake flake<span class="op">,</span></span>
<span id="cb91-17"><a href="#cb91-17" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Occurrence<span class="op">.</span><span class="fu">PointInTime</span> occurrence<span class="op">,</span></span>
<span id="cb91-18"><a href="#cb91-18" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb91-19"><a href="#cb91-19" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Category category<span class="op">,</span></span>
<span id="cb91-20"><a href="#cb91-20" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">List</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> entries</span>
<span id="cb91-21"><a href="#cb91-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">implements</span> Log <span class="op">{</span></span>
<span id="cb91-22"><a href="#cb91-22" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="bu">Event</span><span class="op">(</span></span>
<span id="cb91-23"><a href="#cb91-23" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb91-24"><a href="#cb91-24" aria-hidden="true" tabindex="-1"></a>                Category category</span>
<span id="cb91-25"><a href="#cb91-25" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="op">{</span></span>
<span id="cb91-26"><a href="#cb91-26" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">(</span></span>
<span id="cb91-27"><a href="#cb91-27" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">Thread</span><span class="op">.</span><span class="fu">currentThread</span><span class="op">(),</span> </span>
<span id="cb91-28"><a href="#cb91-28" aria-hidden="true" tabindex="-1"></a>                    Flake<span class="op">.</span><span class="fu">create</span><span class="op">(),</span> </span>
<span id="cb91-29"><a href="#cb91-29" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">new</span> Occurrence<span class="op">.</span><span class="fu">PointInTime</span><span class="op">(</span>Instant<span class="op">.</span><span class="fu">now</span><span class="op">()),</span> </span>
<span id="cb91-30"><a href="#cb91-30" aria-hidden="true" tabindex="-1"></a>                    level<span class="op">,</span> </span>
<span id="cb91-31"><a href="#cb91-31" aria-hidden="true" tabindex="-1"></a>                    category</span>
<span id="cb91-32"><a href="#cb91-32" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb91-33"><a href="#cb91-33" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb91-34"><a href="#cb91-34" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb91-35"><a href="#cb91-35" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb91-36"><a href="#cb91-36" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">Span</span><span class="op">(</span></span>
<span id="cb91-37"><a href="#cb91-37" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Thread</span> thread<span class="op">,</span></span>
<span id="cb91-38"><a href="#cb91-38" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Flake flake<span class="op">,</span></span>
<span id="cb91-39"><a href="#cb91-39" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Occurrence<span class="op">.</span><span class="fu">SpanOfTime</span> occurrence<span class="op">,</span></span>
<span id="cb91-40"><a href="#cb91-40" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb91-41"><a href="#cb91-41" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Category category<span class="op">,</span></span>
<span id="cb91-42"><a href="#cb91-42" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">List</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> entries</span>
<span id="cb91-43"><a href="#cb91-43" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">implements</span> Log <span class="op">{}</span></span>
<span id="cb91-44"><a href="#cb91-44" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb91-45"><a href="#cb91-45" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb91-46"><a href="#cb91-46" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="outcome">Outcome</h3>
<p>When a span finishes, <code>µ/log</code> records whether that span threw an exception and if so what the exception was. This is very doable, we just need to make sure to catch and re-throw anything thrown when performing work a span.</p>
<div class="sourceCode" id="cb92"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb92-1"><a href="#cb92-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Log <span class="op">{</span></span>
<span id="cb92-2"><a href="#cb92-2" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">Span</span><span class="op">(</span></span>
<span id="cb92-3"><a href="#cb92-3" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Thread</span> thread<span class="op">,</span></span>
<span id="cb92-4"><a href="#cb92-4" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Flake flake<span class="op">,</span></span>
<span id="cb92-5"><a href="#cb92-5" aria-hidden="true" tabindex="-1"></a>            Outcome outcome<span class="op">,</span></span>
<span id="cb92-6"><a href="#cb92-6" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Occurrence<span class="op">.</span><span class="fu">SpanOfTime</span> occurrence<span class="op">,</span></span>
<span id="cb92-7"><a href="#cb92-7" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb92-8"><a href="#cb92-8" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Category category<span class="op">,</span></span>
<span id="cb92-9"><a href="#cb92-9" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">List</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> entries<span class="op">)</span> <span class="kw">implements</span> Log <span class="op">{</span></span>
<span id="cb92-10"><a href="#cb92-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> sealed <span class="kw">interface</span> Outcome <span class="op">{</span></span>
<span id="cb92-11"><a href="#cb92-11" aria-hidden="true" tabindex="-1"></a>            <span class="kw">enum</span> Ok <span class="kw">implements</span> Outcome <span class="op">{</span></span>
<span id="cb92-12"><a href="#cb92-12" aria-hidden="true" tabindex="-1"></a>                INSTANCE<span class="op">;</span></span>
<span id="cb92-13"><a href="#cb92-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb92-14"><a href="#cb92-14" aria-hidden="true" tabindex="-1"></a>                <span class="at">@Override</span></span>
<span id="cb92-15"><a href="#cb92-15" aria-hidden="true" tabindex="-1"></a>                <span class="kw">public</span> <span class="bu">String</span> <span class="fu">toString</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb92-16"><a href="#cb92-16" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">return</span> <span class="st">&quot;Ok&quot;</span><span class="op">;</span></span>
<span id="cb92-17"><a href="#cb92-17" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb92-18"><a href="#cb92-18" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb92-19"><a href="#cb92-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb92-20"><a href="#cb92-20" aria-hidden="true" tabindex="-1"></a>            record <span class="bu">Error</span><span class="op">(</span><span class="bu">Throwable</span> throwable<span class="op">)</span> <span class="kw">implements</span> Outcome <span class="op">{</span></span>
<span id="cb92-21"><a href="#cb92-21" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb92-22"><a href="#cb92-22" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb92-23"><a href="#cb92-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb92-24"><a href="#cb92-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>If it weren't for this, <code>Span</code>s and <code>Event</code>s could probably be a single class. Unfortunately there isn't a neat value to put for an <code>Outcome</code> in an <code>Event</code>.</p>
<h3 id="context">Context</h3>
<p>The last thing to worry about is context. We need some mechanism for context to propagate from span to span and across method call boundaries and we need to define what exactly is allowed to be present in context.</p>
<p>The easiest to consider is global context. All we need is some <code>Log.Entry</code>s which will be included in every log.</p>
<div class="sourceCode" id="cb93"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb93-1"><a href="#cb93-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Log <span class="op">{</span></span>
<span id="cb93-2"><a href="#cb93-2" aria-hidden="true" tabindex="-1"></a>    sealed <span class="kw">interface</span> <span class="bu">Context</span> <span class="op">{</span></span>
<span id="cb93-3"><a href="#cb93-3" aria-hidden="true" tabindex="-1"></a>        record <span class="fu">Global</span><span class="op">(</span><span class="bu">List</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> entries<span class="op">)</span> <span class="kw">implements</span> <span class="bu">Context</span> <span class="op">{</span></span>
<span id="cb93-4"><a href="#cb93-4" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb93-5"><a href="#cb93-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb93-6"><a href="#cb93-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>I don't see any reason to be as strict as <code>tracing</code> is when it comes to setting global context more than once, so using <code>µ/log</code>'s storage strategy of an <code>AtomicReference</code> is likely good enough.</p>
<div class="sourceCode" id="cb94"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb94-1"><a href="#cb94-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Separate, internal, class to avoid exposing</span></span>
<span id="cb94-2"><a href="#cb94-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Globals <span class="op">{</span></span>
<span id="cb94-3"><a href="#cb94-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">final</span> <span class="bu">AtomicReference</span><span class="op">&lt;</span>Log<span class="op">.</span><span class="fu">Context</span><span class="op">.</span><span class="fu">Global</span><span class="op">&gt;</span> GLOBAL_CONTEXT <span class="op">=</span></span>
<span id="cb94-4"><a href="#cb94-4" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="bu">AtomicReference</span><span class="op">&lt;&gt;(</span><span class="kw">new</span> Log<span class="op">.</span><span class="fu">Context</span><span class="op">.</span><span class="fu">Global</span><span class="op">(</span><span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">()));</span></span>
<span id="cb94-5"><a href="#cb94-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And at any point it will be "safe" - if maybe leading to strange semantics - to set this context.</p>
<div class="sourceCode" id="cb95"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb95-1"><a href="#cb95-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Log <span class="op">{</span></span>
<span id="cb95-2"><a href="#cb95-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb95-3"><a href="#cb95-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb95-4"><a href="#cb95-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">void</span> <span class="fu">setGlobalContext</span><span class="op">(</span><span class="bu">List</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> entries<span class="op">)</span> <span class="op">{</span></span>
<span id="cb95-5"><a href="#cb95-5" aria-hidden="true" tabindex="-1"></a>        GLOBAL_CONTEXT<span class="op">.</span><span class="fu">set</span><span class="op">(</span><span class="kw">new</span> <span class="bu">Context</span><span class="op">.</span><span class="fu">Global</span><span class="op">(</span>entries<span class="op">));</span></span>
<span id="cb95-6"><a href="#cb95-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb95-7"><a href="#cb95-7" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb95-8"><a href="#cb95-8" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb95-9"><a href="#cb95-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>There are then two other kinds of "child" context. The first is "plain" context which is intended to just carry log entries down. The second is "span" context which doesn't carry entries but instead metadata about the current span.</p>
<div class="sourceCode" id="cb96"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb96-1"><a href="#cb96-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Log <span class="op">{</span></span>
<span id="cb96-2"><a href="#cb96-2" aria-hidden="true" tabindex="-1"></a>    sealed <span class="kw">interface</span> <span class="bu">Context</span> <span class="op">{</span></span>
<span id="cb96-3"><a href="#cb96-3" aria-hidden="true" tabindex="-1"></a>        record <span class="fu">Global</span><span class="op">(</span><span class="bu">List</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> entries<span class="op">)</span> <span class="kw">implements</span> <span class="bu">Context</span> <span class="op">{</span></span>
<span id="cb96-4"><a href="#cb96-4" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb96-5"><a href="#cb96-5" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb96-6"><a href="#cb96-6" aria-hidden="true" tabindex="-1"></a>        sealed <span class="kw">interface</span> Child <span class="kw">extends</span> <span class="bu">Context</span> <span class="op">{</span></span>
<span id="cb96-7"><a href="#cb96-7" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Context</span> <span class="fu">parent</span><span class="op">();</span></span>
<span id="cb96-8"><a href="#cb96-8" aria-hidden="true" tabindex="-1"></a>            </span>
<span id="cb96-9"><a href="#cb96-9" aria-hidden="true" tabindex="-1"></a>            record <span class="fu">Plain</span><span class="op">(</span></span>
<span id="cb96-10"><a href="#cb96-10" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">List</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> entries<span class="op">,</span></span>
<span id="cb96-11"><a href="#cb96-11" aria-hidden="true" tabindex="-1"></a>                    <span class="at">@Override</span> <span class="bu">Context</span> parent</span>
<span id="cb96-12"><a href="#cb96-12" aria-hidden="true" tabindex="-1"></a>            <span class="op">)</span> <span class="kw">implements</span> Child <span class="op">{</span></span>
<span id="cb96-13"><a href="#cb96-13" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb96-14"><a href="#cb96-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb96-15"><a href="#cb96-15" aria-hidden="true" tabindex="-1"></a>            record <span class="fu">Span</span><span class="op">(</span></span>
<span id="cb96-16"><a href="#cb96-16" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">Thread</span> thread<span class="op">,</span></span>
<span id="cb96-17"><a href="#cb96-17" aria-hidden="true" tabindex="-1"></a>                    Instant startedAt<span class="op">,</span></span>
<span id="cb96-18"><a href="#cb96-18" aria-hidden="true" tabindex="-1"></a>                    Flake spanId<span class="op">,</span></span>
<span id="cb96-19"><a href="#cb96-19" aria-hidden="true" tabindex="-1"></a>                    <span class="at">@Override</span> <span class="bu">Context</span> parent</span>
<span id="cb96-20"><a href="#cb96-20" aria-hidden="true" tabindex="-1"></a>            <span class="op">)</span> <span class="kw">implements</span> Child <span class="op">{</span></span>
<span id="cb96-21"><a href="#cb96-21" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb96-22"><a href="#cb96-22" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb96-23"><a href="#cb96-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb96-24"><a href="#cb96-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Both <code>Plain</code> and <code>Span</code> child contexts have a field linking to their parent context. This makes this a strange and wonderful kind of linked list.</p>
<p>To access the immediate parent or the root span, you can just crawl the linked list. This means that unlike <code>µ/log</code> we don't need to explicitly pass down a <code>:mulog/root-trace</code> or <code>:mulog/parent-trace</code>. We just have to <a href="https://rust-unofficial.github.io/too-many-lists/">accept linked lists with all their flaws</a>.</p>
<div class="sourceCode" id="cb97"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb97-1"><a href="#cb97-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Log <span class="op">{</span></span>
<span id="cb97-2"><a href="#cb97-2" aria-hidden="true" tabindex="-1"></a>    sealed <span class="kw">interface</span> <span class="bu">Context</span> <span class="op">{</span></span>
<span id="cb97-3"><a href="#cb97-3" aria-hidden="true" tabindex="-1"></a>        Optional<span class="op">&lt;</span>Child<span class="op">.</span><span class="fu">Span</span><span class="op">&gt;</span> <span class="fu">parentSpan</span><span class="op">();</span></span>
<span id="cb97-4"><a href="#cb97-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb97-5"><a href="#cb97-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">default</span> Optional<span class="op">&lt;</span>Child<span class="op">.</span><span class="fu">Span</span><span class="op">&gt;</span> <span class="fu">rootSpan</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb97-6"><a href="#cb97-6" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">parentSpan</span><span class="op">()</span></span>
<span id="cb97-7"><a href="#cb97-7" aria-hidden="true" tabindex="-1"></a>                    <span class="op">.</span><span class="fu">map</span><span class="op">(</span>parent <span class="op">-&gt;</span> parent<span class="op">.</span><span class="fu">rootSpan</span><span class="op">().</span><span class="fu">orElse</span><span class="op">(</span>parent<span class="op">));</span></span>
<span id="cb97-8"><a href="#cb97-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb97-9"><a href="#cb97-9" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb97-10"><a href="#cb97-10" aria-hidden="true" tabindex="-1"></a>        record <span class="fu">Global</span><span class="op">(</span><span class="bu">List</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> entries<span class="op">)</span> <span class="kw">implements</span> <span class="bu">Context</span> <span class="op">{</span></span>
<span id="cb97-11"><a href="#cb97-11" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span></span>
<span id="cb97-12"><a href="#cb97-12" aria-hidden="true" tabindex="-1"></a>            <span class="kw">public</span> Optional<span class="op">&lt;</span>Child<span class="op">.</span><span class="fu">Span</span><span class="op">&gt;</span> <span class="fu">parentSpan</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb97-13"><a href="#cb97-13" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> Optional<span class="op">.</span><span class="fu">empty</span><span class="op">();</span></span>
<span id="cb97-14"><a href="#cb97-14" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb97-15"><a href="#cb97-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb97-16"><a href="#cb97-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb97-17"><a href="#cb97-17" aria-hidden="true" tabindex="-1"></a>        sealed <span class="kw">interface</span> Child <span class="kw">extends</span> <span class="bu">Context</span> <span class="op">{</span></span>
<span id="cb97-18"><a href="#cb97-18" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Context</span> <span class="fu">parent</span><span class="op">();</span></span>
<span id="cb97-19"><a href="#cb97-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb97-20"><a href="#cb97-20" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span></span>
<span id="cb97-21"><a href="#cb97-21" aria-hidden="true" tabindex="-1"></a>            <span class="kw">default</span> Optional<span class="op">&lt;</span>Span<span class="op">&gt;</span> <span class="fu">parentSpan</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb97-22"><a href="#cb97-22" aria-hidden="true" tabindex="-1"></a>                var parent <span class="op">=</span> <span class="fu">parent</span><span class="op">();</span></span>
<span id="cb97-23"><a href="#cb97-23" aria-hidden="true" tabindex="-1"></a>                <span class="cf">if</span> <span class="op">(</span>parent <span class="kw">instanceof</span> Span parentSpan<span class="op">)</span> <span class="op">{</span></span>
<span id="cb97-24"><a href="#cb97-24" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">return</span> Optional<span class="op">.</span><span class="fu">of</span><span class="op">(</span>parentSpan<span class="op">);</span></span>
<span id="cb97-25"><a href="#cb97-25" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb97-26"><a href="#cb97-26" aria-hidden="true" tabindex="-1"></a>                <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb97-27"><a href="#cb97-27" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">return</span> parent<span class="op">.</span><span class="fu">parentSpan</span><span class="op">();</span></span>
<span id="cb97-28"><a href="#cb97-28" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb97-29"><a href="#cb97-29" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb97-30"><a href="#cb97-30" aria-hidden="true" tabindex="-1"></a>            </span>
<span id="cb97-31"><a href="#cb97-31" aria-hidden="true" tabindex="-1"></a>            record <span class="fu">Plain</span><span class="op">(</span></span>
<span id="cb97-32"><a href="#cb97-32" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">List</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> entries<span class="op">,</span></span>
<span id="cb97-33"><a href="#cb97-33" aria-hidden="true" tabindex="-1"></a>                    <span class="at">@Override</span> <span class="bu">Context</span> parent</span>
<span id="cb97-34"><a href="#cb97-34" aria-hidden="true" tabindex="-1"></a>            <span class="op">)</span> <span class="kw">implements</span> Child <span class="op">{</span></span>
<span id="cb97-35"><a href="#cb97-35" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb97-36"><a href="#cb97-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb97-37"><a href="#cb97-37" aria-hidden="true" tabindex="-1"></a>            record <span class="fu">Span</span><span class="op">(</span></span>
<span id="cb97-38"><a href="#cb97-38" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">Thread</span> thread<span class="op">,</span></span>
<span id="cb97-39"><a href="#cb97-39" aria-hidden="true" tabindex="-1"></a>                    Instant startedAt<span class="op">,</span></span>
<span id="cb97-40"><a href="#cb97-40" aria-hidden="true" tabindex="-1"></a>                    Flake spanId<span class="op">,</span></span>
<span id="cb97-41"><a href="#cb97-41" aria-hidden="true" tabindex="-1"></a>                    <span class="at">@Override</span> <span class="bu">Context</span> parent</span>
<span id="cb97-42"><a href="#cb97-42" aria-hidden="true" tabindex="-1"></a>            <span class="op">)</span> <span class="kw">implements</span> Child <span class="op">{</span></span>
<span id="cb97-43"><a href="#cb97-43" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb97-44"><a href="#cb97-44" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb97-45"><a href="#cb97-45" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb97-46"><a href="#cb97-46" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Now to propagate this non-global context a <code>ThreadLocal</code> will be used. Yes, I've mentioned many times how I want this design to be forward compatible with <code>ExtentLocal</code>s, but getting those early access builds is a bit hard, and I don't want to lock people who want to toy with this API today to have to figure that out.</p>
<div class="sourceCode" id="cb98"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb98-1"><a href="#cb98-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Globals <span class="op">{</span></span>
<span id="cb98-2"><a href="#cb98-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">final</span> <span class="bu">AtomicReference</span><span class="op">&lt;</span>Log<span class="op">.</span><span class="fu">Context</span><span class="op">.</span><span class="fu">Global</span><span class="op">&gt;</span> GLOBAL_CONTEXT <span class="op">=</span></span>
<span id="cb98-3"><a href="#cb98-3" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="bu">AtomicReference</span><span class="op">&lt;&gt;(</span><span class="kw">new</span> Log<span class="op">.</span><span class="fu">Context</span><span class="op">.</span><span class="fu">Global</span><span class="op">(</span><span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">()));</span></span>
<span id="cb98-4"><a href="#cb98-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb98-5"><a href="#cb98-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">/*</span></span>
<span id="cb98-6"><a href="#cb98-6" aria-hidden="true" tabindex="-1"></a><span class="co">     * This should be an extent local when it is possible to be so.</span></span>
<span id="cb98-7"><a href="#cb98-7" aria-hidden="true" tabindex="-1"></a><span class="co">     */</span></span>
<span id="cb98-8"><a href="#cb98-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">final</span> <span class="bu">ThreadLocal</span><span class="op">&lt;</span>Log<span class="op">.</span><span class="fu">Context</span><span class="op">.</span><span class="fu">Child</span><span class="op">&gt;</span> LOCAL_CONTEXT <span class="op">=</span></span>
<span id="cb98-9"><a href="#cb98-9" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="bu">ThreadLocal</span><span class="op">&lt;&gt;();</span></span>
<span id="cb98-10"><a href="#cb98-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Since the local context will contain a pointer to the global context that was established when it was formed, to get the current context we just need to check if there is a currently bound local context and if so use it. If not, we take from the global context.</p>
<div class="sourceCode" id="cb99"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb99-1"><a href="#cb99-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Log <span class="op">{</span></span>
<span id="cb99-2"><a href="#cb99-2" aria-hidden="true" tabindex="-1"></a>    sealed <span class="kw">interface</span> <span class="bu">Context</span> <span class="op">{</span></span>
<span id="cb99-3"><a href="#cb99-3" aria-hidden="true" tabindex="-1"></a>        <span class="dt">static</span> <span class="bu">Context</span> <span class="fu">current</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb99-4"><a href="#cb99-4" aria-hidden="true" tabindex="-1"></a>            var localContext <span class="op">=</span> LOCAL_CONTEXT<span class="op">.</span><span class="fu">get</span><span class="op">();</span></span>
<span id="cb99-5"><a href="#cb99-5" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> localContext <span class="op">==</span> <span class="kw">null</span> </span>
<span id="cb99-6"><a href="#cb99-6" aria-hidden="true" tabindex="-1"></a>                    <span class="op">?</span> GLOBAL_CONTEXT<span class="op">.</span><span class="fu">get</span><span class="op">()</span> </span>
<span id="cb99-7"><a href="#cb99-7" aria-hidden="true" tabindex="-1"></a>                    <span class="op">:</span> localContext<span class="op">;</span></span>
<span id="cb99-8"><a href="#cb99-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb99-9"><a href="#cb99-9" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb99-10"><a href="#cb99-10" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb99-11"><a href="#cb99-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb99-12"><a href="#cb99-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And every log will have some attached context.</p>
<div class="sourceCode" id="cb100"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb100-1"><a href="#cb100-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> sealed <span class="kw">interface</span> Log <span class="op">{</span></span>
<span id="cb100-2"><a href="#cb100-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Context</span> <span class="fu">context</span><span class="op">();</span></span>
<span id="cb100-3"><a href="#cb100-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb100-4"><a href="#cb100-4" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Thread</span> <span class="fu">thread</span><span class="op">();</span></span>
<span id="cb100-5"><a href="#cb100-5" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb100-6"><a href="#cb100-6" aria-hidden="true" tabindex="-1"></a>    Flake <span class="fu">flake</span><span class="op">();</span></span>
<span id="cb100-7"><a href="#cb100-7" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb100-8"><a href="#cb100-8" aria-hidden="true" tabindex="-1"></a>    Occurrence <span class="fu">occurrence</span><span class="op">();</span></span>
<span id="cb100-9"><a href="#cb100-9" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb100-10"><a href="#cb100-10" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Level</span> <span class="fu">level</span><span class="op">();</span></span>
<span id="cb100-11"><a href="#cb100-11" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb100-12"><a href="#cb100-12" aria-hidden="true" tabindex="-1"></a>    Category <span class="fu">category</span><span class="op">();</span></span>
<span id="cb100-13"><a href="#cb100-13" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb100-14"><a href="#cb100-14" aria-hidden="true" tabindex="-1"></a>    <span class="bu">List</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> <span class="fu">entries</span><span class="op">();</span></span>
<span id="cb100-15"><a href="#cb100-15" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb100-16"><a href="#cb100-16" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Event</span><span class="op">(</span></span>
<span id="cb100-17"><a href="#cb100-17" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Context</span> context<span class="op">,</span></span>
<span id="cb100-18"><a href="#cb100-18" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Thread</span> thread<span class="op">,</span></span>
<span id="cb100-19"><a href="#cb100-19" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Flake flake<span class="op">,</span></span>
<span id="cb100-20"><a href="#cb100-20" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Occurrence<span class="op">.</span><span class="fu">PointInTime</span> occurrence<span class="op">,</span></span>
<span id="cb100-21"><a href="#cb100-21" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb100-22"><a href="#cb100-22" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Category category<span class="op">,</span></span>
<span id="cb100-23"><a href="#cb100-23" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">List</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> entries</span>
<span id="cb100-24"><a href="#cb100-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">implements</span> Log <span class="op">{</span></span>
<span id="cb100-25"><a href="#cb100-25" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="bu">Event</span><span class="op">(</span></span>
<span id="cb100-26"><a href="#cb100-26" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb100-27"><a href="#cb100-27" aria-hidden="true" tabindex="-1"></a>                Category category</span>
<span id="cb100-28"><a href="#cb100-28" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="op">{</span></span>
<span id="cb100-29"><a href="#cb100-29" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">(</span></span>
<span id="cb100-30"><a href="#cb100-30" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">Context</span><span class="op">.</span><span class="fu">current</span><span class="op">(),</span></span>
<span id="cb100-31"><a href="#cb100-31" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">Thread</span><span class="op">.</span><span class="fu">currentThread</span><span class="op">(),</span> </span>
<span id="cb100-32"><a href="#cb100-32" aria-hidden="true" tabindex="-1"></a>                    Flake<span class="op">.</span><span class="fu">create</span><span class="op">(),</span> </span>
<span id="cb100-33"><a href="#cb100-33" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">new</span> Occurrence<span class="op">.</span><span class="fu">PointInTime</span><span class="op">(</span>Instant<span class="op">.</span><span class="fu">now</span><span class="op">()),</span> </span>
<span id="cb100-34"><a href="#cb100-34" aria-hidden="true" tabindex="-1"></a>                    level<span class="op">,</span> </span>
<span id="cb100-35"><a href="#cb100-35" aria-hidden="true" tabindex="-1"></a>                    category</span>
<span id="cb100-36"><a href="#cb100-36" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb100-37"><a href="#cb100-37" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb100-38"><a href="#cb100-38" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb100-39"><a href="#cb100-39" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb100-40"><a href="#cb100-40" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">Span</span><span class="op">(</span></span>
<span id="cb100-41"><a href="#cb100-41" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Context</span> context<span class="op">,</span></span>
<span id="cb100-42"><a href="#cb100-42" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Thread</span> thread<span class="op">,</span></span>
<span id="cb100-43"><a href="#cb100-43" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Flake flake<span class="op">,</span></span>
<span id="cb100-44"><a href="#cb100-44" aria-hidden="true" tabindex="-1"></a>            Outcome outcome<span class="op">,</span></span>
<span id="cb100-45"><a href="#cb100-45" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Occurrence<span class="op">.</span><span class="fu">SpanOfTime</span> occurrence<span class="op">,</span></span>
<span id="cb100-46"><a href="#cb100-46" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb100-47"><a href="#cb100-47" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> Category category<span class="op">,</span></span>
<span id="cb100-48"><a href="#cb100-48" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span> <span class="bu">List</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> entries</span>
<span id="cb100-49"><a href="#cb100-49" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">implements</span> Log <span class="op">{</span></span>
<span id="cb100-50"><a href="#cb100-50" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="bu">Event</span><span class="op">(</span></span>
<span id="cb100-51"><a href="#cb100-51" aria-hidden="true" tabindex="-1"></a>                Outcome outcome<span class="op">,</span></span>
<span id="cb100-52"><a href="#cb100-52" aria-hidden="true" tabindex="-1"></a>                Occurrence<span class="op">.</span><span class="fu">SpanOfTime</span> occurrence<span class="op">,</span></span>
<span id="cb100-53"><a href="#cb100-53" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Level</span> level<span class="op">,</span></span>
<span id="cb100-54"><a href="#cb100-54" aria-hidden="true" tabindex="-1"></a>                Category category<span class="op">,</span></span>
<span id="cb100-55"><a href="#cb100-55" aria-hidden="true" tabindex="-1"></a>                <span class="bu">List</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> entries</span>
<span id="cb100-56"><a href="#cb100-56" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span> <span class="op">{</span></span>
<span id="cb100-57"><a href="#cb100-57" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">(</span></span>
<span id="cb100-58"><a href="#cb100-58" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">Context</span><span class="op">.</span><span class="fu">current</span><span class="op">(),</span></span>
<span id="cb100-59"><a href="#cb100-59" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">Thread</span><span class="op">.</span><span class="fu">currentThread</span><span class="op">(),</span></span>
<span id="cb100-60"><a href="#cb100-60" aria-hidden="true" tabindex="-1"></a>                    Flake<span class="op">.</span><span class="fu">create</span><span class="op">(),</span></span>
<span id="cb100-61"><a href="#cb100-61" aria-hidden="true" tabindex="-1"></a>                    outcome</span>
<span id="cb100-62"><a href="#cb100-62" aria-hidden="true" tabindex="-1"></a>                    occurrence<span class="op">,</span></span>
<span id="cb100-63"><a href="#cb100-63" aria-hidden="true" tabindex="-1"></a>                    level<span class="op">,</span></span>
<span id="cb100-64"><a href="#cb100-64" aria-hidden="true" tabindex="-1"></a>                    category</span>
<span id="cb100-65"><a href="#cb100-65" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb100-66"><a href="#cb100-66" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb100-67"><a href="#cb100-67" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb100-68"><a href="#cb100-68" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb100-69"><a href="#cb100-69" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb100-70"><a href="#cb100-70" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>So to add some log entries to every log made in a scope, we just need to set and unset the thread local.</p>
<div class="sourceCode" id="cb101"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb101-1"><a href="#cb101-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Log <span class="op">{</span></span>
<span id="cb101-2"><a href="#cb101-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb101-3"><a href="#cb101-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb101-4"><a href="#cb101-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="op">&lt;</span>T<span class="op">&gt;</span> T <span class="fu">withContext</span><span class="op">(</span><span class="bu">List</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> entries<span class="op">,</span> Supplier<span class="op">&lt;</span>T<span class="op">&gt;</span> code<span class="op">)</span> <span class="op">{</span></span>
<span id="cb101-5"><a href="#cb101-5" aria-hidden="true" tabindex="-1"></a>        var localContext <span class="op">=</span> LOCAL_CONTEXT<span class="op">.</span><span class="fu">get</span><span class="op">();</span></span>
<span id="cb101-6"><a href="#cb101-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb101-7"><a href="#cb101-7" aria-hidden="true" tabindex="-1"></a>            LOCAL_CONTEXT<span class="op">.</span><span class="fu">set</span><span class="op">(</span><span class="kw">new</span> <span class="bu">Context</span><span class="op">.</span><span class="fu">Child</span><span class="op">.</span><span class="fu">Plain</span><span class="op">(</span></span>
<span id="cb101-8"><a href="#cb101-8" aria-hidden="true" tabindex="-1"></a>                    entries<span class="op">,</span></span>
<span id="cb101-9"><a href="#cb101-9" aria-hidden="true" tabindex="-1"></a>                    localContext <span class="op">==</span> <span class="kw">null</span> </span>
<span id="cb101-10"><a href="#cb101-10" aria-hidden="true" tabindex="-1"></a>                            <span class="op">?</span> GLOBAL_CONTEXT<span class="op">.</span><span class="fu">get</span><span class="op">()</span> </span>
<span id="cb101-11"><a href="#cb101-11" aria-hidden="true" tabindex="-1"></a>                            <span class="op">:</span> localContext</span>
<span id="cb101-12"><a href="#cb101-12" aria-hidden="true" tabindex="-1"></a>            <span class="op">));</span></span>
<span id="cb101-13"><a href="#cb101-13" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> code<span class="op">.</span><span class="fu">get</span><span class="op">();</span></span>
<span id="cb101-14"><a href="#cb101-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">finally</span> <span class="op">{</span></span>
<span id="cb101-15"><a href="#cb101-15" aria-hidden="true" tabindex="-1"></a>            LOCAL_CONTEXT<span class="op">.</span><span class="fu">set</span><span class="op">(</span>localContext<span class="op">);</span></span>
<span id="cb101-16"><a href="#cb101-16" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb101-17"><a href="#cb101-17" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb101-18"><a href="#cb101-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb101-19"><a href="#cb101-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb101-20"><a href="#cb101-20" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">void</span> <span class="fu">withContext</span><span class="op">(</span><span class="bu">List</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> entries<span class="op">,</span> <span class="bu">Runnable</span> code<span class="op">)</span> <span class="op">{</span></span>
<span id="cb101-21"><a href="#cb101-21" aria-hidden="true" tabindex="-1"></a>        <span class="fu">withContext</span><span class="op">(</span></span>
<span id="cb101-22"><a href="#cb101-22" aria-hidden="true" tabindex="-1"></a>                entries<span class="op">,</span></span>
<span id="cb101-23"><a href="#cb101-23" aria-hidden="true" tabindex="-1"></a>                <span class="op">()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb101-24"><a href="#cb101-24" aria-hidden="true" tabindex="-1"></a>                    code<span class="op">.</span><span class="fu">run</span><span class="op">();</span></span>
<span id="cb101-25"><a href="#cb101-25" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb101-26"><a href="#cb101-26" aria-hidden="true" tabindex="-1"></a>                <span class="op">});</span></span>
<span id="cb101-27"><a href="#cb101-27" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb101-28"><a href="#cb101-28" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb101-29"><a href="#cb101-29" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb101-30"><a href="#cb101-30" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb102"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb102-1"><a href="#cb102-1" aria-hidden="true" tabindex="-1"></a>Log<span class="op">.</span><span class="fu">withContext</span><span class="op">(</span></span>
<span id="cb102-2"><a href="#cb102-2" aria-hidden="true" tabindex="-1"></a>   <span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>Log<span class="op">.</span><span class="fu">Entry</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;request-id&quot;</span><span class="op">,</span> <span class="st">&quot;abc&quot;</span><span class="op">)),</span></span>
<span id="cb102-3"><a href="#cb102-3" aria-hidden="true" tabindex="-1"></a>   <span class="op">()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb102-4"><a href="#cb102-4" aria-hidden="true" tabindex="-1"></a>      log<span class="op">.</span><span class="fu">info</span><span class="op">(</span><span class="st">&quot;has-request-id!&quot;</span><span class="op">);</span></span>
<span id="cb102-5"><a href="#cb102-5" aria-hidden="true" tabindex="-1"></a>   <span class="op">}</span>   </span>
<span id="cb102-6"><a href="#cb102-6" aria-hidden="true" tabindex="-1"></a><span class="op">)</span></span></code></pre></div>
<p>And the strategy is very similar for propagating spans, with the difference that log entries are not propagated just metadata.</p>
<div class="sourceCode" id="cb103"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb103-1"><a href="#cb103-1" aria-hidden="true" tabindex="-1"></a><span class="kw">interface</span> <span class="bu">Logger</span> <span class="op">{</span></span>
<span id="cb103-2"><a href="#cb103-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb103-3"><a href="#cb103-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb103-4"><a href="#cb103-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="op">&lt;</span>T<span class="op">&gt;</span> T <span class="fu">span</span><span class="op">(</span></span>
<span id="cb103-5"><a href="#cb103-5" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Level</span> level<span class="op">,</span></span>
<span id="cb103-6"><a href="#cb103-6" aria-hidden="true" tabindex="-1"></a>            Log<span class="op">.</span><span class="fu">Category</span> category<span class="op">,</span></span>
<span id="cb103-7"><a href="#cb103-7" aria-hidden="true" tabindex="-1"></a>            <span class="bu">List</span><span class="op">&lt;</span>Log<span class="op">.</span><span class="fu">Entry</span><span class="op">&gt;</span> entries<span class="op">,</span></span>
<span id="cb103-8"><a href="#cb103-8" aria-hidden="true" tabindex="-1"></a>            Supplier<span class="op">&lt;</span>T<span class="op">&gt;</span> code</span>
<span id="cb103-9"><a href="#cb103-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb103-10"><a href="#cb103-10" aria-hidden="true" tabindex="-1"></a>        Log<span class="op">.</span><span class="fu">Span</span><span class="op">.</span><span class="fu">Outcome</span> outcome <span class="op">=</span> Log<span class="op">.</span><span class="fu">Span</span><span class="op">.</span><span class="fu">Outcome</span><span class="op">.</span><span class="fu">Ok</span><span class="op">.</span><span class="fu">INSTANCE</span><span class="op">;</span></span>
<span id="cb103-11"><a href="#cb103-11" aria-hidden="true" tabindex="-1"></a>        var start <span class="op">=</span> Instant<span class="op">.</span><span class="fu">now</span><span class="op">();</span></span>
<span id="cb103-12"><a href="#cb103-12" aria-hidden="true" tabindex="-1"></a>        var localContext <span class="op">=</span> LOCAL_CONTEXT<span class="op">.</span><span class="fu">get</span><span class="op">();</span></span>
<span id="cb103-13"><a href="#cb103-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb103-14"><a href="#cb103-14" aria-hidden="true" tabindex="-1"></a>            LOCAL_CONTEXT<span class="op">.</span><span class="fu">set</span><span class="op">(</span><span class="kw">new</span> Log<span class="op">.</span><span class="fu">Context</span><span class="op">.</span><span class="fu">Child</span><span class="op">.</span><span class="fu">Span</span><span class="op">(</span></span>
<span id="cb103-15"><a href="#cb103-15" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">Thread</span><span class="op">.</span><span class="fu">currentThread</span><span class="op">(),</span></span>
<span id="cb103-16"><a href="#cb103-16" aria-hidden="true" tabindex="-1"></a>                    start<span class="op">,</span></span>
<span id="cb103-17"><a href="#cb103-17" aria-hidden="true" tabindex="-1"></a>                    Flake<span class="op">.</span><span class="fu">create</span><span class="op">(),</span></span>
<span id="cb103-18"><a href="#cb103-18" aria-hidden="true" tabindex="-1"></a>                    localContext <span class="op">==</span> <span class="kw">null</span> </span>
<span id="cb103-19"><a href="#cb103-19" aria-hidden="true" tabindex="-1"></a>                            <span class="op">?</span> GLOBAL_CONTEXT<span class="op">.</span><span class="fu">get</span><span class="op">()</span> </span>
<span id="cb103-20"><a href="#cb103-20" aria-hidden="true" tabindex="-1"></a>                            <span class="op">:</span> localContext</span>
<span id="cb103-21"><a href="#cb103-21" aria-hidden="true" tabindex="-1"></a>            <span class="op">));</span></span>
<span id="cb103-22"><a href="#cb103-22" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> code<span class="op">.</span><span class="fu">get</span><span class="op">();</span></span>
<span id="cb103-23"><a href="#cb103-23" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span><span class="bu">Throwable</span> t<span class="op">)</span> <span class="op">{</span></span>
<span id="cb103-24"><a href="#cb103-24" aria-hidden="true" tabindex="-1"></a>            outcome <span class="op">=</span> <span class="kw">new</span> Log<span class="op">.</span><span class="fu">Span</span><span class="op">.</span><span class="fu">Outcome</span><span class="op">.</span><span class="fu">Error</span><span class="op">(</span>t<span class="op">);</span></span>
<span id="cb103-25"><a href="#cb103-25" aria-hidden="true" tabindex="-1"></a>            <span class="cf">throw</span> t<span class="op">;</span></span>
<span id="cb103-26"><a href="#cb103-26" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">finally</span> <span class="op">{</span></span>
<span id="cb103-27"><a href="#cb103-27" aria-hidden="true" tabindex="-1"></a>            LOCAL_CONTEXT<span class="op">.</span><span class="fu">set</span><span class="op">(</span>localContext<span class="op">);</span></span>
<span id="cb103-28"><a href="#cb103-28" aria-hidden="true" tabindex="-1"></a>            var end <span class="op">=</span> Instant<span class="op">.</span><span class="fu">now</span><span class="op">();</span></span>
<span id="cb103-29"><a href="#cb103-29" aria-hidden="true" tabindex="-1"></a>            var duration <span class="op">=</span> <span class="bu">Duration</span><span class="op">.</span><span class="fu">between</span><span class="op">(</span>start<span class="op">,</span> end<span class="op">);</span></span>
<span id="cb103-30"><a href="#cb103-30" aria-hidden="true" tabindex="-1"></a>            var occurrence <span class="op">=</span> <span class="kw">new</span> Log<span class="op">.</span><span class="fu">Occurrence</span><span class="op">.</span><span class="fu">SpanOfTime</span><span class="op">(</span></span>
<span id="cb103-31"><a href="#cb103-31" aria-hidden="true" tabindex="-1"></a>                    start<span class="op">,</span> </span>
<span id="cb103-32"><a href="#cb103-32" aria-hidden="true" tabindex="-1"></a>                    duration</span>
<span id="cb103-33"><a href="#cb103-33" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb103-34"><a href="#cb103-34" aria-hidden="true" tabindex="-1"></a>            <span class="fu">log</span><span class="op">(</span><span class="kw">new</span> Log<span class="op">.</span><span class="fu">Span</span><span class="op">(</span></span>
<span id="cb103-35"><a href="#cb103-35" aria-hidden="true" tabindex="-1"></a>                    outcome<span class="op">,</span></span>
<span id="cb103-36"><a href="#cb103-36" aria-hidden="true" tabindex="-1"></a>                    occurrence<span class="op">,</span></span>
<span id="cb103-37"><a href="#cb103-37" aria-hidden="true" tabindex="-1"></a>                    level<span class="op">,</span></span>
<span id="cb103-38"><a href="#cb103-38" aria-hidden="true" tabindex="-1"></a>                    category<span class="op">,</span></span>
<span id="cb103-39"><a href="#cb103-39" aria-hidden="true" tabindex="-1"></a>                    entries</span>
<span id="cb103-40"><a href="#cb103-40" aria-hidden="true" tabindex="-1"></a>            <span class="op">));</span></span>
<span id="cb103-41"><a href="#cb103-41" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb103-42"><a href="#cb103-42" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb103-43"><a href="#cb103-43" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb103-44"><a href="#cb103-44" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb103-45"><a href="#cb103-45" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Now putting it all together.</p>
<div class="sourceCode" id="cb104"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb104-1"><a href="#cb104-1" aria-hidden="true" tabindex="-1"></a>Log<span class="op">.</span><span class="fu">setGlobalContext</span><span class="op">(</span><span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb104-2"><a href="#cb104-2" aria-hidden="true" tabindex="-1"></a>    Log<span class="op">.</span><span class="fu">Entry</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb104-3"><a href="#cb104-3" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;os.name&quot;</span><span class="op">,</span></span>
<span id="cb104-4"><a href="#cb104-4" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">getProperty</span><span class="op">(</span><span class="st">&quot;os.name&quot;</span><span class="op">)</span></span>
<span id="cb104-5"><a href="#cb104-5" aria-hidden="true" tabindex="-1"></a><span class="op">));</span></span>
<span id="cb104-6"><a href="#cb104-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb104-7"><a href="#cb104-7" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span>
<span id="cb104-8"><a href="#cb104-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb104-9"><a href="#cb104-9" aria-hidden="true" tabindex="-1"></a>log<span class="op">.</span><span class="fu">infoSpan</span><span class="op">(</span></span>
<span id="cb104-10"><a href="#cb104-10" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;handling-request&quot;</span><span class="op">,</span></span>
<span id="cb104-11"><a href="#cb104-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb104-12"><a href="#cb104-12" aria-hidden="true" tabindex="-1"></a>        Log<span class="op">.</span><span class="fu">withContext</span><span class="op">(</span></span>
<span id="cb104-13"><a href="#cb104-13" aria-hidden="true" tabindex="-1"></a>            <span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>Log<span class="op">.</span><span class="fu">Entry</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;request-id&quot;</span><span class="op">,</span> <span class="st">&quot;abc&quot;</span><span class="op">)),</span></span>
<span id="cb104-14"><a href="#cb104-14" aria-hidden="true" tabindex="-1"></a>            <span class="op">()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb104-15"><a href="#cb104-15" aria-hidden="true" tabindex="-1"></a>               log<span class="op">.</span><span class="fu">warn</span><span class="op">(</span></span>
<span id="cb104-16"><a href="#cb104-16" aria-hidden="true" tabindex="-1"></a>                       <span class="st">&quot;oh-no!&quot;</span><span class="op">,</span> </span>
<span id="cb104-17"><a href="#cb104-17" aria-hidden="true" tabindex="-1"></a>                       Log<span class="op">.</span><span class="fu">Entry</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;failed-for-id&quot;</span><span class="op">,</span> <span class="dv">123</span><span class="op">)</span></span>
<span id="cb104-18"><a href="#cb104-18" aria-hidden="true" tabindex="-1"></a>               <span class="op">);</span></span>
<span id="cb104-19"><a href="#cb104-19" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb104-20"><a href="#cb104-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span></span>
<span id="cb104-21"><a href="#cb104-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb104-22"><a href="#cb104-22" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span></code></pre></div>
<p>Looking past the lambdas, which are only taking so much visual budget because of the trivial-ness of the example, I am pretty happy with this API. The innermost log will have both the <code>request-id</code> and <code>os-name</code> available within its context as well as the <code>failed-for-id</code> directly in its <code>entries</code> component.</p>
<p>Crawling for all the log entries available in the entire linked list for a log is slightly non-trivial, so I think it would be beneficial for <code>Log</code> itself to implement <code>Iterable\&lt;Log&gt;</code> and do that crawling upon request.</p>
<p>A lot of the code so far has been ugly on the outside. I think this code is ugly on the inside too.</p>
<div class="sourceCode" id="cb105"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb105-1"><a href="#cb105-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Log <span class="kw">extends</span> <span class="bu">Iterable</span><span class="op">&lt;</span>Log<span class="op">.</span><span class="fu">Entry</span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb105-2"><a href="#cb105-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb105-3"><a href="#cb105-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb105-4"><a href="#cb105-4" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb105-5"><a href="#cb105-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> <span class="bu">Iterator</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> <span class="fu">iterator</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb105-6"><a href="#cb105-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="bu">Iterator</span><span class="op">&lt;&gt;()</span> <span class="op">{</span></span>
<span id="cb105-7"><a href="#cb105-7" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Iterator</span><span class="op">&lt;</span>Entry<span class="op">&gt;</span> iter <span class="op">=</span> <span class="fu">entries</span><span class="op">().</span><span class="fu">iterator</span><span class="op">();</span></span>
<span id="cb105-8"><a href="#cb105-8" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Context</span> ctx <span class="op">=</span> <span class="fu">context</span><span class="op">();</span></span>
<span id="cb105-9"><a href="#cb105-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb105-10"><a href="#cb105-10" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span></span>
<span id="cb105-11"><a href="#cb105-11" aria-hidden="true" tabindex="-1"></a>            <span class="kw">public</span> <span class="dt">boolean</span> <span class="fu">hasNext</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb105-12"><a href="#cb105-12" aria-hidden="true" tabindex="-1"></a>                <span class="cf">if</span> <span class="op">(</span>iter<span class="op">.</span><span class="fu">hasNext</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb105-13"><a href="#cb105-13" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">return</span> <span class="kw">true</span><span class="op">;</span></span>
<span id="cb105-14"><a href="#cb105-14" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb105-15"><a href="#cb105-15" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">if</span> <span class="op">(</span>ctx <span class="kw">instanceof</span> <span class="bu">Context</span><span class="op">.</span><span class="fu">Child</span><span class="op">.</span><span class="fu">Plain</span> plainCtx<span class="op">)</span> <span class="op">{</span></span>
<span id="cb105-16"><a href="#cb105-16" aria-hidden="true" tabindex="-1"></a>                        iter <span class="op">=</span> plainCtx<span class="op">.</span><span class="fu">entries</span><span class="op">().</span><span class="fu">iterator</span><span class="op">();</span></span>
<span id="cb105-17"><a href="#cb105-17" aria-hidden="true" tabindex="-1"></a>                        ctx <span class="op">=</span> plainCtx<span class="op">.</span><span class="fu">parent</span><span class="op">();</span></span>
<span id="cb105-18"><a href="#cb105-18" aria-hidden="true" tabindex="-1"></a>                        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">hasNext</span><span class="op">();</span></span>
<span id="cb105-19"><a href="#cb105-19" aria-hidden="true" tabindex="-1"></a>                    <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>ctx <span class="kw">instanceof</span> <span class="bu">Context</span><span class="op">.</span><span class="fu">Child</span><span class="op">.</span><span class="fu">Span</span> spanCtx<span class="op">)</span> <span class="op">{</span></span>
<span id="cb105-20"><a href="#cb105-20" aria-hidden="true" tabindex="-1"></a>                        ctx <span class="op">=</span> spanCtx<span class="op">.</span><span class="fu">parent</span><span class="op">();</span></span>
<span id="cb105-21"><a href="#cb105-21" aria-hidden="true" tabindex="-1"></a>                        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">hasNext</span><span class="op">();</span></span>
<span id="cb105-22"><a href="#cb105-22" aria-hidden="true" tabindex="-1"></a>                    <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>ctx <span class="kw">instanceof</span> <span class="bu">Context</span><span class="op">.</span><span class="fu">Global</span> globalCtx<span class="op">)</span> <span class="op">{</span></span>
<span id="cb105-23"><a href="#cb105-23" aria-hidden="true" tabindex="-1"></a>                        iter <span class="op">=</span> globalCtx<span class="op">.</span><span class="fu">entries</span><span class="op">().</span><span class="fu">iterator</span><span class="op">();</span></span>
<span id="cb105-24"><a href="#cb105-24" aria-hidden="true" tabindex="-1"></a>                        ctx <span class="op">=</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb105-25"><a href="#cb105-25" aria-hidden="true" tabindex="-1"></a>                        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">hasNext</span><span class="op">();</span></span>
<span id="cb105-26"><a href="#cb105-26" aria-hidden="true" tabindex="-1"></a>                    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb105-27"><a href="#cb105-27" aria-hidden="true" tabindex="-1"></a>                        <span class="cf">return</span> <span class="kw">false</span><span class="op">;</span></span>
<span id="cb105-28"><a href="#cb105-28" aria-hidden="true" tabindex="-1"></a>                    <span class="op">}</span></span>
<span id="cb105-29"><a href="#cb105-29" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb105-30"><a href="#cb105-30" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb105-31"><a href="#cb105-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb105-32"><a href="#cb105-32" aria-hidden="true" tabindex="-1"></a>            <span class="at">@Override</span></span>
<span id="cb105-33"><a href="#cb105-33" aria-hidden="true" tabindex="-1"></a>            <span class="kw">public</span> Entry <span class="fu">next</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb105-34"><a href="#cb105-34" aria-hidden="true" tabindex="-1"></a>                <span class="cf">if</span> <span class="op">(</span>iter<span class="op">.</span><span class="fu">hasNext</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb105-35"><a href="#cb105-35" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">return</span> iter<span class="op">.</span><span class="fu">next</span><span class="op">();</span></span>
<span id="cb105-36"><a href="#cb105-36" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb105-37"><a href="#cb105-37" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">if</span> <span class="op">(</span>ctx <span class="kw">instanceof</span> <span class="bu">Context</span><span class="op">.</span><span class="fu">Child</span><span class="op">.</span><span class="fu">Plain</span> plainCtx<span class="op">)</span> <span class="op">{</span></span>
<span id="cb105-38"><a href="#cb105-38" aria-hidden="true" tabindex="-1"></a>                        iter <span class="op">=</span> plainCtx<span class="op">.</span><span class="fu">entries</span><span class="op">().</span><span class="fu">iterator</span><span class="op">();</span></span>
<span id="cb105-39"><a href="#cb105-39" aria-hidden="true" tabindex="-1"></a>                        ctx <span class="op">=</span> plainCtx<span class="op">.</span><span class="fu">parent</span><span class="op">();</span></span>
<span id="cb105-40"><a href="#cb105-40" aria-hidden="true" tabindex="-1"></a>                        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">next</span><span class="op">();</span></span>
<span id="cb105-41"><a href="#cb105-41" aria-hidden="true" tabindex="-1"></a>                    <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>ctx <span class="kw">instanceof</span> <span class="bu">Context</span><span class="op">.</span><span class="fu">Child</span><span class="op">.</span><span class="fu">Span</span> spanCtx<span class="op">)</span> <span class="op">{</span></span>
<span id="cb105-42"><a href="#cb105-42" aria-hidden="true" tabindex="-1"></a>                        ctx <span class="op">=</span> spanCtx<span class="op">.</span><span class="fu">parent</span><span class="op">();</span></span>
<span id="cb105-43"><a href="#cb105-43" aria-hidden="true" tabindex="-1"></a>                        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">next</span><span class="op">();</span></span>
<span id="cb105-44"><a href="#cb105-44" aria-hidden="true" tabindex="-1"></a>                    <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>ctx <span class="kw">instanceof</span> <span class="bu">Context</span><span class="op">.</span><span class="fu">Global</span> globalCtx<span class="op">)</span> <span class="op">{</span></span>
<span id="cb105-45"><a href="#cb105-45" aria-hidden="true" tabindex="-1"></a>                        iter <span class="op">=</span> globalCtx<span class="op">.</span><span class="fu">entries</span><span class="op">().</span><span class="fu">iterator</span><span class="op">();</span></span>
<span id="cb105-46"><a href="#cb105-46" aria-hidden="true" tabindex="-1"></a>                        ctx <span class="op">=</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb105-47"><a href="#cb105-47" aria-hidden="true" tabindex="-1"></a>                        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">next</span><span class="op">();</span></span>
<span id="cb105-48"><a href="#cb105-48" aria-hidden="true" tabindex="-1"></a>                    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb105-49"><a href="#cb105-49" aria-hidden="true" tabindex="-1"></a>                        <span class="cf">throw</span> <span class="kw">new</span> <span class="bu">NoSuchElementException</span><span class="op">();</span></span>
<span id="cb105-50"><a href="#cb105-50" aria-hidden="true" tabindex="-1"></a>                    <span class="op">}</span></span>
<span id="cb105-51"><a href="#cb105-51" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb105-52"><a href="#cb105-52" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb105-53"><a href="#cb105-53" aria-hidden="true" tabindex="-1"></a>        <span class="op">};</span></span>
<span id="cb105-54"><a href="#cb105-54" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb105-55"><a href="#cb105-55" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="loggerfactory">LoggerFactory</h3>
<p>Now to have parity with <code>SLF4J</code> we should be able to delegate logging to a specific implementation on the class/module-path.</p>
<p>To do this, we first need to make an interface for creating loggers.</p>
<div class="sourceCode" id="cb106"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb106-1"><a href="#cb106-1" aria-hidden="true" tabindex="-1"></a><span class="kw">interface</span> LoggerFactory <span class="op">{</span></span>
<span id="cb106-2"><a href="#cb106-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Logger</span> <span class="fu">createLogger</span><span class="op">();</span></span>
<span id="cb106-3"><a href="#cb106-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And then we need to declare in our <code>module-info.java</code> that we are interested in consuming external implementors of this interface - just in case people ever decide to put this on the module-path.</p>
<div class="sourceCode" id="cb107"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb107-1"><a href="#cb107-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">log</span><span class="op">.</span><span class="im">alpha</span><span class="op">.</span><span class="im">LoggerFactory</span><span class="op">;</span></span>
<span id="cb107-2"><a href="#cb107-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb107-3"><a href="#cb107-3" aria-hidden="true" tabindex="-1"></a>module dev<span class="op">.</span><span class="fu">mccue</span><span class="op">.</span><span class="fu">log</span><span class="op">.</span><span class="fu">alpha</span> <span class="op">{</span></span>
<span id="cb107-4"><a href="#cb107-4" aria-hidden="true" tabindex="-1"></a>    exports dev<span class="op">.</span><span class="fu">mccue</span><span class="op">.</span><span class="fu">log</span><span class="op">.</span><span class="fu">alpha</span><span class="op">;</span></span>
<span id="cb107-5"><a href="#cb107-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb107-6"><a href="#cb107-6" aria-hidden="true" tabindex="-1"></a>    uses LoggerFactory<span class="op">;</span></span>
<span id="cb107-7"><a href="#cb107-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Then we can build a factory function which scans through available implementations and picks one.</p>
<div class="sourceCode" id="cb108"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb108-1"><a href="#cb108-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">interface</span> LoggerFactory <span class="op">{</span></span>
<span id="cb108-2"><a href="#cb108-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> LoggerFactory <span class="fu">create</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb108-3"><a href="#cb108-3" aria-hidden="true" tabindex="-1"></a>        var loggerFactories <span class="op">=</span> <span class="bu">ServiceLoader</span><span class="op">.</span><span class="fu">load</span><span class="op">(</span>LoggerFactory<span class="op">.</span><span class="fu">class</span><span class="op">).</span><span class="fu">iterator</span><span class="op">();</span></span>
<span id="cb108-4"><a href="#cb108-4" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(!</span>loggerFactories<span class="op">.</span><span class="fu">hasNext</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb108-5"><a href="#cb108-5" aria-hidden="true" tabindex="-1"></a>            <span class="bu">System</span><span class="op">.</span><span class="fu">err</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span></span>
<span id="cb108-6"><a href="#cb108-6" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;No logger factory supplied. Falling back to no-op logger&quot;</span></span>
<span id="cb108-7"><a href="#cb108-7" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb108-8"><a href="#cb108-8" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="op">()</span> <span class="op">-&gt;</span> <span class="op">(</span>__<span class="op">)</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb108-9"><a href="#cb108-9" aria-hidden="true" tabindex="-1"></a>            <span class="op">};</span></span>
<span id="cb108-10"><a href="#cb108-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb108-11"><a href="#cb108-11" aria-hidden="true" tabindex="-1"></a>            var service <span class="op">=</span> loggerFactories<span class="op">.</span><span class="fu">next</span><span class="op">();</span></span>
<span id="cb108-12"><a href="#cb108-12" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>loggerFactories<span class="op">.</span><span class="fu">hasNext</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb108-13"><a href="#cb108-13" aria-hidden="true" tabindex="-1"></a>                var services <span class="op">=</span> <span class="kw">new</span> <span class="bu">ArrayList</span><span class="op">&lt;</span>LoggerFactory<span class="op">&gt;();</span></span>
<span id="cb108-14"><a href="#cb108-14" aria-hidden="true" tabindex="-1"></a>                services<span class="op">.</span><span class="fu">add</span><span class="op">(</span>service<span class="op">);</span></span>
<span id="cb108-15"><a href="#cb108-15" aria-hidden="true" tabindex="-1"></a>                <span class="cf">while</span> <span class="op">(</span>loggerFactories<span class="op">.</span><span class="fu">hasNext</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb108-16"><a href="#cb108-16" aria-hidden="true" tabindex="-1"></a>                    services<span class="op">.</span><span class="fu">add</span><span class="op">(</span>loggerFactories<span class="op">.</span><span class="fu">next</span><span class="op">());</span></span>
<span id="cb108-17"><a href="#cb108-17" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb108-18"><a href="#cb108-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb108-19"><a href="#cb108-19" aria-hidden="true" tabindex="-1"></a>                <span class="bu">System</span><span class="op">.</span><span class="fu">err</span><span class="op">.</span><span class="fu">printf</span><span class="op">(</span></span>
<span id="cb108-20"><a href="#cb108-20" aria-hidden="true" tabindex="-1"></a>                        <span class="st">&quot;Multiple logger factories supplied: </span><span class="sc">%s</span><span class="st">. Picking one at random.</span><span class="sc">%n</span><span class="st">&quot;</span><span class="op">,</span></span>
<span id="cb108-21"><a href="#cb108-21" aria-hidden="true" tabindex="-1"></a>                        services</span>
<span id="cb108-22"><a href="#cb108-22" aria-hidden="true" tabindex="-1"></a>                <span class="op">);</span></span>
<span id="cb108-23"><a href="#cb108-23" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> services<span class="op">.</span><span class="fu">get</span><span class="op">(</span>ThreadLocalRandom<span class="op">.</span><span class="fu">current</span><span class="op">().</span><span class="fu">nextInt</span><span class="op">(</span><span class="dv">0</span><span class="op">,</span> services<span class="op">.</span><span class="fu">size</span><span class="op">()));</span></span>
<span id="cb108-24"><a href="#cb108-24" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb108-25"><a href="#cb108-25" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> service<span class="op">;</span></span>
<span id="cb108-26"><a href="#cb108-26" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb108-27"><a href="#cb108-27" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb108-28"><a href="#cb108-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb108-29"><a href="#cb108-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb108-30"><a href="#cb108-30" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Logger</span> <span class="fu">createLogger</span><span class="op">();</span></span>
<span id="cb108-31"><a href="#cb108-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The reason for the indirection - using a <code>LoggerFactory</code> instead of a <code>Logger</code> - is to allow for implementations to do some one-time set up logic and potentially set up logic per created logger.</p>
<p>In the context of Java, the namespace of a log would often be the name of the class that the log is in. This is why SLF4J has <code>LoggerFactory.getLogger(Class&lt;?&gt;)</code> as <a href="https://www.slf4j.org/manual.html">the obvious way to get a logger</a>. Matching that convention is easy enough.</p>
<div class="sourceCode" id="cb109"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb109-1"><a href="#cb109-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">interface</span> LoggerFactory <span class="op">{</span></span>
<span id="cb109-2"><a href="#cb109-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> LoggerFactory <span class="fu">create</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb109-3"><a href="#cb109-3" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb109-4"><a href="#cb109-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb109-5"><a href="#cb109-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb109-6"><a href="#cb109-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="bu">Logger</span> <span class="fu">getLogger</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb109-7"><a href="#cb109-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fu">create</span><span class="op">().</span><span class="fu">createLogger</span><span class="op">();</span></span>
<span id="cb109-8"><a href="#cb109-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb109-9"><a href="#cb109-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb109-10"><a href="#cb109-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="bu">Logger</span><span class="op">.</span><span class="fu">Namespaced</span> <span class="fu">getLogger</span><span class="op">(</span><span class="bu">String</span> namespace<span class="op">)</span> <span class="op">{</span></span>
<span id="cb109-11"><a href="#cb109-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fu">getLogger</span><span class="op">().</span><span class="fu">namespaced</span><span class="op">(</span>namespace<span class="op">);</span></span>
<span id="cb109-12"><a href="#cb109-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb109-13"><a href="#cb109-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb109-14"><a href="#cb109-14" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="bu">Logger</span><span class="op">.</span><span class="fu">Namespaced</span> <span class="fu">getLogger</span><span class="op">(</span><span class="bu">Class</span><span class="op">&lt;?&gt;</span> klass<span class="op">)</span> <span class="op">{</span></span>
<span id="cb109-15"><a href="#cb109-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fu">getLogger</span><span class="op">().</span><span class="fu">namespaced</span><span class="op">(</span>klass<span class="op">.</span><span class="fu">getCanonicalName</span><span class="op">());</span></span>
<span id="cb109-16"><a href="#cb109-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb109-17"><a href="#cb109-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb109-18"><a href="#cb109-18" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Logger</span> <span class="fu">createLogger</span><span class="op">();</span></span>
<span id="cb109-19"><a href="#cb109-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>So now constructing a logger will look a lot like SLF4J</p>
<div class="sourceCode" id="cb110"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb110-1"><a href="#cb110-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb110-2"><a href="#cb110-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">static</span> <span class="dt">final</span> <span class="bu">Logger</span><span class="op">.</span><span class="fu">Namespaced</span> log <span class="op">=</span> </span>
<span id="cb110-3"><a href="#cb110-3" aria-hidden="true" tabindex="-1"></a>            LoggerFactory<span class="op">.</span><span class="fu">getLogger</span><span class="op">(</span>Main<span class="op">.</span><span class="fu">class</span><span class="op">);</span></span>
<span id="cb110-4"><a href="#cb110-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb110-5"><a href="#cb110-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb110-6"><a href="#cb110-6" aria-hidden="true" tabindex="-1"></a>        log<span class="op">.</span><span class="fu">info</span><span class="op">(</span></span>
<span id="cb110-7"><a href="#cb110-7" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;item-delivered&quot;</span><span class="op">,</span> </span>
<span id="cb110-8"><a href="#cb110-8" aria-hidden="true" tabindex="-1"></a>                Log<span class="op">.</span><span class="fu">Entry</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;cost&quot;</span><span class="op">,</span> <span class="st">&quot;everything&quot;</span><span class="op">)</span></span>
<span id="cb110-9"><a href="#cb110-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb110-10"><a href="#cb110-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb110-11"><a href="#cb110-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="generation">Generation</h3>
<p>There will probably be an itch for some to generate the <code>getLogger</code> call <a href="https://projectlombok.org/features/log">like what lombok does for other loggers</a>.</p>
<p>I can't add to lombok, I have a life, but I can <a href="https://mccue.dev/pages/1-23-22-code-generation">generate the code with an annotation processor</a>.</p>
<div class="sourceCode" id="cb111"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb111-1"><a href="#cb111-1" aria-hidden="true" tabindex="-1"></a><span class="at">@DeriveLogger</span></span>
<span id="cb111-2"><a href="#cb111-2" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> Main <span class="kw">implements</span> MainLog <span class="op">{</span></span>
<span id="cb111-3"><a href="#cb111-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb111-4"><a href="#cb111-4" aria-hidden="true" tabindex="-1"></a>        log<span class="op">.</span><span class="fu">info</span><span class="op">(</span></span>
<span id="cb111-5"><a href="#cb111-5" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;item-delivered&quot;</span><span class="op">,</span> </span>
<span id="cb111-6"><a href="#cb111-6" aria-hidden="true" tabindex="-1"></a>                Log<span class="op">.</span><span class="fu">Entry</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;cost&quot;</span><span class="op">,</span> <span class="st">&quot;everything&quot;</span><span class="op">)</span></span>
<span id="cb111-7"><a href="#cb111-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb111-8"><a href="#cb111-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb111-9"><a href="#cb111-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb112"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb112-1"><a href="#cb112-1" aria-hidden="true" tabindex="-1"></a><span class="co">// ~= to what is generated.</span></span>
<span id="cb112-2"><a href="#cb112-2" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> MainLog permits Main <span class="op">{</span></span>
<span id="cb112-3"><a href="#cb112-3" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Logger</span><span class="op">.</span><span class="fu">Namespaced</span> log <span class="op">=</span></span>
<span id="cb112-4"><a href="#cb112-4" aria-hidden="true" tabindex="-1"></a>            LoggerFactory<span class="op">.</span><span class="fu">getLogger</span><span class="op">(</span>Main<span class="op">.</span><span class="fu">class</span><span class="op">);</span></span>
<span id="cb112-5"><a href="#cb112-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="what-was-the-point-of-all-this">What was the point of all this?</h2>
<p>As <a href="https://www.reddit.com/r/programming/comments/xnt17g/comment/ipvb6md/?utm_source=share&amp;utm_medium=web2x&amp;context=3">someone</a> correctly pointed out to me, I never really clarified why any of this is "better".</p>
<p>The gist of it is that this API allows and enforces <a href="https://docs.newrelic.com/docs/more-integrations/open-source-telemetry-integrations/opentelemetry/best-practices/opentelemetry-best-practices-logs/">structured logging</a>. That is, because there is a data-ified representation of events that happen within your system you can trivially transform them into structured formats such as JSON.</p>
<p>When your logs are all JSON you can use tools like <a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/query_with_cloudwatch-metrics-insights.html">Cloudwatch metric insights</a> to directly search over your data.</p>
<div class="sourceCode" id="cb113"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb113-1"><a href="#cb113-1" aria-hidden="true" tabindex="-1"></a>fields @timestamp, @message</span>
<span id="cb113-2"><a href="#cb113-2" aria-hidden="true" tabindex="-1"></a>| <span class="kw">sort</span> @timestamp <span class="kw">desc</span></span>
<span id="cb113-3"><a href="#cb113-3" aria-hidden="true" tabindex="-1"></a>| <span class="kw">filter</span> uri <span class="op">=</span> <span class="st">&#39;/something&#39;</span></span>
<span id="cb113-4"><a href="#cb113-4" aria-hidden="true" tabindex="-1"></a>| <span class="kw">limit</span> <span class="dv">20</span></span></code></pre></div>
<p>The exact methodology for this will vary from service to service, but the overarching theme is that structured data is searchable. Text data is "grep-able".</p>
<p>Logically when you log something in a classical framework you take a representation in memory and turn it into some "English." Then when you inspect those logs you need to undo that transformation to English to do searching. Because its 2022 there is no chance you could search those logs by hand with any reasonable scale, so you have to fall back to taking the part of your log message that is a constant and searching for that.</p>
<p>So with structured logging, you can skip the english and ship data directly to your observability platforms. This is just a potential API for structured logging or, more accurately, what <code>tracing</code> calls "in process tracing"</p>
<p>Let me know if this explanation doesn't track in the comments.</p>
<h2 id="what-now">What Now?</h2>
<p>Well, I am pretty confident that the API is good enough to start experimenting with. You can find the code for that <a href="https://github.com/bowbahdoe/log.alpha">here</a>.</p>
<p>The annotation processor is also simple enough that I think it can be used right now. Code for that is <a href="https://github.com/bowbahdoe/log.alpha.generate">here</a>.</p>
<p>Both of those finished-ish components can be fetched from jitpack.</p>
<div class="sourceCode" id="cb114"><pre class="sourceCode xml"><code class="sourceCode xml"><span id="cb114-1"><a href="#cb114-1" aria-hidden="true" tabindex="-1"></a>&lt;<span class="ot">repositories</span><span class="er">&gt;</span></span>
<span id="cb114-2"><a href="#cb114-2" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;repository&gt;</span></span>
<span id="cb114-3"><a href="#cb114-3" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;id&gt;jitpack.io&lt;/id&gt;</span></span>
<span id="cb114-4"><a href="#cb114-4" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;url&gt;https://jitpack.io&lt;/url&gt;</span></span>
<span id="cb114-5"><a href="#cb114-5" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;/repository&gt;</span></span>
<span id="cb114-6"><a href="#cb114-6" aria-hidden="true" tabindex="-1"></a><span class="er">&lt;/repositories&gt;</span></span>
<span id="cb114-7"><a href="#cb114-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb114-8"><a href="#cb114-8" aria-hidden="true" tabindex="-1"></a><span class="er">&lt;dependencies&gt;</span></span>
<span id="cb114-9"><a href="#cb114-9" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;dependency&gt;</span></span>
<span id="cb114-10"><a href="#cb114-10" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;groupId&gt;dev.mccue&lt;/groupId&gt;</span></span>
<span id="cb114-11"><a href="#cb114-11" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;artifactId&gt;log.alpha&lt;/artifactId&gt;</span></span>
<span id="cb114-12"><a href="#cb114-12" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;version&gt;main-SNAPSHOT&lt;/version&gt;</span></span>
<span id="cb114-13"><a href="#cb114-13" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;/dependency&gt;</span></span>
<span id="cb114-14"><a href="#cb114-14" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;dependency&gt;</span></span>
<span id="cb114-15"><a href="#cb114-15" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;groupId&gt;dev.mccue&lt;/groupId&gt;</span></span>
<span id="cb114-16"><a href="#cb114-16" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;artifactId&gt;log.alpha.generate&lt;/artifactId&gt;</span></span>
<span id="cb114-17"><a href="#cb114-17" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;version&gt;main-SNAPSHOT&lt;/version&gt;</span></span>
<span id="cb114-18"><a href="#cb114-18" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;/dependency&gt;</span></span>
<span id="cb114-19"><a href="#cb114-19" aria-hidden="true" tabindex="-1"></a><span class="er">&lt;/dependencies&gt;</span></span></code></pre></div>
<p>Everything else - like my rough draft JSON logger, publisher system implementation, etc - currently live in these repos.</p>
<ul>
<li><a href="https://github.com/bowbahdoe/log.alpha.jackson">log.alpha.jackson</a></li>
<li><a href="https://github.com/bowbahdoe/log.alpha.simplejsonlogger">log.alpha.simplejsonlogger</a></li>
<li><a href="https://github.com/bowbahdoe/log.alpha.publisher">log.alpha.publisher</a></li>
</ul>
<p>Contributions very welcome. Feel free to reach out to me directly on discord or similar.</p>
<h3 id="next-steps">Next Steps</h3>
<ul>
<li>Publisher system implementation</li>
</ul>
<p>A lot of design decisions I made were in support of a hypothetical system where <code>µ/log</code>'s publisher scheme was translated. I wrote this up before finishing that prototype because I saw it would be a lot of work, and I didn't want to take the dive if there was no actual interest.</p>
<ul>
<li>SLF4J Bridge</li>
</ul>
<p>I have a sketch of what one could look like that turns <code>SLF4J</code> logs into records with <code>slf4j/message</code>, <code>slf4j/arguments</code>, and <code>slf4j/mdc</code>. This technically works in terms of information conveyance but isn't very pretty. I bet someone knows how to do better.</p>
<ul>
<li>Console publisher</li>
</ul>
<p><code>tracing</code> proves that you can have structured logging and still pretty, developer friendly console logs. Everything I make is a Shrek so I probably need help to pull that off.</p>
<ul>
<li>Tests</li>
</ul>
<p>I didn't test any of this. If you can look me in the eye and say you would have written unit tests for all the log entry <code>of</code> functions I commend you. Some stuff might need to change to allow for unit testing applications which care about asserting that logs happen in the form they expect, but I haven't gone down that rabbit hole yet.</p>
<ul>
<li>Benchmarks</li>
</ul>
<p>I went at this maybe a bit too much by feel. I have no clue about the performance of this API. Is getting the current thread every time an issue? Should I have added predicates to check if log levels are enabled? Make those hundreds of logger overloads? No clue. I <em>should</em> break out JMH or do some profiling.</p>
<ul>
<li>Better Docs</li>
</ul>
<p>If I said I didn't have the opportunity to write better docs that would be a lie. I spent that time watching <a href="https://www.youtube.com/watch?v=FC7a2uE-9_o">Letterkenny</a>. This whole thing probably counts as an explainer, but for there to be any chance of anyone using this the <a href="https://diataxis.fr/">rest of Diátaxis</a> could use some attention. In my head this would take the form of fleshed out reference Javadocs, a tutorial or two, and some how-to guides on managing a migration from SLF4J.</p>
<ul>
<li>Real world usage</li>
</ul>
<p>I need brave souls - whom I would love with all my heart, mind, and body - to try this API out in some real world applications. That is probably the only way to actually validate or invalidate any choices.</p>
<hr />
<p>If nothing else, I hope this got some of you into the same nightmare head-space I'm trapped in. Leave unconstructive criticism in the comments below.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Turn any Java program into a self-contained EXE</title><link>https://mccue.dev/pages/7-28-22-make-an-exe</link><description></description><pubDate>Thu, 28 Jul 0022 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Turn any Java program into a self-contained EXE</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Turn any Java program into a self-contained EXE</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
Double-click to run is one of the easiest ways to open a program. 

<p>If the person you are sharing code with already has the right version of Java installed, they can double-click on a jar file to run it. You wrote it once, they can run it there.</p>
<p>If they don't have Java installed, then there are ways to create a runnable installer like <a href="https://docs.oracle.com/en/java/javase/18/docs/specs/man/jpackage.html">jpackage</a>, but now they have to click through an installer to be able to run your code.</p>
<p>You can use <a href="https://www.graalvm.org/22.1/reference-manual/native-image/">Native Image</a> to turn your code into an exe which won't require them to have anything installed, but now you have to abide by the <a href="https://docs.oracle.com/en/learn/understanding-reflection-graalvm-native-image/index.html#step-2-the-closed-world-assumption">closed world assumption</a> and that's not always easy or possible.</p>
<p>So this post is going to focus on a fairly oonga boonga approach that will work for any app, regardless of what dependencies you include or JVM features you make use of.</p>
<p>The code along with an example GitHub workflow can be found in <a href="https://github.com/bowbahdoe/java-exe-example">this repo</a> and final executables can be found <a href="https://github.com/bowbahdoe/java-exe-example/releases/tag/v0.0.8">here</a>.</p>
<h2 id="prerequisites">Prerequisites</h2>
<h3 id="java-9">Java 9+</h3>
<div class="sourceCode" id="cb1"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>java --version</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>jlink --version</span></code></pre></div>
<h3 id="maven">Maven</h3>
<div class="sourceCode" id="cb2"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>mvn --version</span></code></pre></div>
<h3 id="nodejs">NodeJS</h3>
<div class="sourceCode" id="cb3"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>npx --version</span></code></pre></div>
<h2 id="step-1-compile-and-package-your-code-into-a-jar">Step 1. Compile and Package your code into a jar.</h2>
<p>This toy program will create a basic window that has some text that you can toggle between being capitalized.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span><span class="im"> example</span><span class="op">;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">apache</span><span class="op">.</span><span class="im">commons</span><span class="op">.</span><span class="im">text</span><span class="op">.</span><span class="im">WordUtils</span><span class="op">;</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">javax</span><span class="op">.</span><span class="im">swing</span><span class="op">.*;</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">awt</span><span class="op">.*;</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>        var label <span class="op">=</span> <span class="kw">new</span> <span class="bu">JLabel</span><span class="op">(</span><span class="st">&quot;Hello, World!&quot;</span><span class="op">);</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>        label<span class="op">.</span><span class="fu">setFont</span><span class="op">(</span><span class="kw">new</span> <span class="bu">Font</span><span class="op">(</span><span class="st">&quot;Serif&quot;</span><span class="op">,</span> <span class="bu">Font</span><span class="op">.</span><span class="fu">PLAIN</span><span class="op">,</span> <span class="dv">72</span><span class="op">));</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>        var uppercaseButton <span class="op">=</span> <span class="kw">new</span> <span class="bu">JButton</span><span class="op">(</span><span class="st">&quot;Uppercase&quot;</span><span class="op">);</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>        uppercaseButton<span class="op">.</span><span class="fu">addActionListener</span><span class="op">(</span>e <span class="op">-&gt;</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>            label<span class="op">.</span><span class="fu">setText</span><span class="op">(</span>WordUtils<span class="op">.</span><span class="fu">capitalize</span><span class="op">(</span>label<span class="op">.</span><span class="fu">getText</span><span class="op">()))</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>        var lowercaseButton <span class="op">=</span> <span class="kw">new</span> <span class="bu">JButton</span><span class="op">(</span><span class="st">&quot;lowercase&quot;</span><span class="op">);</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a>        lowercaseButton<span class="op">.</span><span class="fu">addActionListener</span><span class="op">(</span>e <span class="op">-&gt;</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a>            label<span class="op">.</span><span class="fu">setText</span><span class="op">(</span>WordUtils<span class="op">.</span><span class="fu">uncapitalize</span><span class="op">(</span>label<span class="op">.</span><span class="fu">getText</span><span class="op">()))</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true" tabindex="-1"></a>        var panel <span class="op">=</span> <span class="kw">new</span> <span class="bu">JPanel</span><span class="op">();</span></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true" tabindex="-1"></a>        panel<span class="op">.</span><span class="fu">setLayout</span><span class="op">(</span><span class="kw">new</span> <span class="bu">BoxLayout</span><span class="op">(</span>panel<span class="op">,</span> <span class="bu">BoxLayout</span><span class="op">.</span><span class="fu">Y_AXIS</span><span class="op">));</span></span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true" tabindex="-1"></a>        panel<span class="op">.</span><span class="fu">add</span><span class="op">(</span>label<span class="op">);</span></span>
<span id="cb4-26"><a href="#cb4-26" aria-hidden="true" tabindex="-1"></a>        panel<span class="op">.</span><span class="fu">add</span><span class="op">(</span>uppercaseButton<span class="op">);</span></span>
<span id="cb4-27"><a href="#cb4-27" aria-hidden="true" tabindex="-1"></a>        panel<span class="op">.</span><span class="fu">add</span><span class="op">(</span>lowercaseButton<span class="op">);</span></span>
<span id="cb4-28"><a href="#cb4-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-29"><a href="#cb4-29" aria-hidden="true" tabindex="-1"></a>        var frame <span class="op">=</span> <span class="kw">new</span> <span class="bu">JFrame</span><span class="op">(</span><span class="st">&quot;Basic Program&quot;</span><span class="op">);</span></span>
<span id="cb4-30"><a href="#cb4-30" aria-hidden="true" tabindex="-1"></a>        frame<span class="op">.</span><span class="fu">add</span><span class="op">(</span>panel<span class="op">);</span></span>
<span id="cb4-31"><a href="#cb4-31" aria-hidden="true" tabindex="-1"></a>        frame<span class="op">.</span><span class="fu">pack</span><span class="op">();</span></span>
<span id="cb4-32"><a href="#cb4-32" aria-hidden="true" tabindex="-1"></a>        frame<span class="op">.</span><span class="fu">setVisible</span><span class="op">(</span><span class="kw">true</span><span class="op">);</span></span>
<span id="cb4-33"><a href="#cb4-33" aria-hidden="true" tabindex="-1"></a>        frame<span class="op">.</span><span class="fu">setDefaultCloseOperation</span><span class="op">(</span><span class="bu">WindowConstants</span><span class="op">.</span><span class="fu">EXIT_ON_CLOSE</span><span class="op">);</span></span>
<span id="cb4-34"><a href="#cb4-34" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-35"><a href="#cb4-35" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><img src="/pages/7-28-22-gif.gif"
alt="Program Demonstration"></img></p>
<p>The goal is to package up your code, along with its dependencies, into a jar. <a href="https://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html">Jars are just zip files with a little extra structure</a>.</p>
<p>For a <a href="https://maven.apache.org/">Maven</a> project the configuration will look like the following.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode xml"><code class="sourceCode xml"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu">&lt;?xml</span><span class="ot"> version=</span><span class="st">&quot;1.0&quot;</span><span class="ot"> encoding=</span><span class="st">&quot;UTF-8&quot;</span><span class="fu">?&gt;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>&lt;<span class="ot">project</span> <span class="er">xmlns</span><span class="ot">=</span><span class="st">&quot;http://maven.apache.org/POM/4.0.0&quot;</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="ot">         xmlns:xsi=</span><span class="st">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="ot">         xsi:schemaLocation=</span><span class="st">&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;</span>&gt;</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    &lt;<span class="ot">modelVersion</span><span class="er">&gt;4.0.0&lt;/modelVersion&gt;</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;groupId&gt;example&lt;/groupId&gt;</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;artifactId&gt;javaexe&lt;/artifactId&gt;</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;version&gt;1.0&lt;/version&gt;</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;properties&gt;</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;maven.compiler.source&gt;18&lt;/maven.compiler.source&gt;</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;maven.compiler.target&gt;18&lt;/maven.compiler.target&gt;</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;/properties&gt;</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;dependencies&gt;</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;dependency&gt;</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a>            <span class="er">&lt;groupId&gt;org.apache.commons&lt;/groupId&gt;</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a>            <span class="er">&lt;artifactId&gt;commons-text&lt;/artifactId&gt;</span></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true" tabindex="-1"></a>            <span class="er">&lt;version&gt;1.9&lt;/version&gt;</span></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;/dependency&gt;</span></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;/dependencies&gt;</span></span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;build&gt;</span></span>
<span id="cb5-26"><a href="#cb5-26" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;plugins&gt;</span></span>
<span id="cb5-27"><a href="#cb5-27" aria-hidden="true" tabindex="-1"></a>            <span class="er">&lt;plugin&gt;</span></span>
<span id="cb5-28"><a href="#cb5-28" aria-hidden="true" tabindex="-1"></a>                <span class="er">&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;</span></span>
<span id="cb5-29"><a href="#cb5-29" aria-hidden="true" tabindex="-1"></a>                <span class="er">&lt;artifactId&gt;maven-shade-plugin&lt;/artifactId&gt;</span></span>
<span id="cb5-30"><a href="#cb5-30" aria-hidden="true" tabindex="-1"></a>                <span class="er">&lt;version&gt;2.4.3&lt;/version&gt;</span></span>
<span id="cb5-31"><a href="#cb5-31" aria-hidden="true" tabindex="-1"></a>                <span class="er">&lt;executions&gt;</span></span>
<span id="cb5-32"><a href="#cb5-32" aria-hidden="true" tabindex="-1"></a>                    <span class="er">&lt;execution&gt;</span></span>
<span id="cb5-33"><a href="#cb5-33" aria-hidden="true" tabindex="-1"></a>                        <span class="er">&lt;phase&gt;package&lt;/phase&gt;</span></span>
<span id="cb5-34"><a href="#cb5-34" aria-hidden="true" tabindex="-1"></a>                        <span class="er">&lt;goals&gt;</span></span>
<span id="cb5-35"><a href="#cb5-35" aria-hidden="true" tabindex="-1"></a>                            <span class="er">&lt;goal&gt;shade&lt;/goal&gt;</span></span>
<span id="cb5-36"><a href="#cb5-36" aria-hidden="true" tabindex="-1"></a>                        <span class="er">&lt;/goals&gt;</span></span>
<span id="cb5-37"><a href="#cb5-37" aria-hidden="true" tabindex="-1"></a>                        <span class="er">&lt;configuration&gt;</span></span>
<span id="cb5-38"><a href="#cb5-38" aria-hidden="true" tabindex="-1"></a>                            <span class="er">&lt;transformers&gt;</span></span>
<span id="cb5-39"><a href="#cb5-39" aria-hidden="true" tabindex="-1"></a>                                <span class="er">&lt;transformer</span> <span class="er">implementation</span><span class="ot">=</span><span class="st">&quot;org.apache.maven.plugins.shade.resource.ManifestResourceTransformer&quot;</span>&gt;</span>
<span id="cb5-40"><a href="#cb5-40" aria-hidden="true" tabindex="-1"></a>                                    &lt;<span class="ot">manifestEntries</span><span class="er">&gt;</span></span>
<span id="cb5-41"><a href="#cb5-41" aria-hidden="true" tabindex="-1"></a>                                        <span class="er">&lt;Main-Class&gt;example.Main&lt;/Main-Class&gt;</span></span>
<span id="cb5-42"><a href="#cb5-42" aria-hidden="true" tabindex="-1"></a>                                        <span class="er">&lt;Build-Number&gt;1.0&lt;/Build-Number&gt;</span></span>
<span id="cb5-43"><a href="#cb5-43" aria-hidden="true" tabindex="-1"></a>                                    <span class="er">&lt;/manifestEntries&gt;</span></span>
<span id="cb5-44"><a href="#cb5-44" aria-hidden="true" tabindex="-1"></a>                                <span class="er">&lt;/transformer&gt;</span></span>
<span id="cb5-45"><a href="#cb5-45" aria-hidden="true" tabindex="-1"></a>                            <span class="er">&lt;/transformers&gt;</span></span>
<span id="cb5-46"><a href="#cb5-46" aria-hidden="true" tabindex="-1"></a>                        <span class="er">&lt;/configuration&gt;</span></span>
<span id="cb5-47"><a href="#cb5-47" aria-hidden="true" tabindex="-1"></a>                    <span class="er">&lt;/execution&gt;</span></span>
<span id="cb5-48"><a href="#cb5-48" aria-hidden="true" tabindex="-1"></a>                <span class="er">&lt;/executions&gt;</span></span>
<span id="cb5-49"><a href="#cb5-49" aria-hidden="true" tabindex="-1"></a>            <span class="er">&lt;/plugin&gt;</span></span>
<span id="cb5-50"><a href="#cb5-50" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;/plugins&gt;</span></span>
<span id="cb5-51"><a href="#cb5-51" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;/build&gt;</span></span>
<span id="cb5-52"><a href="#cb5-52" aria-hidden="true" tabindex="-1"></a><span class="er">&lt;/project&gt;</span></span></code></pre></div>
<p>Where the "shade" plugin will handle including the code from all of your dependencies into the jar. In this case, the only external dependency is <a href="https://commons.apache.org/proper/commons-text/"><code>org.apache.commons/commons-text</code></a>.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>mvn clean package</span></code></pre></div>
<p>Then for the purposes of this guide we will move that jar into a new directory where it will be separate from whatever other files are in <code>target/</code>.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>mkdir build </span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>mv target/javaexe-1.0.jar build</span></code></pre></div>
<h2 id="step-2-create-a-java-runtime-environment">Step 2. Create a Java Runtime Environment</h2>
<p>In order to run the jar from the previous step, we will need to bundle it with a Java Runtime Environment. To do this we will use <a href="https://docs.oracle.com/en/java/javase/18/docs/specs/man/jlink.html"><code>jlink</code></a>.</p>
<p>Since <a href="https://blog.frankel.ch/update-state-java-modularization/">the Java ecosystem hasn't embraced modules</a>, you most likely haven't heard of or used <a href="https://docs.oracle.com/en/java/javase/18/docs/specs/man/jlink.html"><code>jlink</code></a>.</p>
<p>The short pitch is that it can create "custom runtime images." Say you are making a web server. You don't need AWT or Swing, so including all the code for that is a tad wasteful. With <a href="https://docs.oracle.com/en/java/javase/18/docs/specs/man/jlink.html"><code>jlink</code></a> you can make a JRE that doesn't include the <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/module-summary.html"><code>java.desktop</code></a> module at all.</p>
<p>This system works best if your application and all of its dependencies include compiled <code>module-info.java</code> files which let <a href="https://docs.oracle.com/en/java/javase/18/docs/specs/man/jlink.html"><code>jlink</code></a> know exactly what modules you want to include. You can also manually figure out the list of required modules by using <a href="https://docs.oracle.com/en/java/javase/18/docs/specs/man/jdeps.html"><code>jdeps</code></a> and a bit of detective work.</p>
<p>Even without a modular project though, we can still use <a href="https://docs.oracle.com/en/java/javase/18/docs/specs/man/jlink.html"><code>jlink</code></a> to effectively clone our Java installation to a directory.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>jlink --add-modules ALL-MODULE-PATH --output build/runtime</span></code></pre></div>
<p>Including every module gives confidence that libraries like <a href="https://commons.apache.org/proper/commons-text/"><code>org.apache.commons/commons-text</code></a> will work as intended, even though we never figured out what modules they actually require.</p>
<h2 id="step-3-bundle-the-jar-and-the-jre-into-an-executable">Step 3. Bundle the Jar and the JRE into an executable</h2>
<p>So with a jar containing our code and all of its dependencies in one hand and a JRE in the other, all that's left is to stitch the two together.</p>
<p>The general technique for that is to</p>
<ol type="1">
<li>Zip up the directory containing the JRE and your application jar.</li>
<li>Attach a stub script to the top of that zip file which will extract the zip to a temporary directory and run the code.</li>
</ol>
<p>There is a JavaScript library which does this called <a href="https://github.com/leafac/caxa">caxa</a>. Its purpose is making NodeJS projects into executables, so it will also bundle whatever NodeJS installation is on the system. That step can luckily be skipped by passing the <code>--no-include-node</code> flag, so it will work just fine for this.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>npx caxa \</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>    --input build \</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>    --output application \</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>    --no-include-node \</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>    -- &quot;{{caxa}}/runtime/bin/java&quot; &quot;-jar&quot; &quot;{{caxa}}/javaexe-1.0.jar&quot;</span></code></pre></div>
<p>This will create an executable called "<code>application</code>." If you are doing this for Windows you should specify "<code>application.exe</code>." When the executable is run the <code>{{caxa}}</code>s in the command will be substituted for to the temporary directory where the zip file was expanded.</p>
<hr />
<p>I am aware of <a href="https://www.jdeploy.com/">jdeploy</a> - and it does handle stuff that I didn't cover or would be relatively hard with this scheme like code signing or automatic updates - but as far as I can tell it still <a href="https://www.jdeploy.com/docs/manual/#_the_installer">requires that users run an installer</a>.</p>
<p>On code signing, there <a href="https://github.com/leafac/caxa/issues/40">is an open issue with caxa</a> to figure out how to do that. I can make another post or update this one if an approach is figured out. I don't quite understand the issue, so I don't feel qualified to comment.</p>
<p>If any mildly ambitious reader wants to try their hand at making <a href="https://github.com/leafac/caxa">caxa</a> in a different language so this process isn't dependent on the JS ecosystem I encourage it.</p>
<p>As always, comments and corrections welcome.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>The different ways to handle errors in C</title><link>https://mccue.dev/pages/7-27-22-c-errors</link><description></description><pubDate>Wed, 27 Jul 0022 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>The different ways to handle errors in C</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">The different ways to handle errors in C</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
C doesn't have a single clear way to handle errors.

<p>The tutorials out there are <a href="https://www.geeksforgeeks.org/error-handling-c-programs/">pretty</a> <a href="https://www.studytonight.com/c/error-handling-in-c.php">much</a> <a href="https://www.tutorialspoint.com/cprogramming/c_error_handling.htm">garbage</a> too.</p>
<p>So for this post, we are going to work with the toy example of a function that parses natural numbers from a string and go through the different approaches.</p>
<p>Code samples can be found in a compilable state <a href="https://github.com/bowbahdoe/c-error-examples">here</a>.</p>
<h2 id="1-the-ostrich-algorithm">1. The Ostrich Algorithm</h2>
<p>This might sound silly, but how often are you really going to run out of memory?</p>
<p>If an error condition is rare enough, you can always just dig your head in the sand and choose to ignore the possibility.</p>
<p><img src="/pages/7-27-22-ostrich.png" alt="Ostrich burying its head in sand"></img></p>
<p>This can make code a lot prettier, but at the cost of robustness.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> parse_natural_base_10_number<span class="op">(</span><span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> s<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> parsed <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">!=</span> <span class="ch">&#39;\0&#39;</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>        parsed <span class="op">*=</span> <span class="dv">10</span><span class="op">;</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>        parsed <span class="op">+=</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">-</span> <span class="ch">&#39;0&#39;</span><span class="op">;</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> parsed<span class="op">;</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>    printf<span class="op">(</span><span class="st">&quot;Expecting garbage or crash on bad values</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">);</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> examples<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span> <span class="st">&quot;10&quot;</span><span class="op">,</span> <span class="st">&quot;foo&quot;</span><span class="op">,</span> <span class="st">&quot;42&quot;</span><span class="op">,</span> <span class="st">&quot;&quot;</span> <span class="op">};</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">4</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>        <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> example <span class="op">=</span> examples<span class="op">[</span>i<span class="op">];</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> parsed <span class="op">=</span> parse_natural_base_10_number<span class="op">(</span>example<span class="op">);</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>        printf<span class="op">(</span><span class="st">&quot;parsed: %d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> parsed<span class="op">);</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb2"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>Expecting garbage or crash on bad values</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>parsed: 10</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>parsed: 6093</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>parsed: 42</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>parsed: 0</span></code></pre></div>
<p>A real world example of this can be seen <a href="https://github.com/flipperdevices/flipperzero-firmware/blob/dev/applications/rpc/rpc_storage.c#L117">with the firmware for flipper devices'</a> use of <a href="https://cplusplus.com/reference/cstdlib/malloc/"><code>malloc</code></a>.</p>
<h2 id="2-crash">2. Crash.</h2>
<p>Sometimes errors aren't practically recoverable. Most applications should probably just give up when <a href="https://cplusplus.com/reference/cstdlib/malloc/"><code>malloc</code></a> returns <code>NULL</code>.</p>
<p>If you are sure that there isn't a way to recover from an error condition and that a caller won't want to handle it in any other way, you can just print a message saying what went wrong and exit the program.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdlib.h&gt;</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> parse_natural_base_10_number<span class="op">(</span><span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> s<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> parsed <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">!=</span> <span class="ch">&#39;\0&#39;</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>s<span class="op">[</span>i<span class="op">]</span> <span class="op">&lt;</span> <span class="ch">&#39;0&#39;</span> <span class="op">||</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">&gt;</span> <span class="ch">&#39;9&#39;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>            printf<span class="op">(</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>               <span class="st">&quot;Got a bad character (&#39;%c&#39;) in %s, crashing.&quot;</span><span class="op">,</span> </span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>               s<span class="op">[</span>i<span class="op">],</span> </span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>               s</span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>            exit<span class="op">(</span><span class="dv">1</span><span class="op">);</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>            parsed <span class="op">*=</span> <span class="dv">10</span><span class="op">;</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>            parsed <span class="op">+=</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">-</span> <span class="ch">&#39;0&#39;</span><span class="op">;</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> parsed<span class="op">;</span></span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true" tabindex="-1"></a>    <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> examples<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span> <span class="st">&quot;10&quot;</span><span class="op">,</span> <span class="st">&quot;42&quot;</span><span class="op">,</span> <span class="st">&quot;foo&quot;</span> <span class="op">};</span></span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">3</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true" tabindex="-1"></a>        <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> example <span class="op">=</span> examples<span class="op">[</span>i<span class="op">];</span></span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> parsed <span class="op">=</span> parse_natural_base_10_number<span class="op">(</span>example<span class="op">);</span></span>
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true" tabindex="-1"></a>        printf<span class="op">(</span><span class="st">&quot;parsed: %d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> parsed<span class="op">);</span></span>
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-32"><a href="#cb3-32" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb3-33"><a href="#cb3-33" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb4"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="an">parsed:</span><span class="co"> 10</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="an">parsed:</span><span class="co"> 42</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>Got a bad character (&#39;f&#39;) in foo, crashing.</span></code></pre></div>
<p>You can see this approach <a href="https://github.com/xianyi/OpenBLAS/blob/develop/benchmark/geev.c#L100-122">in the code of OpenBLAS</a>.</p>
<h2 id="3-return-a-negative-number">3. Return a negative number.</h2>
<p>If the function normally would return a natural number, then you can use a negative number to indicate a failure. This is applicable both to our toy example and cases like returning the number of bytes read from a file.</p>
<p>If there are different kinds of errors for this sort of case you could also use specific negative numbers to indicate the different categories.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> parse_natural_base_10_number<span class="op">(</span><span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> s<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> parsed <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">!=</span> <span class="ch">&#39;\0&#39;</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>s<span class="op">[</span>i<span class="op">]</span> <span class="op">&lt;</span> <span class="ch">&#39;0&#39;</span> <span class="op">||</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">&gt;</span> <span class="ch">&#39;9&#39;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="op">-</span><span class="dv">1</span><span class="op">;</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>            parsed <span class="op">*=</span> <span class="dv">10</span><span class="op">;</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>            parsed <span class="op">+=</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">-</span> <span class="ch">&#39;0&#39;</span><span class="op">;</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> parsed<span class="op">;</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a>    <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> examples<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span> <span class="st">&quot;10&quot;</span><span class="op">,</span> <span class="st">&quot;foo&quot;</span><span class="op">,</span> <span class="st">&quot;42&quot;</span> <span class="op">};</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">3</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true" tabindex="-1"></a>        <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> example <span class="op">=</span> examples<span class="op">[</span>i<span class="op">];</span></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> parsed <span class="op">=</span> parse_natural_base_10_number<span class="op">(</span>example<span class="op">);</span></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>parsed <span class="op">&lt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true" tabindex="-1"></a>            printf<span class="op">(</span><span class="st">&quot;failed: %s</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> example<span class="op">);</span></span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb5-26"><a href="#cb5-26" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb5-27"><a href="#cb5-27" aria-hidden="true" tabindex="-1"></a>            printf<span class="op">(</span><span class="st">&quot;worked: %d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> parsed<span class="op">);</span></span>
<span id="cb5-28"><a href="#cb5-28" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb5-29"><a href="#cb5-29" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-30"><a href="#cb5-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-31"><a href="#cb5-31" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb5-32"><a href="#cb5-32" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb6"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="an">worked:</span><span class="co"> 10</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="an">failed:</span><span class="co"> foo</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="an">worked:</span><span class="co"> 42</span></span></code></pre></div>
<p>You can see examples of this <a href="https://github.com/torvalds/linux/blob/master/tools/testing/selftests/net/ipsec.c#L131-151">in the Linux kernel.</a></p>
<h2 id="4-return-null">4. Return NULL</h2>
<p>If the function would normally return a pointer, then you can use <code>NULL</code> to indicate that something went wrong.</p>
<p>Most functions that would be returning pointers will be doing heap allocation in order for that to be sound, so this scheme is likely not applicable when you want to avoid allocations.</p>
<p>Also, lets be real, feels silly to heap allocate an int.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdlib.h&gt;</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span><span class="op">*</span> parse_natural_base_10_number<span class="op">(</span><span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> s<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> parsed <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">!=</span> <span class="ch">&#39;\0&#39;</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>s<span class="op">[</span>i<span class="op">]</span> <span class="op">&lt;</span> <span class="ch">&#39;0&#39;</span> <span class="op">||</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">&gt;</span> <span class="ch">&#39;9&#39;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> NULL<span class="op">;</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>            parsed <span class="op">*=</span> <span class="dv">10</span><span class="op">;</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>            parsed <span class="op">+=</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">-</span> <span class="ch">&#39;0&#39;</span><span class="op">;</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span><span class="op">*</span> result <span class="op">=</span> malloc<span class="op">(</span><span class="kw">sizeof</span> <span class="op">(</span><span class="dt">int</span><span class="op">));</span></span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">*</span>result <span class="op">=</span> parsed<span class="op">;</span></span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> result<span class="op">;</span></span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true" tabindex="-1"></a>    <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> examples<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span> <span class="st">&quot;10&quot;</span><span class="op">,</span> <span class="st">&quot;foo&quot;</span><span class="op">,</span> <span class="st">&quot;42&quot;</span> <span class="op">};</span></span>
<span id="cb7-23"><a href="#cb7-23" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">3</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb7-24"><a href="#cb7-24" aria-hidden="true" tabindex="-1"></a>        <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> example <span class="op">=</span> examples<span class="op">[</span>i<span class="op">];</span></span>
<span id="cb7-25"><a href="#cb7-25" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span><span class="op">*</span> parsed <span class="op">=</span> parse_natural_base_10_number<span class="op">(</span>example<span class="op">);</span></span>
<span id="cb7-26"><a href="#cb7-26" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>parsed <span class="op">==</span> NULL<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-27"><a href="#cb7-27" aria-hidden="true" tabindex="-1"></a>            printf<span class="op">(</span><span class="st">&quot;failed: %s</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> example<span class="op">);</span></span>
<span id="cb7-28"><a href="#cb7-28" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb7-29"><a href="#cb7-29" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb7-30"><a href="#cb7-30" aria-hidden="true" tabindex="-1"></a>            printf<span class="op">(</span><span class="st">&quot;worked: %d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> <span class="op">*</span>parsed<span class="op">);</span></span>
<span id="cb7-31"><a href="#cb7-31" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb7-32"><a href="#cb7-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-33"><a href="#cb7-33" aria-hidden="true" tabindex="-1"></a>        free<span class="op">(</span>parsed<span class="op">);</span></span>
<span id="cb7-34"><a href="#cb7-34" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-35"><a href="#cb7-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-36"><a href="#cb7-36" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb7-37"><a href="#cb7-37" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb8"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="an">worked:</span><span class="co"> 10</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="an">failed:</span><span class="co"> foo</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="an">worked:</span><span class="co"> 42</span></span></code></pre></div>
<p>A real world example of this scheme is <a href="https://cplusplus.com/reference/cstdlib/malloc/"><code>malloc</code></a>. If malloc fails to allocate memory, then instead of returning a pointer to newly allocated memory it will return a null pointer.</p>
<h2 id="5-return-a-boolean-and-take-an-out-param">5. Return a boolean and take an out param</h2>
<p>One of the less obvious things you can do in C is to have one or more of a function's arguments "out params". This means that it is part of the contract of the function that it will write into the memory behind a pointer.</p>
<p>If a function can fail, a natural translation of this can be to return a boolean indicating whether it did and pass an out param that you only inspect when true is returned.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdbool.h&gt;</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> parse_natural_base_10_number<span class="op">(</span><span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> s<span class="op">,</span> <span class="dt">int</span><span class="op">*</span> out<span class="op">)</span> <span class="op">{</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> parsed <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">!=</span> <span class="ch">&#39;\0&#39;</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>s<span class="op">[</span>i<span class="op">]</span> <span class="op">&lt;</span> <span class="ch">&#39;0&#39;</span> <span class="op">||</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">&gt;</span> <span class="ch">&#39;9&#39;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> false<span class="op">;</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>            parsed <span class="op">*=</span> <span class="dv">10</span><span class="op">;</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>            parsed <span class="op">+=</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">-</span> <span class="ch">&#39;0&#39;</span><span class="op">;</span></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">*</span>out <span class="op">=</span> parsed<span class="op">;</span></span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> true<span class="op">;</span></span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb9-19"><a href="#cb9-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-20"><a href="#cb9-20" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb9-21"><a href="#cb9-21" aria-hidden="true" tabindex="-1"></a>    <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> examples<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span> <span class="st">&quot;10&quot;</span><span class="op">,</span> <span class="st">&quot;foo&quot;</span><span class="op">,</span> <span class="st">&quot;42&quot;</span> <span class="op">};</span></span>
<span id="cb9-22"><a href="#cb9-22" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">3</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb9-23"><a href="#cb9-23" aria-hidden="true" tabindex="-1"></a>        <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> example <span class="op">=</span> examples<span class="op">[</span>i<span class="op">];</span></span>
<span id="cb9-24"><a href="#cb9-24" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> parsed<span class="op">;</span></span>
<span id="cb9-25"><a href="#cb9-25" aria-hidden="true" tabindex="-1"></a>        <span class="dt">bool</span> success <span class="op">=</span> parse_natural_base_10_number<span class="op">(</span></span>
<span id="cb9-26"><a href="#cb9-26" aria-hidden="true" tabindex="-1"></a>            example<span class="op">,</span> </span>
<span id="cb9-27"><a href="#cb9-27" aria-hidden="true" tabindex="-1"></a>            <span class="op">&amp;</span>parsed</span>
<span id="cb9-28"><a href="#cb9-28" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb9-29"><a href="#cb9-29" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(!</span>success<span class="op">)</span> <span class="op">{</span></span>
<span id="cb9-30"><a href="#cb9-30" aria-hidden="true" tabindex="-1"></a>            printf<span class="op">(</span><span class="st">&quot;failed: %s</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> example<span class="op">);</span></span>
<span id="cb9-31"><a href="#cb9-31" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb9-32"><a href="#cb9-32" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb9-33"><a href="#cb9-33" aria-hidden="true" tabindex="-1"></a>            printf<span class="op">(</span><span class="st">&quot;worked: %d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> parsed<span class="op">);</span></span>
<span id="cb9-34"><a href="#cb9-34" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb9-35"><a href="#cb9-35" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-36"><a href="#cb9-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-37"><a href="#cb9-37" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb9-38"><a href="#cb9-38" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb10"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="an">worked:</span><span class="co"> 10</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="an">failed:</span><span class="co"> foo</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="an">worked:</span><span class="co"> 42</span></span></code></pre></div>
<p>This is done pretty regularly <a href="https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowdisplayaffinity">in Windows.</a></p>
<h2 id="6-return-an-enum-and-take-an-out-param">6. Return an enum and take an out param</h2>
<p>A boolean can only indicate that something succeeded or failed. If you want to know why something failed then substituting a boolean for an enum is a pretty natural mechanism.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> ParseNaturalNumberResult <span class="op">{</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>    PARSE_NATURAL_SUCCESS<span class="op">,</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>    PARSE_NATURAL_EMPTY_STRING<span class="op">,</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>    PARSE_NATURAL_BAD_CHARACTER</span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> ParseNaturalNumberResult parse_natural_base_10_number<span class="op">(</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>   <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> s<span class="op">,</span> </span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>   <span class="dt">int</span><span class="op">*</span> out</span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>s<span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">==</span> <span class="ch">&#39;\0&#39;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> PARSE_NATURAL_EMPTY_STRING<span class="op">;</span></span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> parsed <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">!=</span> <span class="ch">&#39;\0&#39;</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>s<span class="op">[</span>i<span class="op">]</span> <span class="op">&lt;</span> <span class="ch">&#39;0&#39;</span> <span class="op">||</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">&gt;</span> <span class="ch">&#39;9&#39;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> PARSE_NATURAL_BAD_CHARACTER<span class="op">;</span></span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb11-22"><a href="#cb11-22" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb11-23"><a href="#cb11-23" aria-hidden="true" tabindex="-1"></a>            parsed <span class="op">*=</span> <span class="dv">10</span><span class="op">;</span></span>
<span id="cb11-24"><a href="#cb11-24" aria-hidden="true" tabindex="-1"></a>            parsed <span class="op">+=</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">-</span> <span class="ch">&#39;0&#39;</span><span class="op">;</span></span>
<span id="cb11-25"><a href="#cb11-25" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb11-26"><a href="#cb11-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb11-27"><a href="#cb11-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-28"><a href="#cb11-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">*</span>out <span class="op">=</span> parsed<span class="op">;</span></span>
<span id="cb11-29"><a href="#cb11-29" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> PARSE_NATURAL_SUCCESS<span class="op">;</span></span>
<span id="cb11-30"><a href="#cb11-30" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb11-31"><a href="#cb11-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-32"><a href="#cb11-32" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb11-33"><a href="#cb11-33" aria-hidden="true" tabindex="-1"></a>    <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> examples<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span> <span class="st">&quot;10&quot;</span><span class="op">,</span> <span class="st">&quot;foo&quot;</span><span class="op">,</span> <span class="st">&quot;42&quot;</span><span class="op">,</span> <span class="st">&quot;&quot;</span> <span class="op">};</span></span>
<span id="cb11-34"><a href="#cb11-34" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">4</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb11-35"><a href="#cb11-35" aria-hidden="true" tabindex="-1"></a>        <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> example <span class="op">=</span> examples<span class="op">[</span>i<span class="op">];</span></span>
<span id="cb11-36"><a href="#cb11-36" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> parsed<span class="op">;</span></span>
<span id="cb11-37"><a href="#cb11-37" aria-hidden="true" tabindex="-1"></a>        <span class="cf">switch</span> <span class="op">(</span>parse_natural_base_10_number<span class="op">(</span>example<span class="op">,</span> <span class="op">&amp;</span>parsed<span class="op">))</span> <span class="op">{</span></span>
<span id="cb11-38"><a href="#cb11-38" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> PARSE_NATURAL_SUCCESS<span class="op">:</span></span>
<span id="cb11-39"><a href="#cb11-39" aria-hidden="true" tabindex="-1"></a>                printf<span class="op">(</span><span class="st">&quot;worked: %d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> parsed<span class="op">);</span></span>
<span id="cb11-40"><a href="#cb11-40" aria-hidden="true" tabindex="-1"></a>                <span class="cf">break</span><span class="op">;</span></span>
<span id="cb11-41"><a href="#cb11-41" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> PARSE_NATURAL_EMPTY_STRING<span class="op">:</span></span>
<span id="cb11-42"><a href="#cb11-42" aria-hidden="true" tabindex="-1"></a>                printf<span class="op">(</span><span class="st">&quot;failed because empty string</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">);</span></span>
<span id="cb11-43"><a href="#cb11-43" aria-hidden="true" tabindex="-1"></a>                <span class="cf">break</span><span class="op">;</span></span>
<span id="cb11-44"><a href="#cb11-44" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> PARSE_NATURAL_BAD_CHARACTER<span class="op">:</span></span>
<span id="cb11-45"><a href="#cb11-45" aria-hidden="true" tabindex="-1"></a>                printf<span class="op">(</span><span class="st">&quot;failed because bad char: %s</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> example<span class="op">);</span></span>
<span id="cb11-46"><a href="#cb11-46" aria-hidden="true" tabindex="-1"></a>                <span class="cf">break</span><span class="op">;</span></span>
<span id="cb11-47"><a href="#cb11-47" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb11-48"><a href="#cb11-48" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb11-49"><a href="#cb11-49" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-50"><a href="#cb11-50" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb11-51"><a href="#cb11-51" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb12"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="an">worked:</span><span class="co"> 10</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="an">failed because bad char:</span><span class="co"> foo</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a><span class="an">worked:</span><span class="co"> 42</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>failed because empty string</span></code></pre></div>
<h2 id="7-return-a-boolean-and-take-two-out-params">7. Return a boolean and take two out params</h2>
<p>While an enum can give you the "category" of an error, it doesn't have a place for recording any more specific information than that.</p>
<p>For example, a pretty reasonable thing to want to know if you run into an unexpected character is where in the string that character was found.</p>
<p>By adding a second out param you can have a place to put this information.</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdbool.h&gt;</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> parse_natural_base_10_number<span class="op">(</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>   <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> s<span class="op">,</span> </span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>   <span class="dt">int</span><span class="op">*</span> out_value<span class="op">,</span> </span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>   <span class="dt">size_t</span><span class="op">*</span> out_bad_index</span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> parsed <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">!=</span> <span class="ch">&#39;\0&#39;</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>s<span class="op">[</span>i<span class="op">]</span> <span class="op">&lt;</span> <span class="ch">&#39;0&#39;</span> <span class="op">||</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">&gt;</span> <span class="ch">&#39;9&#39;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a>            <span class="op">*</span>out_bad_index <span class="op">=</span> i<span class="op">;</span></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> false<span class="op">;</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a>            parsed <span class="op">*=</span> <span class="dv">10</span><span class="op">;</span></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a>            parsed <span class="op">+=</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">-</span> <span class="ch">&#39;0&#39;</span><span class="op">;</span></span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">*</span>out_value <span class="op">=</span> parsed<span class="op">;</span></span>
<span id="cb13-22"><a href="#cb13-22" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> true<span class="op">;</span></span>
<span id="cb13-23"><a href="#cb13-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb13-24"><a href="#cb13-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-25"><a href="#cb13-25" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb13-26"><a href="#cb13-26" aria-hidden="true" tabindex="-1"></a>    <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> examples<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span> <span class="st">&quot;10&quot;</span><span class="op">,</span> <span class="st">&quot;foo&quot;</span><span class="op">,</span> <span class="st">&quot;42&quot;</span><span class="op">,</span> <span class="st">&quot;12a34&quot;</span> <span class="op">};</span></span>
<span id="cb13-27"><a href="#cb13-27" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">4</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb13-28"><a href="#cb13-28" aria-hidden="true" tabindex="-1"></a>        <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> example <span class="op">=</span> examples<span class="op">[</span>i<span class="op">];</span></span>
<span id="cb13-29"><a href="#cb13-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-30"><a href="#cb13-30" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> parsed<span class="op">;</span></span>
<span id="cb13-31"><a href="#cb13-31" aria-hidden="true" tabindex="-1"></a>        <span class="dt">size_t</span> bad_index<span class="op">;</span></span>
<span id="cb13-32"><a href="#cb13-32" aria-hidden="true" tabindex="-1"></a>        <span class="dt">bool</span> success <span class="op">=</span> parse_natural_base_10_number<span class="op">(</span></span>
<span id="cb13-33"><a href="#cb13-33" aria-hidden="true" tabindex="-1"></a>            example<span class="op">,</span> </span>
<span id="cb13-34"><a href="#cb13-34" aria-hidden="true" tabindex="-1"></a>            <span class="op">&amp;</span>parsed<span class="op">,</span> </span>
<span id="cb13-35"><a href="#cb13-35" aria-hidden="true" tabindex="-1"></a>            <span class="op">&amp;</span>bad_index</span>
<span id="cb13-36"><a href="#cb13-36" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb13-37"><a href="#cb13-37" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(!</span>success<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-38"><a href="#cb13-38" aria-hidden="true" tabindex="-1"></a>            printf<span class="op">(</span><span class="st">&quot;failed: %s</span><span class="sc">\n</span><span class="st">        &quot;</span><span class="op">,</span> example<span class="op">);</span></span>
<span id="cb13-39"><a href="#cb13-39" aria-hidden="true" tabindex="-1"></a>            <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> j <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> j <span class="op">&lt;</span> bad_index<span class="op">;</span> j<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb13-40"><a href="#cb13-40" aria-hidden="true" tabindex="-1"></a>                printf<span class="op">(</span><span class="st">&quot; &quot;</span><span class="op">);</span></span>
<span id="cb13-41"><a href="#cb13-41" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb13-42"><a href="#cb13-42" aria-hidden="true" tabindex="-1"></a>            printf<span class="op">(</span><span class="st">&quot;^☹️</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">);</span></span>
<span id="cb13-43"><a href="#cb13-43" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb13-44"><a href="#cb13-44" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb13-45"><a href="#cb13-45" aria-hidden="true" tabindex="-1"></a>            printf<span class="op">(</span><span class="st">&quot;worked: %d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> parsed<span class="op">);</span></span>
<span id="cb13-46"><a href="#cb13-46" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb13-47"><a href="#cb13-47" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-48"><a href="#cb13-48" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-49"><a href="#cb13-49" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb13-50"><a href="#cb13-50" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb14"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="an">worked:</span><span class="co"> 10</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="an">failed:</span><span class="co"> foo</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a><span class="co">        ^☹️</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a><span class="an">worked:</span><span class="co"> 42</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a><span class="an">failed:</span><span class="co"> 12a34</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a><span class="co">          ^☹️</span></span></code></pre></div>
<h2 id="8-return-an-enum-and-multiple-out-params">8. Return an enum and multiple out params</h2>
<p>A natural extension of the previous two patterns is that if you have multiple ways in which a computation can fail, you can return an enum with each way and take an out param for each way that would require data.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;string.h&gt;</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> ParseNaturalNumberResult <span class="op">{</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>    PARSE_NATURAL_SUCCESS<span class="op">,</span></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>    PARSE_NATURAL_EMPTY_STRING<span class="op">,</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>    PARSE_NATURAL_BAD_CHARACTER<span class="op">,</span></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>    PARSE_NUMBER_TOO_BIG</span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> BadCharacterInfo <span class="op">{</span></span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> index<span class="op">;</span></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-15"><a href="#cb15-15" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> TooBigInfo <span class="op">{</span></span>
<span id="cb15-16"><a href="#cb15-16" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> remaining_characters<span class="op">;</span></span>
<span id="cb15-17"><a href="#cb15-17" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb15-18"><a href="#cb15-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-19"><a href="#cb15-19" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> ParseNaturalNumberResult parse_natural_base_10_number<span class="op">(</span></span>
<span id="cb15-20"><a href="#cb15-20" aria-hidden="true" tabindex="-1"></a>        <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> s<span class="op">,</span></span>
<span id="cb15-21"><a href="#cb15-21" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span><span class="op">*</span> out_value<span class="op">,</span></span>
<span id="cb15-22"><a href="#cb15-22" aria-hidden="true" tabindex="-1"></a>        <span class="kw">struct</span> BadCharacterInfo<span class="op">*</span> bad_character_info<span class="op">,</span></span>
<span id="cb15-23"><a href="#cb15-23" aria-hidden="true" tabindex="-1"></a>        <span class="kw">struct</span> TooBigInfo<span class="op">*</span> too_big_info</span>
<span id="cb15-24"><a href="#cb15-24" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-25"><a href="#cb15-25" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>s<span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">==</span> <span class="ch">&#39;\0&#39;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-26"><a href="#cb15-26" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> PARSE_NATURAL_EMPTY_STRING<span class="op">;</span></span>
<span id="cb15-27"><a href="#cb15-27" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb15-28"><a href="#cb15-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-29"><a href="#cb15-29" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> parsed <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb15-30"><a href="#cb15-30" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">!=</span> <span class="ch">&#39;\0&#39;</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb15-31"><a href="#cb15-31" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>s<span class="op">[</span>i<span class="op">]</span> <span class="op">&lt;</span> <span class="ch">&#39;0&#39;</span> <span class="op">||</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">&gt;</span> <span class="ch">&#39;9&#39;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-32"><a href="#cb15-32" aria-hidden="true" tabindex="-1"></a>            bad_character_info<span class="op">-&gt;</span>index <span class="op">=</span> i<span class="op">;</span></span>
<span id="cb15-33"><a href="#cb15-33" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> PARSE_NATURAL_BAD_CHARACTER<span class="op">;</span></span>
<span id="cb15-34"><a href="#cb15-34" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb15-35"><a href="#cb15-35" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb15-36"><a href="#cb15-36" aria-hidden="true" tabindex="-1"></a>            <span class="dt">int</span> digit <span class="op">=</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">-</span> <span class="ch">&#39;0&#39;</span><span class="op">;</span></span>
<span id="cb15-37"><a href="#cb15-37" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>__builtin_smul_overflow<span class="op">(</span>parsed<span class="op">,</span> <span class="dv">10</span><span class="op">,</span> <span class="op">&amp;</span>parsed<span class="op">)</span> <span class="op">||</span></span>
<span id="cb15-38"><a href="#cb15-38" aria-hidden="true" tabindex="-1"></a>                __builtin_sadd_overflow<span class="op">(</span>parsed<span class="op">,</span> digit<span class="op">,</span> <span class="op">&amp;</span>parsed<span class="op">))</span> <span class="op">{</span></span>
<span id="cb15-39"><a href="#cb15-39" aria-hidden="true" tabindex="-1"></a>                too_big_info<span class="op">-&gt;</span>remaining_characters <span class="op">=</span> strlen<span class="op">(</span>s<span class="op">)</span> <span class="op">-</span> i<span class="op">;</span></span>
<span id="cb15-40"><a href="#cb15-40" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> PARSE_NUMBER_TOO_BIG<span class="op">;</span></span>
<span id="cb15-41"><a href="#cb15-41" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb15-42"><a href="#cb15-42" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb15-43"><a href="#cb15-43" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb15-44"><a href="#cb15-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-45"><a href="#cb15-45" aria-hidden="true" tabindex="-1"></a>    <span class="op">*</span>out_value <span class="op">=</span> parsed<span class="op">;</span></span>
<span id="cb15-46"><a href="#cb15-46" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> PARSE_NATURAL_SUCCESS<span class="op">;</span></span>
<span id="cb15-47"><a href="#cb15-47" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb15-48"><a href="#cb15-48" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-49"><a href="#cb15-49" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb15-50"><a href="#cb15-50" aria-hidden="true" tabindex="-1"></a>    <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> examples<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span> <span class="st">&quot;10&quot;</span><span class="op">,</span> </span>
<span id="cb15-51"><a href="#cb15-51" aria-hidden="true" tabindex="-1"></a>                               <span class="st">&quot;foo&quot;</span><span class="op">,</span> </span>
<span id="cb15-52"><a href="#cb15-52" aria-hidden="true" tabindex="-1"></a>                               <span class="st">&quot;42&quot;</span><span class="op">,</span> </span>
<span id="cb15-53"><a href="#cb15-53" aria-hidden="true" tabindex="-1"></a>                               <span class="st">&quot;&quot;</span><span class="op">,</span> </span>
<span id="cb15-54"><a href="#cb15-54" aria-hidden="true" tabindex="-1"></a>                               <span class="st">&quot;99999999999999&quot;</span> <span class="op">};</span></span>
<span id="cb15-55"><a href="#cb15-55" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">5</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb15-56"><a href="#cb15-56" aria-hidden="true" tabindex="-1"></a>        <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> example <span class="op">=</span> examples<span class="op">[</span>i<span class="op">];</span></span>
<span id="cb15-57"><a href="#cb15-57" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> parsed<span class="op">;</span></span>
<span id="cb15-58"><a href="#cb15-58" aria-hidden="true" tabindex="-1"></a>        <span class="kw">struct</span> BadCharacterInfo bad_character_info<span class="op">;</span></span>
<span id="cb15-59"><a href="#cb15-59" aria-hidden="true" tabindex="-1"></a>        <span class="kw">struct</span> TooBigInfo too_big_info<span class="op">;</span></span>
<span id="cb15-60"><a href="#cb15-60" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-61"><a href="#cb15-61" aria-hidden="true" tabindex="-1"></a>        <span class="cf">switch</span> <span class="op">(</span>parse_natural_base_10_number<span class="op">(</span></span>
<span id="cb15-62"><a href="#cb15-62" aria-hidden="true" tabindex="-1"></a>            example<span class="op">,</span> </span>
<span id="cb15-63"><a href="#cb15-63" aria-hidden="true" tabindex="-1"></a>            <span class="op">&amp;</span>parsed<span class="op">,</span> </span>
<span id="cb15-64"><a href="#cb15-64" aria-hidden="true" tabindex="-1"></a>            <span class="op">&amp;</span>bad_character_info<span class="op">,</span></span>
<span id="cb15-65"><a href="#cb15-65" aria-hidden="true" tabindex="-1"></a>            <span class="op">&amp;</span>too_big_info</span>
<span id="cb15-66"><a href="#cb15-66" aria-hidden="true" tabindex="-1"></a>        <span class="op">))</span> <span class="op">{</span></span>
<span id="cb15-67"><a href="#cb15-67" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> PARSE_NATURAL_SUCCESS<span class="op">:</span></span>
<span id="cb15-68"><a href="#cb15-68" aria-hidden="true" tabindex="-1"></a>                printf<span class="op">(</span><span class="st">&quot;worked: %d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> parsed<span class="op">);</span></span>
<span id="cb15-69"><a href="#cb15-69" aria-hidden="true" tabindex="-1"></a>                <span class="cf">break</span><span class="op">;</span></span>
<span id="cb15-70"><a href="#cb15-70" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> PARSE_NATURAL_EMPTY_STRING<span class="op">:</span></span>
<span id="cb15-71"><a href="#cb15-71" aria-hidden="true" tabindex="-1"></a>                printf<span class="op">(</span><span class="st">&quot;failed because empty string</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">);</span></span>
<span id="cb15-72"><a href="#cb15-72" aria-hidden="true" tabindex="-1"></a>                <span class="cf">break</span><span class="op">;</span></span>
<span id="cb15-73"><a href="#cb15-73" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> PARSE_NATURAL_BAD_CHARACTER<span class="op">:</span></span>
<span id="cb15-74"><a href="#cb15-74" aria-hidden="true" tabindex="-1"></a>                printf<span class="op">(</span></span>
<span id="cb15-75"><a href="#cb15-75" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;failed because bad char at index %zu: %s</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span></span>
<span id="cb15-76"><a href="#cb15-76" aria-hidden="true" tabindex="-1"></a>                    bad_character_info<span class="op">.</span>index<span class="op">,</span></span>
<span id="cb15-77"><a href="#cb15-77" aria-hidden="true" tabindex="-1"></a>                    example</span>
<span id="cb15-78"><a href="#cb15-78" aria-hidden="true" tabindex="-1"></a>                <span class="op">);</span></span>
<span id="cb15-79"><a href="#cb15-79" aria-hidden="true" tabindex="-1"></a>                <span class="cf">break</span><span class="op">;</span></span>
<span id="cb15-80"><a href="#cb15-80" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> PARSE_NUMBER_TOO_BIG<span class="op">:</span></span>
<span id="cb15-81"><a href="#cb15-81" aria-hidden="true" tabindex="-1"></a>                printf<span class="op">(</span></span>
<span id="cb15-82"><a href="#cb15-82" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;number was too big. had %zu digits left: %s</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span></span>
<span id="cb15-83"><a href="#cb15-83" aria-hidden="true" tabindex="-1"></a>                    too_big_info<span class="op">.</span>remaining_characters<span class="op">,</span></span>
<span id="cb15-84"><a href="#cb15-84" aria-hidden="true" tabindex="-1"></a>                    example</span>
<span id="cb15-85"><a href="#cb15-85" aria-hidden="true" tabindex="-1"></a>                <span class="op">);</span></span>
<span id="cb15-86"><a href="#cb15-86" aria-hidden="true" tabindex="-1"></a>                <span class="cf">break</span><span class="op">;</span></span>
<span id="cb15-87"><a href="#cb15-87" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb15-88"><a href="#cb15-88" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb15-89"><a href="#cb15-89" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-90"><a href="#cb15-90" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb15-91"><a href="#cb15-91" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb16"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="an">worked:</span><span class="co"> 10</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="an">failed because bad char at index 0:</span><span class="co"> foo</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="an">worked:</span><span class="co"> 42</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>failed because empty string</span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>number was too big. had 5 digits left: 99999999999999</span></code></pre></div>
<h2 id="9-set-a-thread-local-static-value">9. Set a thread local static value</h2>
<p>Another option is to, on an error, set a thread local static variable. This avoids needing to propagate an error explicitly all the way up the stack from where it occurs and makes the "normal" api of the function look as neat and clean as the ostrich or crash approaches.</p>
<p>Once you set the thread local static value, either you</p>
<ol type="1">
<li>Return a predictable value indicating an issue (<code>NULL</code>, a negative number, etc) which hints to the programmer to check the thread local static value.</li>
<li>Return an uninitialized value and rely on the programmer to know that the value might be bogus unless they check the thread local static value</li>
</ol>
<div class="sourceCode" id="cb17"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdbool.h&gt;</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a><span class="kw">_Thread_local</span> <span class="dt">static</span> <span class="dt">bool</span> parse_number_error <span class="op">=</span> false<span class="op">;</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> parse_natural_base_10_number<span class="op">(</span><span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> s<span class="op">)</span> <span class="op">{</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> parsed <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">!=</span> <span class="ch">&#39;\0&#39;</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>s<span class="op">[</span>i<span class="op">]</span> <span class="op">&lt;</span> <span class="ch">&#39;0&#39;</span> <span class="op">||</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">&gt;</span> <span class="ch">&#39;9&#39;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a>            parse_number_error <span class="op">=</span> true<span class="op">;</span></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a>            parsed <span class="op">*=</span> <span class="dv">10</span><span class="op">;</span></span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a>            parsed <span class="op">+=</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">-</span> <span class="ch">&#39;0&#39;</span><span class="op">;</span></span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb17-17"><a href="#cb17-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-18"><a href="#cb17-18" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> parsed<span class="op">;</span></span>
<span id="cb17-19"><a href="#cb17-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb17-20"><a href="#cb17-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-21"><a href="#cb17-21" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb17-22"><a href="#cb17-22" aria-hidden="true" tabindex="-1"></a>    <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> examples<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span> <span class="st">&quot;10&quot;</span><span class="op">,</span> <span class="st">&quot;42&quot;</span><span class="op">,</span> <span class="st">&quot;foo&quot;</span> <span class="op">};</span></span>
<span id="cb17-23"><a href="#cb17-23" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">3</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb17-24"><a href="#cb17-24" aria-hidden="true" tabindex="-1"></a>        <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> example <span class="op">=</span> examples<span class="op">[</span>i<span class="op">];</span></span>
<span id="cb17-25"><a href="#cb17-25" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> parsed <span class="op">=</span> parse_natural_base_10_number<span class="op">(</span>example<span class="op">);</span></span>
<span id="cb17-26"><a href="#cb17-26" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>parse_number_error<span class="op">)</span> <span class="op">{</span></span>
<span id="cb17-27"><a href="#cb17-27" aria-hidden="true" tabindex="-1"></a>            parse_number_error <span class="op">=</span> false<span class="op">;</span></span>
<span id="cb17-28"><a href="#cb17-28" aria-hidden="true" tabindex="-1"></a>            printf<span class="op">(</span><span class="st">&quot;error: %s</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> example<span class="op">);</span></span>
<span id="cb17-29"><a href="#cb17-29" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb17-30"><a href="#cb17-30" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb17-31"><a href="#cb17-31" aria-hidden="true" tabindex="-1"></a>            printf<span class="op">(</span><span class="st">&quot;parsed: %d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> parsed<span class="op">);</span></span>
<span id="cb17-32"><a href="#cb17-32" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb17-33"><a href="#cb17-33" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb17-34"><a href="#cb17-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-35"><a href="#cb17-35" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb17-36"><a href="#cb17-36" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb18"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="an">parsed:</span><span class="co"> 10</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="an">parsed:</span><span class="co"> 42</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a><span class="an">error:</span><span class="co"> foo</span></span></code></pre></div>
<p>A good deal of built-in apis use a shared static constant int called <a href="https://en.cppreference.com/w/cpp/error/errno"><code>errno</code></a> and if they fail they will set it to a non-zero value. There are then functions like <a href="https://en.cppreference.com/w/c/io/perror"><code>perror</code></a> which can extract messages from the specific error code.</p>
<p>You technically are allowed to use <a href="https://en.cppreference.com/w/cpp/error/errno"><code>errno</code></a> too as well as long as your error conditions can fit into its int encoding.</p>
<p>This is my least favorite of the patterns.</p>
<h2 id="10-return-a-tagged-union">10. Return a tagged union</h2>
<p>The next approach is what languages like <a href="https://www.rust-lang.org/"><code>Rust</code></a> emulate under the hood of their enums.</p>
<p>You make a struct containing two things</p>
<ol type="1">
<li>A "tag". This should be a boolean or an enum depending on your tastes and the number of possibilities.</li>
<li>A union containing enough space for the data that should be associated with each "tag".</li>
</ol>
<p>Then you return this struct directly. The tag tells the caller which field of the union is safe to access and consequently what the "result" of the computation was.</p>
<p>Compared to the out param solutions, where normally you would allocate each possible out param on the stack, this will compact the required space by way of the union.</p>
<p>It also uses regular return values and checking the tag before checking the union is a relatively standard process.</p>
<p>Unfortunately it will also make code more verbose than most of the other options.</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> ParseNaturalNumberResultKind <span class="op">{</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>    PARSE_NATURAL_SUCCESS<span class="op">,</span></span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a>    PARSE_NATURAL_EMPTY_STRING<span class="op">,</span></span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>    PARSE_NATURAL_BAD_CHARACTER</span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> BadCharacter <span class="op">{</span></span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> index<span class="op">;</span></span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span> c<span class="op">;</span></span>
<span id="cb19-12"><a href="#cb19-12" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb19-13"><a href="#cb19-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-14"><a href="#cb19-14" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> ParseNaturalNumberResult <span class="op">{</span></span>
<span id="cb19-15"><a href="#cb19-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">enum</span> ParseNaturalNumberResultKind kind<span class="op">;</span></span>
<span id="cb19-16"><a href="#cb19-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">union</span> <span class="op">{</span></span>
<span id="cb19-17"><a href="#cb19-17" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> success<span class="op">;</span></span>
<span id="cb19-18"><a href="#cb19-18" aria-hidden="true" tabindex="-1"></a>        <span class="kw">struct</span> BadCharacter bad_character<span class="op">;</span></span>
<span id="cb19-19"><a href="#cb19-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> data<span class="op">;</span></span>
<span id="cb19-20"><a href="#cb19-20" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb19-21"><a href="#cb19-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-22"><a href="#cb19-22" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> ParseNaturalNumberResult parse_natural_base_10_number<span class="op">(</span></span>
<span id="cb19-23"><a href="#cb19-23" aria-hidden="true" tabindex="-1"></a>   <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> s</span>
<span id="cb19-24"><a href="#cb19-24" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb19-25"><a href="#cb19-25" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>s<span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">==</span> <span class="ch">&#39;\0&#39;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb19-26"><a href="#cb19-26" aria-hidden="true" tabindex="-1"></a>        <span class="kw">struct</span> ParseNaturalNumberResult result <span class="op">=</span> <span class="op">{</span></span>
<span id="cb19-27"><a href="#cb19-27" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span>kind <span class="op">=</span> PARSE_NATURAL_EMPTY_STRING</span>
<span id="cb19-28"><a href="#cb19-28" aria-hidden="true" tabindex="-1"></a>        <span class="op">};</span></span>
<span id="cb19-29"><a href="#cb19-29" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> result<span class="op">;</span></span>
<span id="cb19-30"><a href="#cb19-30" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb19-31"><a href="#cb19-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-32"><a href="#cb19-32" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> parsed <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb19-33"><a href="#cb19-33" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">!=</span> <span class="ch">&#39;\0&#39;</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb19-34"><a href="#cb19-34" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>s<span class="op">[</span>i<span class="op">]</span> <span class="op">&lt;</span> <span class="ch">&#39;0&#39;</span> <span class="op">||</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">&gt;</span> <span class="ch">&#39;9&#39;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb19-35"><a href="#cb19-35" aria-hidden="true" tabindex="-1"></a>            <span class="kw">struct</span> ParseNaturalNumberResult result <span class="op">=</span> <span class="op">{</span></span>
<span id="cb19-36"><a href="#cb19-36" aria-hidden="true" tabindex="-1"></a>                    <span class="op">.</span>kind <span class="op">=</span> PARSE_NATURAL_BAD_CHARACTER<span class="op">,</span></span>
<span id="cb19-37"><a href="#cb19-37" aria-hidden="true" tabindex="-1"></a>                    <span class="op">.</span>data <span class="op">=</span> <span class="op">{</span></span>
<span id="cb19-38"><a href="#cb19-38" aria-hidden="true" tabindex="-1"></a>                            <span class="op">.</span>bad_character <span class="op">=</span> <span class="op">{</span></span>
<span id="cb19-39"><a href="#cb19-39" aria-hidden="true" tabindex="-1"></a>                                    <span class="op">.</span>index <span class="op">=</span> i<span class="op">,</span></span>
<span id="cb19-40"><a href="#cb19-40" aria-hidden="true" tabindex="-1"></a>                                    <span class="op">.</span>c <span class="op">=</span> s<span class="op">[</span>i<span class="op">]</span></span>
<span id="cb19-41"><a href="#cb19-41" aria-hidden="true" tabindex="-1"></a>                            <span class="op">}</span></span>
<span id="cb19-42"><a href="#cb19-42" aria-hidden="true" tabindex="-1"></a>                    <span class="op">}</span></span>
<span id="cb19-43"><a href="#cb19-43" aria-hidden="true" tabindex="-1"></a>            <span class="op">};</span></span>
<span id="cb19-44"><a href="#cb19-44" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> result<span class="op">;</span></span>
<span id="cb19-45"><a href="#cb19-45" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb19-46"><a href="#cb19-46" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb19-47"><a href="#cb19-47" aria-hidden="true" tabindex="-1"></a>            parsed <span class="op">*=</span> <span class="dv">10</span><span class="op">;</span></span>
<span id="cb19-48"><a href="#cb19-48" aria-hidden="true" tabindex="-1"></a>            parsed <span class="op">+=</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">-</span> <span class="ch">&#39;0&#39;</span><span class="op">;</span></span>
<span id="cb19-49"><a href="#cb19-49" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb19-50"><a href="#cb19-50" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb19-51"><a href="#cb19-51" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-52"><a href="#cb19-52" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> ParseNaturalNumberResult result <span class="op">=</span> <span class="op">{</span></span>
<span id="cb19-53"><a href="#cb19-53" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>kind <span class="op">=</span> PARSE_NATURAL_SUCCESS<span class="op">,</span></span>
<span id="cb19-54"><a href="#cb19-54" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>data <span class="op">=</span> <span class="op">{</span></span>
<span id="cb19-55"><a href="#cb19-55" aria-hidden="true" tabindex="-1"></a>                    <span class="op">.</span>success <span class="op">=</span> parsed</span>
<span id="cb19-56"><a href="#cb19-56" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb19-57"><a href="#cb19-57" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb19-58"><a href="#cb19-58" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-59"><a href="#cb19-59" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> result<span class="op">;</span></span>
<span id="cb19-60"><a href="#cb19-60" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb19-61"><a href="#cb19-61" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-62"><a href="#cb19-62" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb19-63"><a href="#cb19-63" aria-hidden="true" tabindex="-1"></a>    <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> examples<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span> <span class="st">&quot;10&quot;</span><span class="op">,</span> <span class="st">&quot;foo&quot;</span><span class="op">,</span> <span class="st">&quot;42&quot;</span><span class="op">,</span> <span class="st">&quot;12a34&quot;</span> <span class="op">};</span></span>
<span id="cb19-64"><a href="#cb19-64" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">4</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb19-65"><a href="#cb19-65" aria-hidden="true" tabindex="-1"></a>        <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> example <span class="op">=</span> examples<span class="op">[</span>i<span class="op">];</span></span>
<span id="cb19-66"><a href="#cb19-66" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-67"><a href="#cb19-67" aria-hidden="true" tabindex="-1"></a>        <span class="kw">struct</span> ParseNaturalNumberResult result <span class="op">=</span> </span>
<span id="cb19-68"><a href="#cb19-68" aria-hidden="true" tabindex="-1"></a>            parse_natural_base_10_number<span class="op">(</span>example<span class="op">);</span></span>
<span id="cb19-69"><a href="#cb19-69" aria-hidden="true" tabindex="-1"></a>        <span class="cf">switch</span> <span class="op">(</span>result<span class="op">.</span>kind<span class="op">)</span> <span class="op">{</span></span>
<span id="cb19-70"><a href="#cb19-70" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> PARSE_NATURAL_SUCCESS<span class="op">:</span></span>
<span id="cb19-71"><a href="#cb19-71" aria-hidden="true" tabindex="-1"></a>                printf<span class="op">(</span><span class="st">&quot;worked: %d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> result<span class="op">.</span>data<span class="op">.</span>success<span class="op">);</span></span>
<span id="cb19-72"><a href="#cb19-72" aria-hidden="true" tabindex="-1"></a>                <span class="cf">break</span><span class="op">;</span></span>
<span id="cb19-73"><a href="#cb19-73" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> PARSE_NATURAL_EMPTY_STRING<span class="op">:</span></span>
<span id="cb19-74"><a href="#cb19-74" aria-hidden="true" tabindex="-1"></a>                printf<span class="op">(</span><span class="st">&quot;got empty string&quot;</span><span class="op">);</span></span>
<span id="cb19-75"><a href="#cb19-75" aria-hidden="true" tabindex="-1"></a>                <span class="cf">break</span><span class="op">;</span></span>
<span id="cb19-76"><a href="#cb19-76" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> PARSE_NATURAL_BAD_CHARACTER<span class="op">:</span></span>
<span id="cb19-77"><a href="#cb19-77" aria-hidden="true" tabindex="-1"></a>                printf<span class="op">(</span><span class="st">&quot;failed: %s</span><span class="sc">\n</span><span class="st">        &quot;</span><span class="op">,</span> example<span class="op">);</span></span>
<span id="cb19-78"><a href="#cb19-78" aria-hidden="true" tabindex="-1"></a>                <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> j <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> </span>
<span id="cb19-79"><a href="#cb19-79" aria-hidden="true" tabindex="-1"></a>                     j <span class="op">&lt;</span> result<span class="op">.</span>data<span class="op">.</span>bad_character<span class="op">.</span>index<span class="op">;</span> </span>
<span id="cb19-80"><a href="#cb19-80" aria-hidden="true" tabindex="-1"></a>                     j<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb19-81"><a href="#cb19-81" aria-hidden="true" tabindex="-1"></a>                    printf<span class="op">(</span><span class="st">&quot; &quot;</span><span class="op">);</span></span>
<span id="cb19-82"><a href="#cb19-82" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb19-83"><a href="#cb19-83" aria-hidden="true" tabindex="-1"></a>                printf<span class="op">(</span></span>
<span id="cb19-84"><a href="#cb19-84" aria-hidden="true" tabindex="-1"></a>                    <span class="st">&quot;^☹️ &#39;%c&#39; is not good</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> </span>
<span id="cb19-85"><a href="#cb19-85" aria-hidden="true" tabindex="-1"></a>                    result<span class="op">.</span>data<span class="op">.</span>bad_character<span class="op">.</span>c</span>
<span id="cb19-86"><a href="#cb19-86" aria-hidden="true" tabindex="-1"></a>                <span class="op">);</span></span>
<span id="cb19-87"><a href="#cb19-87" aria-hidden="true" tabindex="-1"></a>                <span class="cf">break</span><span class="op">;</span></span>
<span id="cb19-88"><a href="#cb19-88" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb19-89"><a href="#cb19-89" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-90"><a href="#cb19-90" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb19-91"><a href="#cb19-91" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-92"><a href="#cb19-92" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb19-93"><a href="#cb19-93" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb20"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="an">worked:</span><span class="co"> 10</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a><span class="an">failed:</span><span class="co"> foo</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a><span class="co">        ^☹️ &#39;f&#39; is not good</span></span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a><span class="an">worked:</span><span class="co"> 42</span></span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a><span class="an">failed:</span><span class="co"> 12a34</span></span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a><span class="co">          ^☹️ &#39;a&#39; is not good</span></span></code></pre></div>
<p>This is a very common pattern, especially when writing programs like language parsers where it is hard to avoid functions which can return one of many differently shaped possibilities. There are some examples <a href="https://github.com/curl/curl/blob/master/lib/ftplistparser.c">here in the curl codebase</a> of using the general mechanism for the result of parsing.</p>
<h2 id="11-return-a-boxed-error-object">11. Return a boxed "error object"</h2>
<p>The last one here is probably the toughest sell. It is more verbose than the other approaches, requires heap allocation, and requires a non-trivial degree of comfortableness in C. It does have its perks though.</p>
<p>First, make a <a href="https://en.wikipedia.org/wiki/Virtual_method_table#:~:text=A%20virtual%20method%20table%20(VMT,run%2Dtime%20method%20binding).">"vtable"</a>. This will be a struct containing pointers to functions which take as their first argument a void pointer.</p>
<p>For errors, lets say the things we will want to do are <a href="https://go.dev/blog/error-handling-and-go">produce an error message</a> and dispose of any allocated resources afterward.</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> ErrorOps <span class="op">{</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span><span class="op">*</span> <span class="op">(*</span>describe<span class="op">)(</span><span class="dt">const</span> <span class="dt">void</span><span class="op">*);</span></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="op">(*</span>free<span class="op">)(</span><span class="dt">void</span><span class="op">*);</span></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span></code></pre></div>
<p>Then make a struct which contains this <a href="https://en.wikipedia.org/wiki/Virtual_method_table#:~:text=A%20virtual%20method%20table%20(VMT,run%2Dtime%20method%20binding).">vtable</a> as well as a pointer to the memory that is meant to be passed as the first argument to each function within.</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Error <span class="op">{</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> ErrorOps ops<span class="op">;</span></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span><span class="op">*</span> self<span class="op">;</span></span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span></code></pre></div>
<p>You can then make some helpers for doing the calling.</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="dt">char</span><span class="op">*</span> error_describe<span class="op">(</span><span class="kw">struct</span> Error error<span class="op">)</span> <span class="op">{</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> error<span class="op">.</span>ops<span class="op">.</span>describe<span class="op">(</span>error<span class="op">.</span>self<span class="op">);</span></span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> error_free<span class="op">(</span><span class="kw">struct</span> Error error<span class="op">)</span> <span class="op">{</span></span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>error<span class="op">.</span>ops<span class="op">.</span>free <span class="op">!=</span> NULL<span class="op">)</span> <span class="op">{</span></span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a>        error<span class="op">.</span>ops<span class="op">.</span>free<span class="op">(</span>error<span class="op">.</span>self<span class="op">);</span></span>
<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb23-9"><a href="#cb23-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Then for each error condition, define how each operation should work as well as any helper functions and structs that you need.</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="dt">char</span><span class="op">*</span> empty_string_describe<span class="op">(</span><span class="dt">const</span> <span class="dt">void</span><span class="op">*</span> self<span class="op">)</span> <span class="op">{</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span><span class="op">*</span> result<span class="op">;</span></span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>    asprintf<span class="op">(&amp;</span>result<span class="op">,</span> <span class="st">&quot;Empty string is not good&quot;</span><span class="op">);</span></span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> result<span class="op">;</span></span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a><span class="dt">const</span> <span class="kw">struct</span> ErrorOps empty_string_error_ops <span class="op">=</span> <span class="op">{</span></span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>describe <span class="op">=</span> empty_string_describe<span class="op">,</span></span>
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>free <span class="op">=</span> NULL</span>
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb24-11"><a href="#cb24-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-12"><a href="#cb24-12" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Error empty_string_error<span class="op">()</span> <span class="op">{</span></span>
<span id="cb24-13"><a href="#cb24-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> Error result <span class="op">=</span> <span class="op">{</span></span>
<span id="cb24-14"><a href="#cb24-14" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>ops <span class="op">=</span> empty_string_error_ops<span class="op">,</span></span>
<span id="cb24-15"><a href="#cb24-15" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>self <span class="op">=</span> NULL</span>
<span id="cb24-16"><a href="#cb24-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb24-17"><a href="#cb24-17" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> result<span class="op">;</span></span>
<span id="cb24-18"><a href="#cb24-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb25"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> BadCharacterError <span class="op">{</span></span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span><span class="op">*</span> source<span class="op">;</span></span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">size_t</span> index<span class="op">;</span></span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a><span class="dt">char</span><span class="op">*</span> bad_character_describe<span class="op">(</span><span class="dt">const</span> <span class="dt">void</span><span class="op">*</span> self<span class="op">)</span> <span class="op">{</span></span>
<span id="cb25-7"><a href="#cb25-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">const</span> <span class="kw">struct</span> BadCharacterError<span class="op">*</span> this <span class="op">=</span> self<span class="op">;</span></span>
<span id="cb25-8"><a href="#cb25-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span><span class="op">*</span> result<span class="op">;</span></span>
<span id="cb25-9"><a href="#cb25-9" aria-hidden="true" tabindex="-1"></a>    asprintf<span class="op">(</span></span>
<span id="cb25-10"><a href="#cb25-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">&amp;</span>result<span class="op">,</span> </span>
<span id="cb25-11"><a href="#cb25-11" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;Bad character in %s at index %zu: &#39;%c&#39;&quot;</span><span class="op">,</span> </span>
<span id="cb25-12"><a href="#cb25-12" aria-hidden="true" tabindex="-1"></a>        this<span class="op">-&gt;</span>source<span class="op">,</span> </span>
<span id="cb25-13"><a href="#cb25-13" aria-hidden="true" tabindex="-1"></a>        this<span class="op">-&gt;</span>index<span class="op">,</span> </span>
<span id="cb25-14"><a href="#cb25-14" aria-hidden="true" tabindex="-1"></a>        this<span class="op">-&gt;</span>source<span class="op">[</span>this<span class="op">-&gt;</span>index<span class="op">]</span></span>
<span id="cb25-15"><a href="#cb25-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">);</span></span>
<span id="cb25-16"><a href="#cb25-16" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> result<span class="op">;</span></span>
<span id="cb25-17"><a href="#cb25-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb25-18"><a href="#cb25-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-19"><a href="#cb25-19" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> bad_character_free<span class="op">(</span><span class="dt">void</span><span class="op">*</span> self<span class="op">)</span> <span class="op">{</span></span>
<span id="cb25-20"><a href="#cb25-20" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> BadCharacterError<span class="op">*</span> this <span class="op">=</span> self<span class="op">;</span></span>
<span id="cb25-21"><a href="#cb25-21" aria-hidden="true" tabindex="-1"></a>    free<span class="op">(</span>this<span class="op">-&gt;</span>source<span class="op">);</span></span>
<span id="cb25-22"><a href="#cb25-22" aria-hidden="true" tabindex="-1"></a>    free<span class="op">(</span>this<span class="op">);</span></span>
<span id="cb25-23"><a href="#cb25-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb25-24"><a href="#cb25-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-25"><a href="#cb25-25" aria-hidden="true" tabindex="-1"></a><span class="dt">const</span> <span class="kw">struct</span> ErrorOps bad_character_error_ops <span class="op">=</span> <span class="op">{</span></span>
<span id="cb25-26"><a href="#cb25-26" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>describe <span class="op">=</span> bad_character_describe<span class="op">,</span></span>
<span id="cb25-27"><a href="#cb25-27" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>free <span class="op">=</span> bad_character_free</span>
<span id="cb25-28"><a href="#cb25-28" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb25-29"><a href="#cb25-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-30"><a href="#cb25-30" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Error bad_character_error<span class="op">(</span><span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> source<span class="op">,</span> <span class="dt">size_t</span> index<span class="op">)</span> <span class="op">{</span></span>
<span id="cb25-31"><a href="#cb25-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> BadCharacterError<span class="op">*</span> error <span class="op">=</span> </span>
<span id="cb25-32"><a href="#cb25-32" aria-hidden="true" tabindex="-1"></a>        malloc<span class="op">(</span><span class="kw">sizeof</span> <span class="op">(</span><span class="kw">struct</span> BadCharacterError<span class="op">));</span></span>
<span id="cb25-33"><a href="#cb25-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-34"><a href="#cb25-34" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span><span class="op">*</span> source_clone <span class="op">=</span> calloc<span class="op">(</span>strlen<span class="op">(</span>source<span class="op">)</span> <span class="op">+</span> <span class="dv">1</span><span class="op">,</span> <span class="kw">sizeof</span> <span class="op">(</span><span class="dt">char</span><span class="op">));</span></span>
<span id="cb25-35"><a href="#cb25-35" aria-hidden="true" tabindex="-1"></a>    strcpy<span class="op">(</span>source_clone<span class="op">,</span> source<span class="op">);</span></span>
<span id="cb25-36"><a href="#cb25-36" aria-hidden="true" tabindex="-1"></a>    error<span class="op">-&gt;</span>source <span class="op">=</span> source_clone<span class="op">;</span></span>
<span id="cb25-37"><a href="#cb25-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-38"><a href="#cb25-38" aria-hidden="true" tabindex="-1"></a>    error<span class="op">-&gt;</span>index <span class="op">=</span> index<span class="op">;</span></span>
<span id="cb25-39"><a href="#cb25-39" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-40"><a href="#cb25-40" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> Error result <span class="op">=</span> <span class="op">{</span></span>
<span id="cb25-41"><a href="#cb25-41" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>ops <span class="op">=</span> bad_character_error_ops<span class="op">,</span></span>
<span id="cb25-42"><a href="#cb25-42" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>self <span class="op">=</span> error</span>
<span id="cb25-43"><a href="#cb25-43" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb25-44"><a href="#cb25-44" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> result<span class="op">;</span></span>
<span id="cb25-45"><a href="#cb25-45" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Then, by any of the previous schemes, return one of these error structs if something goes wrong.</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> ParseNaturalNumberResult <span class="op">{</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">bool</span> success<span class="op">;</span></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">union</span> <span class="op">{</span></span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> success<span class="op">;</span></span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">struct</span> Error error<span class="op">;</span></span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> data<span class="op">;</span></span>
<span id="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb26-8"><a href="#cb26-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-9"><a href="#cb26-9" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> ParseNaturalNumberResult parse_natural_base_10_number<span class="op">(</span></span>
<span id="cb26-10"><a href="#cb26-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> s</span>
<span id="cb26-11"><a href="#cb26-11" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb26-12"><a href="#cb26-12" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>s<span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">==</span> <span class="ch">&#39;\0&#39;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb26-13"><a href="#cb26-13" aria-hidden="true" tabindex="-1"></a>        <span class="kw">struct</span> ParseNaturalNumberResult result <span class="op">=</span> <span class="op">{</span></span>
<span id="cb26-14"><a href="#cb26-14" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span>success <span class="op">=</span> false<span class="op">,</span></span>
<span id="cb26-15"><a href="#cb26-15" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span>data <span class="op">=</span> <span class="op">{</span></span>
<span id="cb26-16"><a href="#cb26-16" aria-hidden="true" tabindex="-1"></a>                        <span class="op">.</span>error <span class="op">=</span> empty_string_error<span class="op">()</span></span>
<span id="cb26-17"><a href="#cb26-17" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb26-18"><a href="#cb26-18" aria-hidden="true" tabindex="-1"></a>        <span class="op">};</span></span>
<span id="cb26-19"><a href="#cb26-19" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> result<span class="op">;</span></span>
<span id="cb26-20"><a href="#cb26-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb26-21"><a href="#cb26-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-22"><a href="#cb26-22" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> parsed <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb26-23"><a href="#cb26-23" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">!=</span> <span class="ch">&#39;\0&#39;</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb26-24"><a href="#cb26-24" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>s<span class="op">[</span>i<span class="op">]</span> <span class="op">&lt;</span> <span class="ch">&#39;0&#39;</span> <span class="op">||</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">&gt;</span> <span class="ch">&#39;9&#39;</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb26-25"><a href="#cb26-25" aria-hidden="true" tabindex="-1"></a>            <span class="kw">struct</span> ParseNaturalNumberResult result <span class="op">=</span> <span class="op">{</span></span>
<span id="cb26-26"><a href="#cb26-26" aria-hidden="true" tabindex="-1"></a>                    <span class="op">.</span>success <span class="op">=</span> false<span class="op">,</span></span>
<span id="cb26-27"><a href="#cb26-27" aria-hidden="true" tabindex="-1"></a>                    <span class="op">.</span>data <span class="op">=</span> <span class="op">{</span></span>
<span id="cb26-28"><a href="#cb26-28" aria-hidden="true" tabindex="-1"></a>                            <span class="op">.</span>error <span class="op">=</span> bad_character_error<span class="op">(</span>s<span class="op">,</span> i<span class="op">)</span></span>
<span id="cb26-29"><a href="#cb26-29" aria-hidden="true" tabindex="-1"></a>                    <span class="op">}</span></span>
<span id="cb26-30"><a href="#cb26-30" aria-hidden="true" tabindex="-1"></a>            <span class="op">};</span></span>
<span id="cb26-31"><a href="#cb26-31" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> result<span class="op">;</span></span>
<span id="cb26-32"><a href="#cb26-32" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb26-33"><a href="#cb26-33" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb26-34"><a href="#cb26-34" aria-hidden="true" tabindex="-1"></a>            parsed <span class="op">*=</span> <span class="dv">10</span><span class="op">;</span></span>
<span id="cb26-35"><a href="#cb26-35" aria-hidden="true" tabindex="-1"></a>            parsed <span class="op">+=</span> s<span class="op">[</span>i<span class="op">]</span> <span class="op">-</span> <span class="ch">&#39;0&#39;</span><span class="op">;</span></span>
<span id="cb26-36"><a href="#cb26-36" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb26-37"><a href="#cb26-37" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb26-38"><a href="#cb26-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-39"><a href="#cb26-39" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> ParseNaturalNumberResult result <span class="op">=</span> <span class="op">{</span></span>
<span id="cb26-40"><a href="#cb26-40" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>success <span class="op">=</span> true<span class="op">,</span></span>
<span id="cb26-41"><a href="#cb26-41" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>data <span class="op">=</span> <span class="op">{</span></span>
<span id="cb26-42"><a href="#cb26-42" aria-hidden="true" tabindex="-1"></a>                    <span class="op">.</span>success <span class="op">=</span> parsed</span>
<span id="cb26-43"><a href="#cb26-43" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb26-44"><a href="#cb26-44" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb26-45"><a href="#cb26-45" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-46"><a href="#cb26-46" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> result<span class="op">;</span></span>
<span id="cb26-47"><a href="#cb26-47" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb26-48"><a href="#cb26-48" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-49"><a href="#cb26-49" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb26-50"><a href="#cb26-50" aria-hidden="true" tabindex="-1"></a>    <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> examples<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span> <span class="st">&quot;10&quot;</span><span class="op">,</span> <span class="st">&quot;foo&quot;</span><span class="op">,</span> <span class="st">&quot;42&quot;</span><span class="op">,</span> <span class="st">&quot;12a34&quot;</span> <span class="op">};</span></span>
<span id="cb26-51"><a href="#cb26-51" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">4</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb26-52"><a href="#cb26-52" aria-hidden="true" tabindex="-1"></a>        <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> example <span class="op">=</span> examples<span class="op">[</span>i<span class="op">];</span></span>
<span id="cb26-53"><a href="#cb26-53" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-54"><a href="#cb26-54" aria-hidden="true" tabindex="-1"></a>        <span class="kw">struct</span> ParseNaturalNumberResult result <span class="op">=</span> </span>
<span id="cb26-55"><a href="#cb26-55" aria-hidden="true" tabindex="-1"></a>            parse_natural_base_10_number<span class="op">(</span>example<span class="op">);</span></span>
<span id="cb26-56"><a href="#cb26-56" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(!</span>result<span class="op">.</span>success<span class="op">)</span> <span class="op">{</span></span>
<span id="cb26-57"><a href="#cb26-57" aria-hidden="true" tabindex="-1"></a>            <span class="dt">char</span><span class="op">*</span> description <span class="op">=</span> error_describe<span class="op">(</span>result<span class="op">.</span>data<span class="op">.</span>error<span class="op">);</span></span>
<span id="cb26-58"><a href="#cb26-58" aria-hidden="true" tabindex="-1"></a>            printf<span class="op">(</span><span class="st">&quot;error: %s</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> description<span class="op">);</span></span>
<span id="cb26-59"><a href="#cb26-59" aria-hidden="true" tabindex="-1"></a>            free<span class="op">(</span>description<span class="op">);</span></span>
<span id="cb26-60"><a href="#cb26-60" aria-hidden="true" tabindex="-1"></a>            error_free<span class="op">(</span>result<span class="op">.</span>data<span class="op">.</span>error<span class="op">);</span></span>
<span id="cb26-61"><a href="#cb26-61" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb26-62"><a href="#cb26-62" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb26-63"><a href="#cb26-63" aria-hidden="true" tabindex="-1"></a>            printf<span class="op">(</span><span class="st">&quot;success: %d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> result<span class="op">.</span>data<span class="op">.</span>success<span class="op">);</span></span>
<span id="cb26-64"><a href="#cb26-64" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb26-65"><a href="#cb26-65" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb26-66"><a href="#cb26-66" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-67"><a href="#cb26-67" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb26-68"><a href="#cb26-68" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb27"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="an">success:</span><span class="co"> 10</span></span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a><span class="an">error:</span><span class="co"> Bad character in foo at index 0: &#39;f&#39;</span></span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a><span class="an">success:</span><span class="co"> 42</span></span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a><span class="an">error:</span><span class="co"> Bad character in 12a34 at index 2: &#39;a&#39;</span></span></code></pre></div>
<p>So... why do this?</p>
<p><a href="https://www.youtube.com/watch?v=idYERhOsw54"><img src="/pages/7-27-22-crystals.png" alt="Crystals!"></img></a></p>
<p>Because it is easy to compose this kind of error.</p>
<p>Say we extended our problem such that we were reading a number from a file. Now the set of things that can go wrong includes all sorts of file reading related errors.</p>
<p>It is a lot easier to include those errors if there is a way to treat them the "same" as the ones encountered during parsing. This accomplishes that.</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> FileOperationError <span class="op">{</span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> error_number<span class="op">;</span></span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a><span class="dt">char</span><span class="op">*</span> file_operation_error_describe<span class="op">(</span><span class="dt">const</span> <span class="dt">void</span><span class="op">*</span> self<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">const</span> <span class="kw">struct</span> FileOperationError<span class="op">*</span> this <span class="op">=</span> self<span class="op">;</span></span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span><span class="op">*</span> result<span class="op">;</span></span>
<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a>    asprintf<span class="op">(&amp;</span>result<span class="op">,</span> <span class="st">&quot;%s&quot;</span><span class="op">,</span> strerror<span class="op">(</span>this<span class="op">-&gt;</span>error_number<span class="op">));</span></span>
<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> result<span class="op">;</span></span>
<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb28-11"><a href="#cb28-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-12"><a href="#cb28-12" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> file_operation_error_free<span class="op">(</span><span class="dt">void</span><span class="op">*</span> self<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-13"><a href="#cb28-13" aria-hidden="true" tabindex="-1"></a>    free<span class="op">(</span>self<span class="op">);</span></span>
<span id="cb28-14"><a href="#cb28-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb28-15"><a href="#cb28-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-16"><a href="#cb28-16" aria-hidden="true" tabindex="-1"></a><span class="dt">const</span> <span class="kw">struct</span> ErrorOps file_operation_error_ops <span class="op">=</span> <span class="op">{</span></span>
<span id="cb28-17"><a href="#cb28-17" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>describe <span class="op">=</span> file_operation_error_describe<span class="op">,</span></span>
<span id="cb28-18"><a href="#cb28-18" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>free <span class="op">=</span> file_operation_error_free</span>
<span id="cb28-19"><a href="#cb28-19" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb28-20"><a href="#cb28-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-21"><a href="#cb28-21" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Error file_operation_error<span class="op">(</span><span class="dt">int</span> error_number<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-22"><a href="#cb28-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> FileOperationError<span class="op">*</span> file_operation_error <span class="op">=</span> </span>
<span id="cb28-23"><a href="#cb28-23" aria-hidden="true" tabindex="-1"></a>        malloc<span class="op">(</span><span class="kw">sizeof</span> <span class="op">(</span><span class="kw">struct</span> FileOperationError<span class="op">));</span></span>
<span id="cb28-24"><a href="#cb28-24" aria-hidden="true" tabindex="-1"></a>    file_operation_error<span class="op">-&gt;</span>error_number <span class="op">=</span> error_number<span class="op">;</span></span>
<span id="cb28-25"><a href="#cb28-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-26"><a href="#cb28-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> Error result <span class="op">=</span> <span class="op">{</span></span>
<span id="cb28-27"><a href="#cb28-27" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>ops <span class="op">=</span> file_operation_error_ops<span class="op">,</span></span>
<span id="cb28-28"><a href="#cb28-28" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>self <span class="op">=</span> file_operation_error</span>
<span id="cb28-29"><a href="#cb28-29" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb28-30"><a href="#cb28-30" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> result<span class="op">;</span></span>
<span id="cb28-31"><a href="#cb28-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb28-32"><a href="#cb28-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-33"><a href="#cb28-33" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> ReadNumberFromFileResult <span class="op">{</span></span>
<span id="cb28-34"><a href="#cb28-34" aria-hidden="true" tabindex="-1"></a>    <span class="dt">bool</span> success<span class="op">;</span></span>
<span id="cb28-35"><a href="#cb28-35" aria-hidden="true" tabindex="-1"></a>    <span class="kw">union</span> <span class="op">{</span></span>
<span id="cb28-36"><a href="#cb28-36" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> success<span class="op">;</span></span>
<span id="cb28-37"><a href="#cb28-37" aria-hidden="true" tabindex="-1"></a>        <span class="kw">struct</span> Error error<span class="op">;</span></span>
<span id="cb28-38"><a href="#cb28-38" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> data<span class="op">;</span></span>
<span id="cb28-39"><a href="#cb28-39" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb28-40"><a href="#cb28-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-41"><a href="#cb28-41" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> ReadNumberFromFileResult read_number_from_file<span class="op">(</span></span>
<span id="cb28-42"><a href="#cb28-42" aria-hidden="true" tabindex="-1"></a>   <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> path</span>
<span id="cb28-43"><a href="#cb28-43" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-44"><a href="#cb28-44" aria-hidden="true" tabindex="-1"></a>    <span class="dt">FILE</span><span class="op">*</span> fp <span class="op">=</span> fopen<span class="op">(</span>path<span class="op">,</span> <span class="st">&quot;r&quot;</span><span class="op">);</span></span>
<span id="cb28-45"><a href="#cb28-45" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>fp <span class="op">==</span> NULL<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-46"><a href="#cb28-46" aria-hidden="true" tabindex="-1"></a>        <span class="kw">struct</span> ReadNumberFromFileResult result <span class="op">=</span> <span class="op">{</span></span>
<span id="cb28-47"><a href="#cb28-47" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span>success <span class="op">=</span> false<span class="op">,</span></span>
<span id="cb28-48"><a href="#cb28-48" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span>data <span class="op">=</span> <span class="op">{</span></span>
<span id="cb28-49"><a href="#cb28-49" aria-hidden="true" tabindex="-1"></a>                        <span class="op">.</span>error <span class="op">=</span> file_operation_error<span class="op">(</span>errno<span class="op">)</span></span>
<span id="cb28-50"><a href="#cb28-50" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb28-51"><a href="#cb28-51" aria-hidden="true" tabindex="-1"></a>        <span class="op">};</span></span>
<span id="cb28-52"><a href="#cb28-52" aria-hidden="true" tabindex="-1"></a>        errno <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb28-53"><a href="#cb28-53" aria-hidden="true" tabindex="-1"></a>        fclose<span class="op">(</span>fp<span class="op">);</span></span>
<span id="cb28-54"><a href="#cb28-54" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> result<span class="op">;</span></span>
<span id="cb28-55"><a href="#cb28-55" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-56"><a href="#cb28-56" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-57"><a href="#cb28-57" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Max positive int is only 10 characters big in base 10</span></span>
<span id="cb28-58"><a href="#cb28-58" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span> first_line<span class="op">[</span><span class="dv">12</span><span class="op">];</span></span>
<span id="cb28-59"><a href="#cb28-59" aria-hidden="true" tabindex="-1"></a>    fgets<span class="op">(</span>first_line<span class="op">,</span> <span class="kw">sizeof</span> <span class="op">(</span>first_line<span class="op">),</span> fp<span class="op">);</span></span>
<span id="cb28-60"><a href="#cb28-60" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-61"><a href="#cb28-61" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>ferror<span class="op">(</span>fp<span class="op">))</span> <span class="op">{</span></span>
<span id="cb28-62"><a href="#cb28-62" aria-hidden="true" tabindex="-1"></a>        <span class="kw">struct</span> ReadNumberFromFileResult result <span class="op">=</span> <span class="op">{</span></span>
<span id="cb28-63"><a href="#cb28-63" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span>success <span class="op">=</span> false<span class="op">,</span></span>
<span id="cb28-64"><a href="#cb28-64" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span>data <span class="op">=</span> <span class="op">{</span></span>
<span id="cb28-65"><a href="#cb28-65" aria-hidden="true" tabindex="-1"></a>                        <span class="op">.</span>error <span class="op">=</span> file_operation_error<span class="op">(</span>errno<span class="op">)</span></span>
<span id="cb28-66"><a href="#cb28-66" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb28-67"><a href="#cb28-67" aria-hidden="true" tabindex="-1"></a>        <span class="op">};</span></span>
<span id="cb28-68"><a href="#cb28-68" aria-hidden="true" tabindex="-1"></a>        errno <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb28-69"><a href="#cb28-69" aria-hidden="true" tabindex="-1"></a>        fclose<span class="op">(</span>fp<span class="op">);</span></span>
<span id="cb28-70"><a href="#cb28-70" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> result<span class="op">;</span></span>
<span id="cb28-71"><a href="#cb28-71" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-72"><a href="#cb28-72" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-73"><a href="#cb28-73" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> ParseNaturalNumberResult parse_result <span class="op">=</span> </span>
<span id="cb28-74"><a href="#cb28-74" aria-hidden="true" tabindex="-1"></a>        parse_natural_base_10_number<span class="op">(</span>first_line<span class="op">);</span></span>
<span id="cb28-75"><a href="#cb28-75" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(!</span>parse_result<span class="op">.</span>success<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-76"><a href="#cb28-76" aria-hidden="true" tabindex="-1"></a>        <span class="kw">struct</span> ReadNumberFromFileResult result <span class="op">=</span> <span class="op">{</span></span>
<span id="cb28-77"><a href="#cb28-77" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span>success <span class="op">=</span> false<span class="op">,</span></span>
<span id="cb28-78"><a href="#cb28-78" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span>data <span class="op">=</span> <span class="op">{</span></span>
<span id="cb28-79"><a href="#cb28-79" aria-hidden="true" tabindex="-1"></a>                        <span class="op">.</span>error <span class="op">=</span> parse_result<span class="op">.</span>data<span class="op">.</span>error</span>
<span id="cb28-80"><a href="#cb28-80" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb28-81"><a href="#cb28-81" aria-hidden="true" tabindex="-1"></a>        <span class="op">};</span></span>
<span id="cb28-82"><a href="#cb28-82" aria-hidden="true" tabindex="-1"></a>        fclose<span class="op">(</span>fp<span class="op">);</span></span>
<span id="cb28-83"><a href="#cb28-83" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> result<span class="op">;</span></span>
<span id="cb28-84"><a href="#cb28-84" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-85"><a href="#cb28-85" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-86"><a href="#cb28-86" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> ReadNumberFromFileResult result <span class="op">=</span> <span class="op">{</span></span>
<span id="cb28-87"><a href="#cb28-87" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>success <span class="op">=</span> true<span class="op">,</span></span>
<span id="cb28-88"><a href="#cb28-88" aria-hidden="true" tabindex="-1"></a>            <span class="op">.</span>data <span class="op">=</span> <span class="op">{</span></span>
<span id="cb28-89"><a href="#cb28-89" aria-hidden="true" tabindex="-1"></a>                    <span class="op">.</span>success <span class="op">=</span> parse_result<span class="op">.</span>data<span class="op">.</span>success</span>
<span id="cb28-90"><a href="#cb28-90" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb28-91"><a href="#cb28-91" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb28-92"><a href="#cb28-92" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-93"><a href="#cb28-93" aria-hidden="true" tabindex="-1"></a>    fclose<span class="op">(</span>fp<span class="op">);</span></span>
<span id="cb28-94"><a href="#cb28-94" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> result<span class="op">;</span></span>
<span id="cb28-95"><a href="#cb28-95" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb28-96"><a href="#cb28-96" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-97"><a href="#cb28-97" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb28-98"><a href="#cb28-98" aria-hidden="true" tabindex="-1"></a>    <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> examples<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span> <span class="st">&quot;../ex1&quot;</span><span class="op">,</span> <span class="st">&quot;../ex2&quot;</span><span class="op">,</span> <span class="st">&quot;../ex3&quot;</span> <span class="op">};</span></span>
<span id="cb28-99"><a href="#cb28-99" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">3</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb28-100"><a href="#cb28-100" aria-hidden="true" tabindex="-1"></a>        <span class="dt">const</span> <span class="dt">char</span><span class="op">*</span> example_file <span class="op">=</span> examples<span class="op">[</span>i<span class="op">];</span></span>
<span id="cb28-101"><a href="#cb28-101" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-102"><a href="#cb28-102" aria-hidden="true" tabindex="-1"></a>        <span class="kw">struct</span> ReadNumberFromFileResult result <span class="op">=</span> </span>
<span id="cb28-103"><a href="#cb28-103" aria-hidden="true" tabindex="-1"></a>            read_number_from_file<span class="op">(</span>example_file<span class="op">);</span></span>
<span id="cb28-104"><a href="#cb28-104" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(!</span>result<span class="op">.</span>success<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-105"><a href="#cb28-105" aria-hidden="true" tabindex="-1"></a>            <span class="dt">char</span><span class="op">*</span> description <span class="op">=</span> error_describe<span class="op">(</span>result<span class="op">.</span>data<span class="op">.</span>error<span class="op">);</span></span>
<span id="cb28-106"><a href="#cb28-106" aria-hidden="true" tabindex="-1"></a>            printf<span class="op">(</span><span class="st">&quot;error: %s</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> description<span class="op">);</span></span>
<span id="cb28-107"><a href="#cb28-107" aria-hidden="true" tabindex="-1"></a>            free<span class="op">(</span>description<span class="op">);</span></span>
<span id="cb28-108"><a href="#cb28-108" aria-hidden="true" tabindex="-1"></a>            error_free<span class="op">(</span>result<span class="op">.</span>data<span class="op">.</span>error<span class="op">);</span></span>
<span id="cb28-109"><a href="#cb28-109" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb28-110"><a href="#cb28-110" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb28-111"><a href="#cb28-111" aria-hidden="true" tabindex="-1"></a>            printf<span class="op">(</span><span class="st">&quot;success: %d</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">,</span> result<span class="op">.</span>data<span class="op">.</span>success<span class="op">);</span></span>
<span id="cb28-112"><a href="#cb28-112" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb28-113"><a href="#cb28-113" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-114"><a href="#cb28-114" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-115"><a href="#cb28-115" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb28-116"><a href="#cb28-116" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb29"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="an">success:</span><span class="co"> 8</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a><span class="an">error:</span><span class="co"> Bad character in abc at index 0: &#39;a&#39;</span></span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a><span class="an">error:</span><span class="co"> No such file or directory</span></span></code></pre></div>
<p>This can all be done with tagged unions as well, so it is a judgement call. This sort of pattern definitely has more appeal when the language being used makes it convenient.</p>
<hr />
<p>Important to note that I am not a professional C programmer. I fully expect to be shown the error of my ways in the comments below.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Publish a Java library to Maven Central without Maven or Gradle</title><link>https://mccue.dev/pages/6-1-22-upload-to-maven-central</link><description></description><pubDate>Wed, 01 Jun 0022 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Publish a Java library to Maven Central without Maven or Gradle</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Publish a Java library to Maven Central without Maven or Gradle</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
Say, like me, you have some code you want to share with the world.

<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span><span class="im"> dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">datastructures</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="co">/**</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a> <span class="co">*</span> <span class="co">&quot;</span>Sum Type<span class="co">&quot;</span> representation of a linked list<span class="co">.</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a> <span class="co">*/</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> sealed <span class="kw">interface</span> <span class="bu">LinkedList</span><span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">/**</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> An empty list<span class="co">.</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>     <span class="co">*/</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>    record Empty<span class="op">&lt;</span>T<span class="op">&gt;()</span> </span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>        <span class="kw">implements</span> <span class="bu">LinkedList</span><span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">{}</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>    <span class="co">/**</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> A not empty list<span class="co">.</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>     <span class="co">*/</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">NotEmpty</span><span class="op">&lt;</span>T<span class="op">&gt;(</span>T first<span class="op">,</span> <span class="bu">LinkedList</span><span class="op">&lt;</span>T<span class="op">&gt;</span> rest<span class="op">)</span> </span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>        <span class="kw">implements</span> <span class="bu">LinkedList</span><span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">{}</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>To do this, you need to put that code in a place others can find it.</p>
<p>For Python programmers this means publishing to <a href="https://pypi.org/">PyPI</a>, Javascript programmers to <a href="https://www.npmjs.com/">npm</a>, Rust programmers to <a href="https://crates.io/">crates.io</a>, and C++ programmers to somewhere I assume.</p>
<p>For Java there are a few options, but the only one that will work by default in every build tool is <a href="https://search.maven.org/">Maven Central</a>. Its apparently really good at <a href="https://github.com/bowbahdoe/magic-bean/issues/8#issuecomment-1023872969">being a repository</a>, so publishing there is the thing to do.</p>
<p>There are plugins for all the major build tools that do this. However, last I tried, <a href="https://issues.sonatype.org/browse/OSSRH-66257">uploading a Java 16+ library to Maven Central using Maven was busted</a> and <a href="https://github.com/bowbahdoe/magic-bean/blob/main/.github/workflows/publish.yml#L27">requires exposing Java internals to work around</a>.</p>
<p>So we are going to do something a little different. I am going to show you how to go through the entire process manually in the hope that it is straightforward enough to write your own scripts to do.</p>
<h2 id="prerequisites-to-follow-along">Prerequisites to follow along</h2>
<h3 id="java">Java</h3>
<div class="sourceCode" id="cb2"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>javac --version</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>jar --version</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>javadoc --version</span></code></pre></div>
<h3 id="gpg">gpg</h3>
<div class="sourceCode" id="cb3"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>gpg --version</span></code></pre></div>
<h3 id="curl">curl</h3>
<div class="sourceCode" id="cb4"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>curl --version</span></code></pre></div>
<h3 id="git">git</h3>
<div class="sourceCode" id="cb5"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>git --version</span></code></pre></div>
<h3 id="github-cli">Github CLI</h3>
<div class="sourceCode" id="cb6"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>gh --version</span></code></pre></div>
<h2 id="step-1-write-your-code">Step 1. Write your code</h2>
<p>For this example I am going to put the linked list code from the top of the page in a file <code>src/dev/mccue/datastructures/LinkedList.java</code> and make a small <code>.gitignore</code>.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>target/</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>.idea/</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>*.iml</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>.DS_Store</span></code></pre></div>
<h2 id="step-2-add-your-code-to-a-git-repo">Step 2. Add your code to a git repo</h2>
<div class="sourceCode" id="cb8"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>git init</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>git add src/</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>git add .gitignore</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>git commit -m &quot;Initial Commit&quot;</span></code></pre></div>
<h2 id="step-3-put-that-git-repo-on-the-internet">Step 3. Put that git repo on the internet</h2>
<p>You will need a public url to refer to later and services like Github are convenient for that.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>gh auth login</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>gh repo create --public --source .</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>git branch -M main</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>git push origin main</span></code></pre></div>
<h2 id="step-4-get-unique-coordinates">Step 4. Get unique coordinates</h2>
<p>Unlike other package repositories, Maven Central requires that you have a unique "group id" to prefix any packages you make. You cannot publish code under <code>com.google</code>, only Google can.</p>
<p>To meet this requirement you either need to</p>
<ul>
<li>Buy a domain name. You can do this through a lot of websites. I personally use <a href="https://www.namecheap.com/">namecheap</a>, but there are quite a few options. Once you do this you can publish code under <code>com.yoursite</code>.</li>
<li>Make an account on one of the git hosting services. This is the easiest way, but you will only be able to publish under <code>io.github.yourusername</code> or similar.</li>
</ul>
<h2 id="step-5-make-an-account-with-sonatype">Step 5. Make an account with Sonatype</h2>
<p>Once you got that all settled</p>
<ol type="1">
<li>Make an account <a href="https://issues.sonatype.org/secure/Signup!default.jspa">here</a>. Save the username and password.</li>
<li>Make a ticket <a href="https://issues.sonatype.org/secure/CreateIssue.jspa?pid=10134&amp;issuetype=21">here</a>. You will need to prove that you own the website or git account that you want to use for your group id.</li>
</ol>
<p>This is an annoying step, I know, but it is what it is. If you get caught here ask in the comments below and I'll add more clarification.</p>
<h2 id="step-6-compile-your-code">Step 6. Compile your code</h2>
<div class="sourceCode" id="cb10"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>javac -d target/classes -g --release 17 src/**/*.java</span></code></pre></div>
<p>The <code>-g</code> includes debug information. Always do that.</p>
<h2 id="step-7-generate-documentation-for-your-code">Step 7. Generate documentation for your code</h2>
<div class="sourceCode" id="cb11"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>javadoc -d target/doc src/**/*.java</span></code></pre></div>
<p>If you get warnings about undocumented classes and methods ignoring them is a choice you are technically allowed to make.</p>
<h2 id="step-8-decide-on-a-version-number">Step 8. Decide on a version number</h2>
<p>When you publish code there is the implicit assumption that you might upload newer versions of that code at a later point in time. To distinguish between versions, you need to number them. There are a few schemes for doing this including <a href="https://semver.org/">Semver</a>, <a href="https://calver.org/">Calver</a>, and <a href="https://0ver.org/">0ver</a>.</p>
<p>In the commands from this point on, I am going to assume that the initial version being published is <code>0.0.1</code>, but you can do what you feel is best.</p>
<h2 id="step-9-zip-your-compiled-code-into-a-jar">Step 9. Zip your compiled code into a jar</h2>
<p>As early minecraft players learned when installing mods, Jar files are just zip files with a few extra bells and whistles.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>mkdir target/deploy</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>jar --create \</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>  --file target/deploy/datastructures-0.0.1.jar \</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>  -C target/classes .</span></code></pre></div>
<h2 id="step-10-zip-your-source-code-into-a-jar">Step 10. Zip your source code into a jar</h2>
<div class="sourceCode" id="cb13"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a>jar --create \</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>  --file target/deploy/datastructures-0.0.1-sources.jar \</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>  -C src .</span></code></pre></div>
<h2 id="step-11-zip-your-documentation-into-a-jar">Step 11. Zip your documentation into a jar</h2>
<div class="sourceCode" id="cb14"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>jar --create \</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>  --file target/deploy/datastructures-0.0.1-javadoc.jar \</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>  -C target/doc .</span></code></pre></div>
<h2 id="step-12-create-a-pom-file">Step 12. Create a POM File</h2>
<p>A POM - "Project Object Model" - file is the standard format for declaring information about your library including any dependencies it may have on other libraries. This format is <a href="https://www.javaadvent.com/2021/12/from-maven-3-to-maven-5.html">going to be around forever</a> and all build tools have to handle it.</p>
<p>The following I am going to put into <code>target/deploy/datastructures-0.0.1.pom</code>. This is the "minimal" POM and <a href="https://central.sonatype.org/publish/requirements/#project-name-description-and-url">every field I list needs to be specified</a>.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode xml"><code class="sourceCode xml"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="fu">&lt;?xml</span><span class="ot"> version=</span><span class="st">&quot;1.0&quot;</span><span class="ot"> encoding=</span><span class="st">&quot;UTF-8&quot;</span><span class="fu">?&gt;</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>&lt;<span class="ot">project</span> <span class="er">xmlns</span><span class="ot">=</span><span class="st">&quot;http://maven.apache.org/POM/4.0.0&quot;</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="ot">         xmlns:xsi=</span><span class="st">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="ot">         xsi:schemaLocation=</span><span class="st">&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&quot;</span>&gt;</span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>    &lt;<span class="ot">modelVersion</span><span class="er">&gt;4.0.0&lt;/modelVersion&gt;</span></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>                </span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;groupId&gt;dev.mccue&lt;/groupId&gt;</span></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;artifactId&gt;datastructures&lt;/artifactId&gt;</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;version&gt;0.0.1&lt;/version&gt;</span></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;packaging&gt;jar&lt;/packaging&gt;</span></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a>                </span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;name&gt;Datastructures&lt;/name&gt;</span></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;description&gt;Basic</span> <span class="er">Datastructures</span> <span class="er">for</span> <span class="er">Java.&lt;/description&gt;</span></span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;url&gt;https://github.com/bowbahdoe/java-datastructures&lt;/url&gt;</span></span>
<span id="cb15-15"><a href="#cb15-15" aria-hidden="true" tabindex="-1"></a>                </span>
<span id="cb15-16"><a href="#cb15-16" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;licenses&gt;</span></span>
<span id="cb15-17"><a href="#cb15-17" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;license&gt;</span></span>
<span id="cb15-18"><a href="#cb15-18" aria-hidden="true" tabindex="-1"></a>            <span class="er">&lt;name&gt;The</span> <span class="er">Apache</span> <span class="er">Software</span> <span class="er">License,</span> <span class="er">Version</span> <span class="er">2.0&lt;/name&gt;</span></span>
<span id="cb15-19"><a href="#cb15-19" aria-hidden="true" tabindex="-1"></a>            <span class="er">&lt;url&gt;http://www.apache.org/licenses/LICENSE-2.0.txt&lt;/url&gt;</span></span>
<span id="cb15-20"><a href="#cb15-20" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;/license&gt;</span></span>
<span id="cb15-21"><a href="#cb15-21" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;/licenses&gt;</span></span>
<span id="cb15-22"><a href="#cb15-22" aria-hidden="true" tabindex="-1"></a>                </span>
<span id="cb15-23"><a href="#cb15-23" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;developers&gt;</span></span>
<span id="cb15-24"><a href="#cb15-24" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;developer&gt;</span></span>
<span id="cb15-25"><a href="#cb15-25" aria-hidden="true" tabindex="-1"></a>            <span class="er">&lt;name&gt;Ethan</span> <span class="er">McCue&lt;/name&gt;</span></span>
<span id="cb15-26"><a href="#cb15-26" aria-hidden="true" tabindex="-1"></a>            <span class="er">&lt;email&gt;ethan@mccue.dev&lt;/email&gt;</span></span>
<span id="cb15-27"><a href="#cb15-27" aria-hidden="true" tabindex="-1"></a>            <span class="er">&lt;organization&gt;McCue</span> <span class="er">Software</span> <span class="er">Solutions&lt;/organization&gt;</span></span>
<span id="cb15-28"><a href="#cb15-28" aria-hidden="true" tabindex="-1"></a>            <span class="er">&lt;organizationUrl&gt;https://www.mccue.dev&lt;/organizationUrl&gt;</span></span>
<span id="cb15-29"><a href="#cb15-29" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;/developer&gt;</span></span>
<span id="cb15-30"><a href="#cb15-30" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;/developers&gt;</span></span>
<span id="cb15-31"><a href="#cb15-31" aria-hidden="true" tabindex="-1"></a>                </span>
<span id="cb15-32"><a href="#cb15-32" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;scm&gt;</span></span>
<span id="cb15-33"><a href="#cb15-33" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;connection&gt;scm:git:git://github.com/bowbahdoe/java-datastructures.git&lt;/connection&gt;</span></span>
<span id="cb15-34"><a href="#cb15-34" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;developerConnection&gt;scm:git:ssh://github.com:bowbahdoe/java-datastructures.git&lt;/developerConnection&gt;</span></span>
<span id="cb15-35"><a href="#cb15-35" aria-hidden="true" tabindex="-1"></a>        <span class="er">&lt;url&gt;https://github.com/bowbahdoe/java-datastructures/tree/main&lt;/url&gt;</span></span>
<span id="cb15-36"><a href="#cb15-36" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;/scm&gt;</span></span>
<span id="cb15-37"><a href="#cb15-37" aria-hidden="true" tabindex="-1"></a><span class="er">&lt;/project&gt;</span></span></code></pre></div>
<h2 id="step-13-create-a-gpg-key">Step 13. Create a GPG Key</h2>
<p>Okay so this part might feel wierd.</p>
<p>The idea here was that you generate a public and private key. You sign all the files you upload with those keys and then later on someone can confirm that it was "you" that actually did that signing.</p>
<p>Maven Central just makes sure that everything is signed, not that there is any way to associate the signed files back to you. Because public key infrastructure never really took off, this step is largely ceremonial in practice. You still need to do it though.</p>
<p><a href="https://central.sonatype.org/publish/requirements/gpg/#generating-a-key-pair">The official guide is more comprehensive than I am going to be</a></p>
<div class="sourceCode" id="cb16"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a>gpg --gen-key</span></code></pre></div>
<p>Make sure to save your passphrase if you made one.</p>
<h2 id="step-14-distribute-your-gpg-key">Step 14. Distribute your GPG Key</h2>
<p>Run this command</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>gpg --list-keys</span></code></pre></div>
<p>And you should get output that kinda looks like this.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a>pub   rsa3072 2021-06-23 <span class="co">[</span><span class="ot">SC</span><span class="co">] [expires: 2023-06-23]</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>      CA925CD6C9E8D064FF05B4728190C4130ABA0F98</span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>uid           <span class="co">[</span><span class="ot">ultimate</span><span class="co">]</span> Central Repo Test <span class="ot">&lt;central@example.com&gt;</span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>sub   rsa3072 2021-06-23 <span class="co">[</span><span class="ot">E</span><span class="co">] [expires: 2023-06-23]</span></span></code></pre></div>
<p>You want to take the part that looks like <code>CA925CD6C9E8D064FF05B4728190C4130ABA0F98</code> and run the following command.</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>gpg --keyserver keyserver.ubuntu.com \</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>  --send-keys CA925CD6C9E8D064FF05B4728190C4130ABA0F98</span></code></pre></div>
<h2 id="step-15-sign-all-the-files-with-gpg">Step 15. Sign all the files with GPG</h2>
<div class="sourceCode" id="cb20"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a>gpg --armor --detach-sign target/deploy/datastructures-0.0.1.jar</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>gpg --armor --detach-sign target/deploy/datastructures-0.0.1-sources.jar</span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>gpg --armor --detach-sign target/deploy/datastructures-0.0.1-javadoc.jar</span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>gpg --armor --detach-sign target/deploy/datastructures-0.0.1.pom</span></code></pre></div>
<p>If you are scripting this you should add <code>--pinentry-mode loopback</code> and provide your passphrase via <code>--passphrase</code>.</p>
<h2 id="step-16-zip-all-the-jars-into-one-large-jar">Step 16. Zip all the jars into one large jar</h2>
<p>Yes, we are making a jar jar.</p>
<p><img src="/pages/6-1-22-jarjar.webp" alt="Jar Jar Binks"></img></p>
<p>The most convenient api for uploading code manually is a <a href="https://central.sonatype.org/publish/publish-manual/">form submit on the gui</a> that is undocumented. I wanted to use something more official, but I had trouble <a href="https://grep.app/search?q=ProjectDeployerRequest">finding what to do</a>. I think its probably fine.</p>
<p>Said api wants one large jar as its input.</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>jar --create --file target/bundle.jar -C target/deploy .</span></code></pre></div>
<h2 id="step-17-log-in-to-sonatype">Step 17. Log in to sonatype</h2>
<p>Use the username and password you got from step 5.</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a>curl --request GET \</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>  --url https://s01.oss.sonatype.org/service/local/authentication/login \</span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>  --cookie-jar cookies.txt \</span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>  --user USERNAME:PASSWORD</span></code></pre></div>
<h2 id="step-18-upload-the-bundle-to-a-staging-repository">Step 18. Upload the bundle to a staging repository</h2>
<div class="sourceCode" id="cb23"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a>curl --request POST \</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>  --url https://s01.oss.sonatype.org/service/local/staging/bundle_upload \</span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>  --cookie cookies.txt \</span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>  --header &#39;Content-Type: multipart/form-data&#39; \</span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a>  --form file=@target/bundle.jar</span></code></pre></div>
<p>When you run this command, you will get output back that looks like this</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span><span class="dt">&quot;repositoryUris&quot;</span><span class="fu">:</span><span class="ot">[</span><span class="st">&quot;https://s01.oss.sonatype.org/content/repositories/STAGING_REPOSITORY_ID&quot;</span><span class="ot">]</span><span class="fu">}</span></span></code></pre></div>
<p>At this point, you can pause and point a build tool to the staging repository to make sure that everything is okay with your code before releasing the final version.</p>
<h2 id="step-19-release-the-staging-repository">Step 19. Release the staging repository</h2>
<p>Fill in the <code>STAGING_REPOSITORY_ID</code> from the output of the last command. There is no going back once the staging repostory is released.</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a>curl --request POST \</span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a>  --url https://s01.oss.sonatype.org/service/local/staging/bulk/promote \</span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a>  --cookie cookies.txt \</span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a>  --header &#39;Content-Type: application/json&#39; \</span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a>  --data &#39;{ </span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a>    &quot;data&quot;: {</span>
<span id="cb25-7"><a href="#cb25-7" aria-hidden="true" tabindex="-1"></a>        &quot;autoDropAfterRelease&quot;: true,</span>
<span id="cb25-8"><a href="#cb25-8" aria-hidden="true" tabindex="-1"></a>        &quot;description&quot;: &quot;&quot;,</span>
<span id="cb25-9"><a href="#cb25-9" aria-hidden="true" tabindex="-1"></a>        &quot;stagedRepositoryIds&quot;: <span class="co">[</span><span class="ot">&quot;STAGING_REPOSITORY_ID&quot;</span><span class="co">]</span></span>
<span id="cb25-10"><a href="#cb25-10" aria-hidden="true" tabindex="-1"></a>    }</span>
<span id="cb25-11"><a href="#cb25-11" aria-hidden="true" tabindex="-1"></a>}&#39;</span></code></pre></div>
<hr />
<p>You can try out the linked list we just published by including it in your build tool of choice.</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode xml"><code class="sourceCode xml"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a>&lt;<span class="ot">dependency</span><span class="er">&gt;</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;groupId&gt;dev.mccue&lt;/groupId&gt;</span></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;artifactId&gt;datastructures&lt;/artifactId&gt;</span></span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a>    <span class="er">&lt;version&gt;0.0.1&lt;/version&gt;</span></span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a><span class="er">&lt;/dependency&gt;</span></span></code></pre></div>
<p>A fully scripted version of this process can be seen <a href="https://github.com/bowbahdoe/java-async-utils/blob/main/build/Build.java">here</a> along with <a href="https://github.com/bowbahdoe/java-async-utils/blob/main/.github/workflows/publish.yml">an associated Github workflow</a></p>
<p>Explain what a Maven MOJO is in 140 characters or less in the comments below.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Why is it that byteArrMap.remove is returning false</title><link>https://mccue.dev/pages/5-14-22-byte-arr-map-returning-false</link><description></description><pubDate>Sat, 14 May 0022 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Why is it that byteArrMap.remove is returning false</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Why is it that byteArrMap.remove is returning false</h1>
</header>
<h2 id="question-from-theuntamed0001481">Question from theuntamed000#1481</h2>
<blockquote>
<p>noob question why is that byteArrMap.remove returning false</p>
<p><img src="/pages/5-14-22-shell-1.png" alt="JShell Session Screenshot 1" ></img> <img src="/pages/5-14-22-shell-2.png" alt="JShell Session Screenshot 2" ></img></p>
<p>also does java use something like Integer.valueOf() while doing boxing</p>
</blockquote>
<p>aight so first one</p>
<p>when you call remove with a byte array those byte arrays are not equal</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>jshell<span class="op">&gt;</span> <span class="dt">byte</span><span class="op">[]</span> b1 <span class="op">=</span> <span class="kw">new</span> <span class="dt">byte</span><span class="op">[</span><span class="dv">0</span><span class="op">];</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>b1 <span class="op">==&gt;</span> <span class="dt">byte</span><span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">{</span>  <span class="op">}</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>jshell<span class="op">&gt;</span> <span class="dt">byte</span><span class="op">[]</span> b2 <span class="op">=</span> <span class="kw">new</span> <span class="dt">byte</span><span class="op">[</span><span class="dv">0</span><span class="op">];</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>b2 <span class="op">==&gt;</span> <span class="dt">byte</span><span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">{</span>  <span class="op">}</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>jshell<span class="op">&gt;</span> b1 <span class="op">==</span> b2</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>$<span class="dv">3</span> <span class="op">==&gt;</span> <span class="kw">false</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>jshell<span class="op">&gt;</span> b1<span class="op">.</span><span class="fu">equals</span><span class="op">(</span>b2<span class="op">)</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>$<span class="dv">4</span> <span class="op">==&gt;</span> <span class="kw">false</span></span></code></pre></div>
<p>even though they have the same contents</p>
<blockquote>
<p>just read the docs , it uses Object.equals which uses references</p>
</blockquote>
<p>So it won't find a matching key, thus it won't remove anything returning false.</p>
<p>Second, <code>new Integer(123)</code> and <code>Integer.valueOf(123</code>) might seem identical, but <code>new Integer</code> is a constructor call and all constructor calls need to return distinct objects.</p>
<p>Static methods don't have that restriction, so you can implement some degree of caching behind them. Which, looking at the implementation of <code>Integer.valueOf</code> is what is being done. Small numbers' Integer representations are cached.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>    <span class="at">@IntrinsicCandidate</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="bu">Integer</span> <span class="fu">valueOf</span><span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> i <span class="op">&gt;=</span> <span class="op">-</span><span class="dv">128</span> <span class="op">&amp;&amp;</span> i <span class="op">&lt;=</span> <span class="bu">Integer</span><span class="op">.</span><span class="fu">IntegerCache</span><span class="op">.</span><span class="fu">high</span> <span class="op">?</span> <span class="bu">Integer</span><span class="op">.</span><span class="fu">IntegerCache</span><span class="op">.</span><span class="fu">cache</span><span class="op">[</span>i <span class="op">+</span> <span class="dv">128</span><span class="op">]</span> <span class="op">:</span> <span class="kw">new</span> <span class="bu">Integer</span><span class="op">(</span>i<span class="op">);</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span></code></pre></div>
<p>But the exact strategy matters less than the fact that choosing to implement a strategy is possible with the "static factory."</p>
<p>Even if the implementation was just</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>    <span class="at">@IntrinsicCandidate</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="bu">Integer</span> <span class="fu">valueOf</span><span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="bu">Integer</span><span class="op">(</span>i<span class="op">);</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span></code></pre></div>
<p>there would be a value in it from a library design standpoint.</p>
<p>And that is why this deprecated for removal makes sense. Removing the ability for libraries to call the constructor directly means the jdk would simply have more options for optimizations.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Deprecated</span><span class="op">(</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>        since <span class="op">=</span> <span class="st">&quot;9&quot;</span><span class="op">,</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>        forRemoval <span class="op">=</span> <span class="kw">true</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">Integer</span><span class="op">(</span><span class="dt">int</span> value<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">value</span> <span class="op">=</span> value<span class="op">;</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span></code></pre></div>
<p>And when the language does autoboxing - yes it uses valueOf</p>
<pre class="shell"><code>$ cat Box.java
class Box {
    Integer f() {
        Integer i = 4;
        return i;
    }
}

$ javac Box.java

$ javap -v Box.class</code></pre>
<pre><code>Classfile /Users/emccue/Development/micro-http-ring/Box.class
  Last modified May 14, 2022; size 325 bytes
  SHA-256 checksum 78f01c27cb6b16a51a1c0ac47bf1ceb94cc5a4a7672afc615eb634dd948ba138
  Compiled from &quot;Box.java&quot;
class Box
  minor version: 0
  major version: 61
  flags: (0x0020) ACC_SUPER
  this_class: #13                         // Box
  super_class: #2                         // java/lang/Object
  interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
   #1 = Methodref          #2.#3          // java/lang/Object.&quot;&lt;init&gt;&quot;:()V
   #2 = Class              #4             // java/lang/Object
   #3 = NameAndType        #5:#6          // &quot;&lt;init&gt;&quot;:()V
   #4 = Utf8               java/lang/Object
   #5 = Utf8               &lt;init&gt;
   #6 = Utf8               ()V
   #7 = Methodref          #8.#9          // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   #8 = Class              #10            // java/lang/Integer
   #9 = NameAndType        #11:#12        // valueOf:(I)Ljava/lang/Integer;
  #10 = Utf8               java/lang/Integer
  #11 = Utf8               valueOf
  #12 = Utf8               (I)Ljava/lang/Integer;
  #13 = Class              #14            // Box
  #14 = Utf8               Box
  #15 = Utf8               Code
  #16 = Utf8               LineNumberTable
  #17 = Utf8               f
  #18 = Utf8               ()Ljava/lang/Integer;
  #19 = Utf8               SourceFile
  #20 = Utf8               Box.java
{
  Box();
    descriptor: ()V
    flags: (0x0000)
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object.&quot;&lt;init&gt;&quot;:()V
         4: return
      LineNumberTable:
        line 1: 0
  java.lang.Integer f();
    descriptor: ()Ljava/lang/Integer;
    flags: (0x0000)
    Code:
      stack=1, locals=2, args_size=1
         0: iconst_4
         1: invokestatic  #7                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
         4: astore_1
         5: aload_1
         6: areturn
      LineNumberTable:
        line 3: 0
        line 4: 5
}
SourceFile: &quot;Box.java&quot;</code></pre>
<p>a bit verbose, but you see the <code>invokestatic</code> call in the last snippet refers to <code>Integer.valueOf</code></p>
<blockquote>
<p>yeah</p>
</blockquote>
<pre><code>$ javap -c Box.class
Compiled from &quot;Box.java&quot;
class Box {
  Box();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object.&quot;&lt;init&gt;&quot;:()V
       4: return

  java.lang.Integer f();
    Code:
       0: iconst_4
       1: invokestatic  #7                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       4: astore_1
       5: aload_1
       6: areturn
}</code></pre>
<p>easier to see with <code>-c</code> (still learning javap)</p>
<blockquote>
<p>can there be case where the new Integer(i) is called</p>
</blockquote>
<p>yes, if the integer is outside of the range -128 to 128 it will be outside of the cache and new Integer will be used.</p>
<p><em>for this implementation</em></p>
<blockquote>
<p>if it can then Objects.equals() will return false , and it would behave like the byte[] example</p>
<p>but i guess that never happens</p>
</blockquote>
<p>not quite</p>
<p>the implementation of equals for Integer actually compares the value</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>jshell<span class="op">&gt;</span> <span class="bu">Integer</span> i1 <span class="op">=</span> <span class="bu">Integer</span><span class="op">.</span><span class="fu">valueOf</span><span class="op">(</span><span class="dv">123456</span><span class="op">);</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>i1 <span class="op">==&gt;</span> <span class="dv">123456</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>jshell<span class="op">&gt;</span> <span class="bu">Integer</span> i2 <span class="op">=</span> <span class="bu">Integer</span><span class="op">.</span><span class="fu">valueOf</span><span class="op">(</span><span class="dv">123456</span><span class="op">);</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>i2 <span class="op">==&gt;</span> <span class="dv">123456</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>jshell<span class="op">&gt;</span> i1 <span class="op">==</span> i2</span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>$<span class="dv">7</span> <span class="op">==&gt;</span> <span class="kw">false</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>jshell<span class="op">&gt;</span> i1<span class="op">.</span><span class="fu">equals</span><span class="op">(</span>i2<span class="op">)</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>$<span class="dv">8</span> <span class="op">==&gt;</span> <span class="kw">true</span></span></code></pre></div>
<div class="sourceCode" id="cb9"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>jshell<span class="op">&gt;</span> <span class="dt">byte</span><span class="op">[]</span> b1 <span class="op">=</span> <span class="kw">new</span> <span class="dt">byte</span><span class="op">[</span><span class="dv">0</span><span class="op">];</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>b1 <span class="op">==&gt;</span> <span class="dt">byte</span><span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">{</span>  <span class="op">}</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>jshell<span class="op">&gt;</span> <span class="dt">byte</span><span class="op">[]</span> b2 <span class="op">=</span> <span class="kw">new</span> <span class="dt">byte</span><span class="op">[</span><span class="dv">0</span><span class="op">];</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>b2 <span class="op">==&gt;</span> <span class="dt">byte</span><span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">{</span>  <span class="op">}</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>jshell<span class="op">&gt;</span> b1 <span class="op">==</span> b2</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>$<span class="dv">3</span> <span class="op">==&gt;</span> <span class="kw">false</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>jshell<span class="op">&gt;</span> b1<span class="op">.</span><span class="fu">equals</span><span class="op">(</span>b2<span class="op">)</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>$<span class="dv">4</span> <span class="op">==&gt;</span> <span class="kw">false</span></span></code></pre></div>
<p>reference equality <code>i1 == i2</code> will return false if you have distinct <code>Integer</code> objects</p>
<blockquote>
<p><img src="/pages/5-14-22-docs.png" alt="Screenshot of docs page for Map.remove" ></img></p>
</blockquote>
<p>But the <code>equals</code> method for <code>Integer</code> inherited from <code>Object</code> is overridden so that comparing them with <code>.equals</code> or <code>java.util.Objects.equals(</code> will give the answer you would usually expect.</p>
<p>Yep so if you tried the <code>byte[]</code> map example with <code>Integer</code> then <code>.remove </code>would always find its target value and return <code>true</code> even if you used the deprecated <code>new Integer</code> directly or were outside of the cache range for <code>Integer.valueOf</code>.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>BYTE ARRAYS</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>                | b1 == b2 | b1.equals(b2) | Objects.equals(b1, b2) | Arrays.equals(b1, b2)</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>----------------|--------------------------------------------------------------------------</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>| SAME OBJECT   | true     | true          | true                   | true</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>----------------|--------------------------------------------------------------------------</span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>| SAME CONTENTS | false    | false         | false                  | true</span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>----------------|--------------------------------------------------------------------------</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>| DIFF CONTENTS | false    | false         | false                  | false</span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>----------------|--------------------------------------------------------------------------</span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>| b1 is null    | false    | crash         | false                  | false</span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a>----------------|--------------------------------------------------------------------------</span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a>| b2 is null    | false    | false         | false                  | false</span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a>----------------|--------------------------------------------------------------------------</span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a>| both are null | true     | crash         | true                   | true</span></code></pre></div>
<blockquote>
<p>internal implementation does not use Objects.equals but instead does value.equals(provided)</p>
<p>so yeah it overrides that method</p>
</blockquote>
<div class="sourceCode" id="cb11"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>Integer</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>                | i1 == i2 | b1.equals(b2) | Objects.equals(b1, b2) |</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>----------------|----------------------------------------------------</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>| SAME OBJECT   | true     | true          | true                   |</span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>----------------|----------------------------------------------------</span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>| SAME VALUE    | false    | true          | true                   |</span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>----------------|----------------------------------------------------</span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>| DIFF VALUE    | false    | false         | false                  | </span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a>----------------|----------------------------------------------------</span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>| i1 is null    | false    | crash         | false                  |</span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>----------------|----------------------------------------------------</span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>| i2 is null    | false    | false         | false                  |</span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a>----------------|----------------------------------------------------</span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a>| both are null | true     | crash         | true                   |</span></code></pre></div>
<blockquote>
<p>hey thanks man, that was quite detailed</p>
</blockquote>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Go's Concurrency Examples in Java 19</title><link>https://mccue.dev/pages/5-2-22-go-concurrency-in-java</link><description></description><pubDate>Mon, 02 May 0022 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Go's Concurrency Examples in Java 19</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Go's Concurrency Examples in Java 19</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
## Preface

<p>Threads are usually expensive.</p>
<p>There is no way for your operating system to know exactly how much stack space a thread will need so it allocates an amount on the order of around a kilobyte initially and then around a megabyte once the thread starts to be used. You only have around a bakers dozen gigabytes of RAM, so you can only have give or take 10,000 active threads.</p>
<p>The way around this is to implement a some mechanism that takes a limited number of operating system threads and juggles a much larger number of "logical threads" on top of them.</p>
<p>For most languages, this means adding some form of <code>async/await</code> syntax. Where you put an <code>await</code> the language knows it can switch to handling another task. You can only put <code>await</code>s inside of code marked <code>async</code>. This <a href="https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/">has problems</a>.</p>
<p>The Go programming language is different than most in that it implemented this juggling "non-cooperatively". You don't explicitly mark your code with <code>async</code> and <code>await</code>, the runtime slices it up for you. They call these cheap threads "goroutines."</p>
<p>The Java Virtual Machine is going to get an analogous feature called "Virtual Threads."</p>
<p>This won't just benefit Java, but every language on the JVM including Clojure, Groovy, Kotlin, and Scala.</p>
<p>Virtual Threads are slated to appear as a "Preview" feature in Java 19 on September 20, 2022. This means that the implementation of the underlying feature is complete and tested, but the public API is subject to breaking changes and must be opted into explicitly.</p>
<p>Many of Go's patterns around concurrency arise from the conceit that you can create threads with abandon.</p>
<p>Since Java is about to join that club, it seems a good time to go through some of the Go concurrency examples and see what they might look like translated over.</p>
<p>If you want to follow along, you can get an early access build <a href="https://jdk.java.net/loom/">here</a>. Unzip the files and add the <code>bin/</code> directory to your path.</p>
<p>All the examples can be followed in sequence by using <a href="https://docs.oracle.com/en/java/javase/18/docs/specs/man/jshell.html"><code>jshell</code></a>.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> java <span class="at">--version</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="ex">openjdk</span> 19-loom 2022-09-20</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="ex">OpenJDK</span> Runtime Environment <span class="er">(</span><span class="ex">build</span> 19-loom+6-625<span class="kw">)</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="ex">OpenJDK</span> 64-Bit Server VM <span class="er">(</span><span class="ex">build</span> 19-loom+6-625, mixed mode, sharing<span class="kw">)</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> jshell <span class="at">--enable-preview</span> <span class="at">--add-modules</span><span class="op">=</span>jdk.incubator.concurrent</span></code></pre></div>
<h2 id="example-1-goroutines">Example 1. Goroutines</h2>
<p><a href="https://go.dev/tour/concurrency/1">https://go.dev/tour/concurrency/1</a></p>
<div class="sourceCode" id="cb2"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span> main</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="op">(</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;fmt&quot;</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;time&quot;</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="op">)</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> say<span class="op">(</span>s <span class="dt">string</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">for</span> i <span class="op">:=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">5</span><span class="op">;</span> i<span class="op">++</span> <span class="op">{</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>        time<span class="op">.</span>Sleep<span class="op">(</span><span class="dv">100</span> <span class="op">*</span> time<span class="op">.</span>Millisecond<span class="op">)</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>        fmt<span class="op">.</span>Println<span class="op">(</span>s<span class="op">)</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">go</span> say<span class="op">(</span><span class="st">&quot;world&quot;</span><span class="op">)</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>    say<span class="op">(</span><span class="st">&quot;hello&quot;</span><span class="op">)</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This is a pretty classic example, and frankly can be done with operating system threads just as well.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">time</span><span class="op">.</span><span class="im">Duration</span><span class="op">;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">Executors</span><span class="op">;</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> VirtualThreads <span class="op">{</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">VirtualThreads</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">void</span> <span class="fu">say</span><span class="op">(</span><span class="bu">String</span> s<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>            <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">5</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Thread</span><span class="op">.</span><span class="fu">sleep</span><span class="op">(</span><span class="bu">Duration</span><span class="op">.</span><span class="fu">ofMillis</span><span class="op">(</span><span class="dv">100</span><span class="op">));</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>                <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>s<span class="op">);</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span><span class="bu">InterruptedException</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>            <span class="cf">throw</span> <span class="kw">new</span> <span class="bu">RuntimeException</span><span class="op">(</span>e<span class="op">);</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span>var executor <span class="op">=</span> </span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Executors</span><span class="op">.</span><span class="fu">newVirtualThreadPerTaskExecutor</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a>            executor<span class="op">.</span><span class="fu">submit</span><span class="op">(()</span> <span class="op">-&gt;</span> <span class="fu">say</span><span class="op">(</span><span class="st">&quot;world&quot;</span><span class="op">));</span></span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a>            <span class="fu">say</span><span class="op">(</span><span class="st">&quot;hello&quot;</span><span class="op">);</span></span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>VirtualThreads<span class="op">.</span><span class="fu">main</span><span class="op">(</span><span class="kw">new</span> <span class="bu">String</span><span class="op">[]{});</span></span></code></pre></div>
<p>A few key things to notice.</p>
<ol type="1">
<li>There is some noise in the <code>say</code> method around handling what will happen if the thread is interrupted.</li>
</ol>
<p>In this case we just choose to throw a <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/lang/RuntimeException.html"><code>RuntimeException</code></a> to indicate we just want to crash.</p>
<p>In Go there is less noise, but also there no way to interrupt Go's <a href="https://pkg.go.dev/time#Sleep"><code>time.Sleep</code></a>.</p>
<p>It is also an option to propagate the <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/lang/InterruptedException.html"><code>InterruptedException</code></a> up if we add a <code>return null;</code> to target the <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/Callable.html"><code>Callable</code></a> overload.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> VirtualThreads <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">VirtualThreads</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">void</span> <span class="fu">say</span><span class="op">(</span><span class="bu">String</span> s<span class="op">)</span> <span class="kw">throws</span> <span class="bu">InterruptedException</span> <span class="op">{</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">5</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Thread</span><span class="op">.</span><span class="fu">sleep</span><span class="op">(</span><span class="bu">Duration</span><span class="op">.</span><span class="fu">ofMillis</span><span class="op">(</span><span class="dv">100</span><span class="op">));</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>            <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>s<span class="op">);</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> </span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>            <span class="kw">throws</span> <span class="bu">InterruptedException</span> <span class="op">{</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span>var executor <span class="op">=</span> </span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Executors</span><span class="op">.</span><span class="fu">newVirtualThreadPerTaskExecutor</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>            executor<span class="op">.</span><span class="fu">submit</span><span class="op">(()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a>                <span class="fu">say</span><span class="op">(</span><span class="st">&quot;world&quot;</span><span class="op">);</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a>            <span class="op">});</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a>            <span class="fu">say</span><span class="op">(</span><span class="st">&quot;hello&quot;</span><span class="op">);</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<ol start="2" type="1">
<li>You need more than <code>go say("world")</code></li>
</ol>
<p><code>Executors.newVirtualThreadPerTaskExecutor()</code> creates an <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/ExecutorService.html"><code>ExecutorService</code></a>. This is a thing which you can submit tasks to and it will run them "somehow".</p>
<p>Today most <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/ExecutorService.html"><code>ExecutorService</code></a>s are backed by some pool of threads. The purpose of the interface is to be able to write code without needing to know about the underlying strategy for maintaining that pool.</p>
<p>Virtual Threads are cheap, so you don't need to pool them. The interface still serves a use though. <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/ExecutorService.html"><code>ExecutorService</code></a>s will extend <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/lang/AutoCloseable.html"><code>AutoClosable</code></a>, so when used with the "try-with-resources" syntax you can make a block of code where you wait until all tasks have completed before moving on.</p>
<p>If you wanted to do the same creating threads directly it would look like this.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> VirtualThreads <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">VirtualThreads</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">void</span> <span class="fu">say</span><span class="op">(</span><span class="bu">String</span> s<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>            <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">5</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Thread</span><span class="op">.</span><span class="fu">sleep</span><span class="op">(</span><span class="bu">Duration</span><span class="op">.</span><span class="fu">ofMillis</span><span class="op">(</span><span class="dv">100</span><span class="op">));</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>                <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>s<span class="op">);</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span><span class="bu">InterruptedException</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>            <span class="cf">throw</span> <span class="kw">new</span> <span class="bu">RuntimeException</span><span class="op">(</span>e<span class="op">);</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> </span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a>            <span class="kw">throws</span> <span class="bu">InterruptedException</span> <span class="op">{</span></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a>        var worldThread <span class="op">=</span> <span class="bu">Thread</span><span class="op">.</span><span class="fu">startVirtualThread</span><span class="op">(</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a>            <span class="op">()</span> <span class="op">-&gt;</span> <span class="fu">say</span><span class="op">(</span><span class="st">&quot;world&quot;</span><span class="op">)</span></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a>        <span class="fu">say</span><span class="op">(</span><span class="st">&quot;hello&quot;</span><span class="op">);</span></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true" tabindex="-1"></a>        <span class="co">// Explicitly join to wait for the other thread.</span></span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true" tabindex="-1"></a>        worldThread<span class="op">.</span><span class="fu">join</span><span class="op">();</span></span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb6-26"><a href="#cb6-26" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="example-2-channels">Example 2. Channels</h2>
<p><a href="https://go.dev/tour/concurrency/2">https://go.dev/tour/concurrency/2</a></p>
<div class="sourceCode" id="cb7"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span> main</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="st">&quot;fmt&quot;</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> sum<span class="op">(</span>s <span class="op">[]</span><span class="dt">int</span><span class="op">,</span> c <span class="kw">chan</span> <span class="dt">int</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>    sum <span class="op">:=</span> <span class="dv">0</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">for</span> _<span class="op">,</span> v <span class="op">:=</span> <span class="kw">range</span> s <span class="op">{</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>        sum <span class="op">+=</span> v</span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>    c <span class="op">&lt;-</span> sum <span class="co">// send sum to c</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a>    s <span class="op">:=</span> <span class="op">[]</span><span class="dt">int</span><span class="op">{</span><span class="dv">7</span><span class="op">,</span> <span class="dv">2</span><span class="op">,</span> <span class="dv">8</span><span class="op">,</span> <span class="op">-</span><span class="dv">9</span><span class="op">,</span> <span class="dv">4</span><span class="op">,</span> <span class="dv">0</span><span class="op">}</span></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a>    c <span class="op">:=</span> <span class="bu">make</span><span class="op">(</span><span class="kw">chan</span> <span class="dt">int</span><span class="op">)</span></span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">go</span> sum<span class="op">(</span>s<span class="op">[:</span><span class="bu">len</span><span class="op">(</span>s<span class="op">)/</span><span class="dv">2</span><span class="op">],</span> c<span class="op">)</span></span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">go</span> sum<span class="op">(</span>s<span class="op">[</span><span class="bu">len</span><span class="op">(</span>s<span class="op">)/</span><span class="dv">2</span><span class="op">:],</span> c<span class="op">)</span></span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true" tabindex="-1"></a>    x<span class="op">,</span> y <span class="op">:=</span> <span class="op">&lt;-</span>c<span class="op">,</span> <span class="op">&lt;-</span>c <span class="co">// receive from c</span></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true" tabindex="-1"></a>    fmt<span class="op">.</span>Println<span class="op">(</span>x<span class="op">,</span> y<span class="op">,</span> x<span class="op">+</span>y<span class="op">)</span></span>
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Go has the concept of a "channel." This is a lightweight pipe along which values can be sent between <a href="https://www.cs.cmu.edu/~crary/819-f09/Hoare78.pdf">"Communicating Sequential Processes"</a>.</p>
<p>Java does not have this concept in its standard library. There are <a href="https://clojure.github.io/core.async/#clojure.core.async/chan">similar constructs</a> in libraries and it <a href="https://cr.openjdk.java.net/~rpressler/loom/loom/sol1_part2.html#channels">may come in the future</a>, but for now no dice.</p>
<p>A somewhat close analogue is a <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/BlockingQueue.html"><code>BlockingQueue</code></a>, so that is what I am going to use for the purposes of these examples.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">ArrayBlockingQueue</span><span class="op">;</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">BlockingQueue</span><span class="op">;</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">Executors</span><span class="op">;</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> Queues <span class="op">{</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Queues</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">void</span> <span class="fu">sum</span><span class="op">(</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span><span class="op">[]</span> s<span class="op">,</span> </span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> start<span class="op">,</span> </span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> end<span class="op">,</span> </span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>        <span class="bu">BlockingQueue</span><span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;</span> queue</span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">throws</span> <span class="bu">InterruptedException</span> <span class="op">{</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> sum <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> start<span class="op">;</span> i <span class="op">&lt;</span> end<span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>            sum <span class="op">+=</span> s<span class="op">[</span>i<span class="op">];</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true" tabindex="-1"></a>        queue<span class="op">.</span><span class="fu">put</span><span class="op">(</span>sum<span class="op">);</span></span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> </span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true" tabindex="-1"></a>        <span class="kw">throws</span> <span class="bu">InterruptedException</span> <span class="op">{</span></span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span><span class="op">[]</span> s <span class="op">=</span> <span class="op">{</span> <span class="dv">7</span><span class="op">,</span> <span class="dv">2</span><span class="op">,</span> <span class="dv">8</span><span class="op">,</span> <span class="op">-</span><span class="dv">9</span><span class="op">,</span> <span class="dv">4</span><span class="op">,</span> <span class="dv">0</span> <span class="op">};</span></span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span>var executor <span class="op">=</span> </span>
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Executors</span><span class="op">.</span><span class="fu">newVirtualThreadPerTaskExecutor</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb8-26"><a href="#cb8-26" aria-hidden="true" tabindex="-1"></a>            var queue <span class="op">=</span> <span class="kw">new</span> <span class="bu">ArrayBlockingQueue</span><span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;(</span><span class="dv">1</span><span class="op">);</span></span>
<span id="cb8-27"><a href="#cb8-27" aria-hidden="true" tabindex="-1"></a>            executor<span class="op">.</span><span class="fu">submit</span><span class="op">(()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb8-28"><a href="#cb8-28" aria-hidden="true" tabindex="-1"></a>                <span class="fu">sum</span><span class="op">(</span>s<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> s<span class="op">.</span><span class="fu">length</span> <span class="op">/</span> <span class="dv">2</span><span class="op">,</span> queue<span class="op">);</span></span>
<span id="cb8-29"><a href="#cb8-29" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb8-30"><a href="#cb8-30" aria-hidden="true" tabindex="-1"></a>            <span class="op">});</span></span>
<span id="cb8-31"><a href="#cb8-31" aria-hidden="true" tabindex="-1"></a>            executor<span class="op">.</span><span class="fu">submit</span><span class="op">(()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb8-32"><a href="#cb8-32" aria-hidden="true" tabindex="-1"></a>                <span class="fu">sum</span><span class="op">(</span>s<span class="op">,</span> s<span class="op">.</span><span class="fu">length</span> <span class="op">/</span> <span class="dv">2</span><span class="op">,</span> s<span class="op">.</span><span class="fu">length</span><span class="op">,</span> queue<span class="op">);</span></span>
<span id="cb8-33"><a href="#cb8-33" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb8-34"><a href="#cb8-34" aria-hidden="true" tabindex="-1"></a>            <span class="op">});</span></span>
<span id="cb8-35"><a href="#cb8-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-36"><a href="#cb8-36" aria-hidden="true" tabindex="-1"></a>            <span class="dt">int</span> x <span class="op">=</span> queue<span class="op">.</span><span class="fu">take</span><span class="op">();</span></span>
<span id="cb8-37"><a href="#cb8-37" aria-hidden="true" tabindex="-1"></a>            <span class="dt">int</span> y <span class="op">=</span> queue<span class="op">.</span><span class="fu">take</span><span class="op">();</span></span>
<span id="cb8-38"><a href="#cb8-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-39"><a href="#cb8-39" aria-hidden="true" tabindex="-1"></a>            <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">printf</span><span class="op">(</span><span class="st">&quot;</span><span class="sc">%d</span><span class="st"> </span><span class="sc">%d</span><span class="st"> </span><span class="sc">%d\n</span><span class="st">&quot;</span><span class="op">,</span> x<span class="op">,</span> y<span class="op">,</span> x <span class="op">+</span> y<span class="op">);</span></span>
<span id="cb8-40"><a href="#cb8-40" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb8-41"><a href="#cb8-41" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-42"><a href="#cb8-42" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb9"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>Queues<span class="op">.</span><span class="fu">main</span><span class="op">(</span><span class="kw">new</span> <span class="bu">String</span><span class="op">[]{});</span></span></code></pre></div>
<p>Instead of Go's syntax for making slices of arrays, I opted to instead pass the indexes that each <code>sum</code> call was expected to work on.</p>
<p>It is only safe to share the memory for the array like this because no other threads are changing its contents. If there was we would have summoned Gorslax. This would be true in both Go and Java.</p>
<p>In both cases the way this works is each worker sends the results of its computation to a logical queue. Once we have read two values off the shared queue we implicitly know that the two tasks we started have finished.</p>
<p>For "one shot" use cases such as this, you could also use Java's <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/CompletableFuture.html"><code>CompletableFuture</code></a> for the same purpose.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">CompletableFuture</span><span class="op">;</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">ExecutionException</span><span class="op">;</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">Executors</span><span class="op">;</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> Queues <span class="op">{</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Queues</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">void</span> <span class="fu">sum</span><span class="op">(</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span><span class="op">[]</span> s<span class="op">,</span> </span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> start<span class="op">,</span> </span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> end<span class="op">,</span> </span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a>        CompletableFuture<span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;</span> future</span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> sum <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> start<span class="op">;</span> i <span class="op">&lt;</span> end<span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a>            sum <span class="op">+=</span> s<span class="op">[</span>i<span class="op">];</span></span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a>        future<span class="op">.</span><span class="fu">complete</span><span class="op">(</span>sum<span class="op">);</span></span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span></span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true" tabindex="-1"></a>        <span class="kw">throws</span> <span class="bu">InterruptedException</span><span class="op">,</span> <span class="bu">ExecutionException</span> <span class="op">{</span></span>
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span><span class="op">[]</span> s <span class="op">=</span> <span class="op">{</span> <span class="dv">7</span><span class="op">,</span> <span class="dv">2</span><span class="op">,</span> <span class="dv">8</span><span class="op">,</span> <span class="op">-</span><span class="dv">9</span><span class="op">,</span> <span class="dv">4</span><span class="op">,</span> <span class="dv">0</span> <span class="op">};</span></span>
<span id="cb10-24"><a href="#cb10-24" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span>var executor <span class="op">=</span> </span>
<span id="cb10-25"><a href="#cb10-25" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Executors</span><span class="op">.</span><span class="fu">newVirtualThreadPerTaskExecutor</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb10-26"><a href="#cb10-26" aria-hidden="true" tabindex="-1"></a>            var futureOne <span class="op">=</span> <span class="kw">new</span> CompletableFuture<span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;();</span></span>
<span id="cb10-27"><a href="#cb10-27" aria-hidden="true" tabindex="-1"></a>            var futureTwo <span class="op">=</span> <span class="kw">new</span> CompletableFuture<span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;();</span></span>
<span id="cb10-28"><a href="#cb10-28" aria-hidden="true" tabindex="-1"></a>            </span>
<span id="cb10-29"><a href="#cb10-29" aria-hidden="true" tabindex="-1"></a>            executor<span class="op">.</span><span class="fu">submit</span><span class="op">(()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb10-30"><a href="#cb10-30" aria-hidden="true" tabindex="-1"></a>                <span class="fu">sum</span><span class="op">(</span>s<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> s<span class="op">.</span><span class="fu">length</span> <span class="op">/</span> <span class="dv">2</span><span class="op">,</span> futureOne<span class="op">);</span></span>
<span id="cb10-31"><a href="#cb10-31" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb10-32"><a href="#cb10-32" aria-hidden="true" tabindex="-1"></a>            <span class="op">});</span></span>
<span id="cb10-33"><a href="#cb10-33" aria-hidden="true" tabindex="-1"></a>            executor<span class="op">.</span><span class="fu">submit</span><span class="op">(()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb10-34"><a href="#cb10-34" aria-hidden="true" tabindex="-1"></a>                <span class="fu">sum</span><span class="op">(</span>s<span class="op">,</span> s<span class="op">.</span><span class="fu">length</span> <span class="op">/</span> <span class="dv">2</span><span class="op">,</span> s<span class="op">.</span><span class="fu">length</span><span class="op">,</span> futureTwo<span class="op">);</span></span>
<span id="cb10-35"><a href="#cb10-35" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb10-36"><a href="#cb10-36" aria-hidden="true" tabindex="-1"></a>            <span class="op">});</span></span>
<span id="cb10-37"><a href="#cb10-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-38"><a href="#cb10-38" aria-hidden="true" tabindex="-1"></a>            <span class="dt">int</span> x <span class="op">=</span> futureOne<span class="op">.</span><span class="fu">get</span><span class="op">();</span></span>
<span id="cb10-39"><a href="#cb10-39" aria-hidden="true" tabindex="-1"></a>            <span class="dt">int</span> y <span class="op">=</span> futureTwo<span class="op">.</span><span class="fu">get</span><span class="op">();</span></span>
<span id="cb10-40"><a href="#cb10-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-41"><a href="#cb10-41" aria-hidden="true" tabindex="-1"></a>            <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">printf</span><span class="op">(</span><span class="st">&quot;</span><span class="sc">%d</span><span class="st"> </span><span class="sc">%d</span><span class="st"> </span><span class="sc">%d\n</span><span class="st">&quot;</span><span class="op">,</span> x<span class="op">,</span> y<span class="op">,</span> x <span class="op">+</span> y<span class="op">);</span></span>
<span id="cb10-42"><a href="#cb10-42" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb10-43"><a href="#cb10-43" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-44"><a href="#cb10-44" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This adds <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/ExecutionException.html"><code>ExecutionException</code></a> to the explicit list of things that can go wrong, but is a more direct api for a task that will run and produce one value as a result.</p>
<p>In fact, if we were to change <code>sum</code> to return its result directly then we could eliminate its awareness that it is being run asynchronously.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">CompletableFuture</span><span class="op">;</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">ExecutionException</span><span class="op">;</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">Executors</span><span class="op">;</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> Queues <span class="op">{</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Queues</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">int</span> <span class="fu">sum</span><span class="op">(</span><span class="dt">int</span><span class="op">[]</span> s<span class="op">,</span> <span class="dt">int</span> start<span class="op">,</span> <span class="dt">int</span> end<span class="op">)</span>  <span class="op">{</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> sum <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> start<span class="op">;</span> i <span class="op">&lt;</span> end<span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>            sum <span class="op">+=</span> s<span class="op">[</span>i<span class="op">];</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> sum<span class="op">;</span></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> </span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true" tabindex="-1"></a>        <span class="kw">throws</span> <span class="bu">InterruptedException</span><span class="op">,</span> <span class="bu">ExecutionException</span> <span class="op">{</span></span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span><span class="op">[]</span> s <span class="op">=</span> <span class="op">{</span> <span class="dv">7</span><span class="op">,</span> <span class="dv">2</span><span class="op">,</span> <span class="dv">8</span><span class="op">,</span> <span class="op">-</span><span class="dv">9</span><span class="op">,</span> <span class="dv">4</span><span class="op">,</span> <span class="dv">0</span> <span class="op">};</span></span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span>var executor <span class="op">=</span> </span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Executors</span><span class="op">.</span><span class="fu">newVirtualThreadPerTaskExecutor</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true" tabindex="-1"></a>            var futureOne <span class="op">=</span> CompletableFuture</span>
<span id="cb11-22"><a href="#cb11-22" aria-hidden="true" tabindex="-1"></a>                    <span class="op">.</span><span class="fu">supplyAsync</span><span class="op">(</span></span>
<span id="cb11-23"><a href="#cb11-23" aria-hidden="true" tabindex="-1"></a>                        <span class="op">()</span> <span class="op">-&gt;</span>  <span class="fu">sum</span><span class="op">(</span>s<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> s<span class="op">.</span><span class="fu">length</span> <span class="op">/</span> <span class="dv">2</span><span class="op">),</span></span>
<span id="cb11-24"><a href="#cb11-24" aria-hidden="true" tabindex="-1"></a>                        executor</span>
<span id="cb11-25"><a href="#cb11-25" aria-hidden="true" tabindex="-1"></a>                    <span class="op">);</span></span>
<span id="cb11-26"><a href="#cb11-26" aria-hidden="true" tabindex="-1"></a>            var futureTwo <span class="op">=</span> CompletableFuture</span>
<span id="cb11-27"><a href="#cb11-27" aria-hidden="true" tabindex="-1"></a>                    <span class="op">.</span><span class="fu">supplyAsync</span><span class="op">(</span></span>
<span id="cb11-28"><a href="#cb11-28" aria-hidden="true" tabindex="-1"></a>                        <span class="op">()</span> <span class="op">-&gt;</span>  <span class="fu">sum</span><span class="op">(</span>s<span class="op">,</span> s<span class="op">.</span><span class="fu">length</span> <span class="op">/</span> <span class="dv">2</span><span class="op">,</span> s<span class="op">.</span><span class="fu">length</span><span class="op">),</span></span>
<span id="cb11-29"><a href="#cb11-29" aria-hidden="true" tabindex="-1"></a>                        executor</span>
<span id="cb11-30"><a href="#cb11-30" aria-hidden="true" tabindex="-1"></a>                    <span class="op">);</span></span>
<span id="cb11-31"><a href="#cb11-31" aria-hidden="true" tabindex="-1"></a>                    </span>
<span id="cb11-32"><a href="#cb11-32" aria-hidden="true" tabindex="-1"></a>            <span class="dt">int</span> x <span class="op">=</span> futureOne<span class="op">.</span><span class="fu">get</span><span class="op">();</span></span>
<span id="cb11-33"><a href="#cb11-33" aria-hidden="true" tabindex="-1"></a>            <span class="dt">int</span> y <span class="op">=</span> futureTwo<span class="op">.</span><span class="fu">get</span><span class="op">();</span></span>
<span id="cb11-34"><a href="#cb11-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-35"><a href="#cb11-35" aria-hidden="true" tabindex="-1"></a>            <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">printf</span><span class="op">(</span><span class="st">&quot;</span><span class="sc">%d</span><span class="st"> </span><span class="sc">%d</span><span class="st"> </span><span class="sc">%d\n</span><span class="st">&quot;</span><span class="op">,</span> x<span class="op">,</span> y<span class="op">,</span> x <span class="op">+</span> y<span class="op">);</span></span>
<span id="cb11-36"><a href="#cb11-36" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb11-37"><a href="#cb11-37" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb11-38"><a href="#cb11-38" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And if we don't need any of the fancier capabilities of <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/CompletableFuture.html"><code>CompletableFuture</code></a>, then the plain <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/Future.html"><code>Future</code></a> objects returned by submitting directly to the <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/ExecutorService.html"><code>ExecutorService</code></a> are also an option.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">ExecutionException</span><span class="op">;</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">Executors</span><span class="op">;</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> Queues <span class="op">{</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Queues</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">int</span> <span class="fu">sum</span><span class="op">(</span><span class="dt">int</span><span class="op">[]</span> s<span class="op">,</span> <span class="dt">int</span> start<span class="op">,</span> <span class="dt">int</span> end<span class="op">)</span>  <span class="op">{</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> sum <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> start<span class="op">;</span> i <span class="op">&lt;</span> end<span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>            sum <span class="op">+=</span> s<span class="op">[</span>i<span class="op">];</span></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> sum<span class="op">;</span></span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> </span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true" tabindex="-1"></a>        <span class="kw">throws</span> <span class="bu">InterruptedException</span><span class="op">,</span> <span class="bu">ExecutionException</span> <span class="op">{</span></span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span><span class="op">[]</span> s <span class="op">=</span> <span class="op">{</span> <span class="dv">7</span><span class="op">,</span> <span class="dv">2</span><span class="op">,</span> <span class="dv">8</span><span class="op">,</span> <span class="op">-</span><span class="dv">9</span><span class="op">,</span> <span class="dv">4</span><span class="op">,</span> <span class="dv">0</span> <span class="op">};</span></span>
<span id="cb12-18"><a href="#cb12-18" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span>var executor <span class="op">=</span> </span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Executors</span><span class="op">.</span><span class="fu">newVirtualThreadPerTaskExecutor</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb12-20"><a href="#cb12-20" aria-hidden="true" tabindex="-1"></a>            var futureOne <span class="op">=</span> executor<span class="op">.</span><span class="fu">submit</span><span class="op">(</span></span>
<span id="cb12-21"><a href="#cb12-21" aria-hidden="true" tabindex="-1"></a>                <span class="op">()</span> <span class="op">-&gt;</span>  <span class="fu">sum</span><span class="op">(</span>s<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> s<span class="op">.</span><span class="fu">length</span> <span class="op">/</span> <span class="dv">2</span><span class="op">)</span></span>
<span id="cb12-22"><a href="#cb12-22" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb12-23"><a href="#cb12-23" aria-hidden="true" tabindex="-1"></a>            var futureTwo <span class="op">=</span> executor<span class="op">.</span><span class="fu">submit</span><span class="op">(</span></span>
<span id="cb12-24"><a href="#cb12-24" aria-hidden="true" tabindex="-1"></a>                <span class="op">()</span> <span class="op">-&gt;</span>  <span class="fu">sum</span><span class="op">(</span>s<span class="op">,</span> s<span class="op">.</span><span class="fu">length</span> <span class="op">/</span> <span class="dv">2</span><span class="op">,</span> s<span class="op">.</span><span class="fu">length</span><span class="op">)</span></span>
<span id="cb12-25"><a href="#cb12-25" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb12-26"><a href="#cb12-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-27"><a href="#cb12-27" aria-hidden="true" tabindex="-1"></a>            <span class="dt">int</span> x <span class="op">=</span> futureOne<span class="op">.</span><span class="fu">get</span><span class="op">();</span></span>
<span id="cb12-28"><a href="#cb12-28" aria-hidden="true" tabindex="-1"></a>            <span class="dt">int</span> y <span class="op">=</span> futureTwo<span class="op">.</span><span class="fu">get</span><span class="op">();</span></span>
<span id="cb12-29"><a href="#cb12-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-30"><a href="#cb12-30" aria-hidden="true" tabindex="-1"></a>            <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">printf</span><span class="op">(</span><span class="st">&quot;</span><span class="sc">%d</span><span class="st"> </span><span class="sc">%d</span><span class="st"> </span><span class="sc">%d\n</span><span class="st">&quot;</span><span class="op">,</span> x<span class="op">,</span> y<span class="op">,</span> x <span class="op">+</span> y<span class="op">);</span></span>
<span id="cb12-31"><a href="#cb12-31" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb12-32"><a href="#cb12-32" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb12-33"><a href="#cb12-33" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="example-3-buffered-channels">Example 3. Buffered Channels</h2>
<p><a href="https://go.dev/tour/concurrency/3">https://go.dev/tour/concurrency/3</a></p>
<div class="sourceCode" id="cb13"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span> main</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="st">&quot;fmt&quot;</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>    ch <span class="op">:=</span> <span class="bu">make</span><span class="op">(</span><span class="kw">chan</span> <span class="dt">int</span><span class="op">,</span> <span class="dv">2</span><span class="op">)</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>    ch <span class="op">&lt;-</span> <span class="dv">1</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>    ch <span class="op">&lt;-</span> <span class="dv">2</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>    fmt<span class="op">.</span>Println<span class="op">(&lt;-</span>ch<span class="op">)</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>    fmt<span class="op">.</span>Println<span class="op">(&lt;-</span>ch<span class="op">)</span></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>There isn't much to this one. Go's channels can be "buffered", meaning they can accept multiple values before they will be "full". If a channel is full then any thread that wants to put a value onto that channel will have to wait until another thread takes a value off.</p>
<p>The <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/ArrayBlockingQueue.html"><code>ArrayBlockingQueue</code></a> class we've been using works the same way.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">ArrayBlockingQueue</span><span class="op">;</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> BufferedQueue <span class="op">{</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">BufferedQueue</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> </span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">throws</span> <span class="bu">InterruptedException</span> <span class="op">{</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>        var queue <span class="op">=</span> <span class="kw">new</span> <span class="bu">ArrayBlockingQueue</span><span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;(</span><span class="dv">2</span><span class="op">);</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>        queue<span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="dv">1</span><span class="op">);</span></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a>        queue<span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="dv">2</span><span class="op">);</span></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>queue<span class="op">.</span><span class="fu">take</span><span class="op">());</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>queue<span class="op">.</span><span class="fu">take</span><span class="op">());</span></span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb15"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>BufferedQueue<span class="op">.</span><span class="fu">main</span><span class="op">(</span><span class="kw">new</span> <span class="bu">String</span><span class="op">[]{});</span></span></code></pre></div>
<h2 id="example-4-range-and-close">Example 4. Range and Close</h2>
<p><a href="https://go.dev/tour/concurrency/4">https://go.dev/tour/concurrency/4</a></p>
<div class="sourceCode" id="cb16"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span> main</span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="op">(</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;fmt&quot;</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a><span class="op">)</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> fibonacci<span class="op">(</span>n <span class="dt">int</span><span class="op">,</span> c <span class="kw">chan</span> <span class="dt">int</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>    x<span class="op">,</span> y <span class="op">:=</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">1</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">for</span> i <span class="op">:=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> n<span class="op">;</span> i<span class="op">++</span> <span class="op">{</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>        c <span class="op">&lt;-</span> x</span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>        x<span class="op">,</span> y <span class="op">=</span> y<span class="op">,</span> x<span class="op">+</span>y</span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a>    <span class="bu">close</span><span class="op">(</span>c<span class="op">)</span></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a>    c <span class="op">:=</span> <span class="bu">make</span><span class="op">(</span><span class="kw">chan</span> <span class="dt">int</span><span class="op">,</span> <span class="dv">10</span><span class="op">)</span></span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">go</span> fibonacci<span class="op">(</span><span class="bu">cap</span><span class="op">(</span>c<span class="op">),</span> c<span class="op">)</span></span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">for</span> i <span class="op">:=</span> <span class="kw">range</span> c <span class="op">{</span></span>
<span id="cb16-20"><a href="#cb16-20" aria-hidden="true" tabindex="-1"></a>        fmt<span class="op">.</span>Println<span class="op">(</span>i<span class="op">)</span></span>
<span id="cb16-21"><a href="#cb16-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-22"><a href="#cb16-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Here is where the differences between a Java <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/BlockingQueue.html"><code>BlockingQueue</code></a> and a Go <code>chan</code> start to manifest themselves.</p>
<p>There is no ability to "close" a <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/BlockingQueue.html"><code>BlockingQueue</code></a>. One way around this is to send a special "sentinel" value over the queue to indicate that a reader should stop reading. This only works cleanly when we have a single reader though.</p>
<p>There is also no equivalent to the <code>range</code> operator. We need to write a normal <code>while</code> loop.</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">ArrayBlockingQueue</span><span class="op">;</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">BlockingQueue</span><span class="op">;</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">Executors</span><span class="op">;</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> TakeResult<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>    record GotValue<span class="op">&lt;</span>T<span class="op">&gt;(</span>T value<span class="op">)</span> <span class="kw">implements</span> TakeResult<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">{}</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a>    record NoValue<span class="op">&lt;</span>T<span class="op">&gt;()</span> <span class="kw">implements</span> TakeResult<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">{}</span></span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> Fibonacci <span class="op">{</span></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Fibonacci</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">void</span> <span class="fu">fibonacci</span><span class="op">(</span></span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> n<span class="op">,</span> </span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a>        <span class="bu">BlockingQueue</span><span class="op">&lt;</span>TakeResult<span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;&gt;</span> queue</span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">throws</span> <span class="bu">InterruptedException</span> <span class="op">{</span></span>
<span id="cb17-17"><a href="#cb17-17" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> x <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb17-18"><a href="#cb17-18" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> y <span class="op">=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb17-19"><a href="#cb17-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-20"><a href="#cb17-20" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> n<span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb17-21"><a href="#cb17-21" aria-hidden="true" tabindex="-1"></a>            queue<span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="kw">new</span> TakeResult<span class="op">.</span><span class="fu">GotValue</span><span class="op">&lt;&gt;(</span>x<span class="op">));</span></span>
<span id="cb17-22"><a href="#cb17-22" aria-hidden="true" tabindex="-1"></a>            <span class="dt">int</span> temp <span class="op">=</span> x<span class="op">;</span></span>
<span id="cb17-23"><a href="#cb17-23" aria-hidden="true" tabindex="-1"></a>            x <span class="op">=</span> y<span class="op">;</span></span>
<span id="cb17-24"><a href="#cb17-24" aria-hidden="true" tabindex="-1"></a>            y <span class="op">=</span> temp <span class="op">+</span> x<span class="op">;</span></span>
<span id="cb17-25"><a href="#cb17-25" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb17-26"><a href="#cb17-26" aria-hidden="true" tabindex="-1"></a>        queue<span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="kw">new</span> TakeResult<span class="op">.</span><span class="fu">NoValue</span><span class="op">&lt;&gt;());</span></span>
<span id="cb17-27"><a href="#cb17-27" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb17-28"><a href="#cb17-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-29"><a href="#cb17-29" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> </span>
<span id="cb17-30"><a href="#cb17-30" aria-hidden="true" tabindex="-1"></a>        <span class="kw">throws</span> <span class="bu">InterruptedException</span> <span class="op">{</span></span>
<span id="cb17-31"><a href="#cb17-31" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span>var executor <span class="op">=</span> </span>
<span id="cb17-32"><a href="#cb17-32" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Executors</span><span class="op">.</span><span class="fu">newVirtualThreadPerTaskExecutor</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb17-33"><a href="#cb17-33" aria-hidden="true" tabindex="-1"></a>            var queue <span class="op">=</span> </span>
<span id="cb17-34"><a href="#cb17-34" aria-hidden="true" tabindex="-1"></a>                <span class="kw">new</span> <span class="bu">ArrayBlockingQueue</span><span class="op">&lt;</span>TakeResult<span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;&gt;(</span><span class="dv">10</span><span class="op">);</span></span>
<span id="cb17-35"><a href="#cb17-35" aria-hidden="true" tabindex="-1"></a>            executor<span class="op">.</span><span class="fu">submit</span><span class="op">(()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb17-36"><a href="#cb17-36" aria-hidden="true" tabindex="-1"></a>                <span class="fu">fibonacci</span><span class="op">(</span>queue<span class="op">.</span><span class="fu">remainingCapacity</span><span class="op">(),</span> queue<span class="op">);</span></span>
<span id="cb17-37"><a href="#cb17-37" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb17-38"><a href="#cb17-38" aria-hidden="true" tabindex="-1"></a>            <span class="op">});</span></span>
<span id="cb17-39"><a href="#cb17-39" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-40"><a href="#cb17-40" aria-hidden="true" tabindex="-1"></a>            <span class="cf">while</span> <span class="op">(</span>queue<span class="op">.</span><span class="fu">take</span><span class="op">()</span> <span class="kw">instanceof</span> </span>
<span id="cb17-41"><a href="#cb17-41" aria-hidden="true" tabindex="-1"></a>                    GotValue<span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;</span> gotValue<span class="op">)</span> <span class="op">{</span></span>
<span id="cb17-42"><a href="#cb17-42" aria-hidden="true" tabindex="-1"></a>                <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>gotValue<span class="op">.</span><span class="fu">value</span><span class="op">());</span></span>
<span id="cb17-43"><a href="#cb17-43" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb17-44"><a href="#cb17-44" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb17-45"><a href="#cb17-45" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb17-46"><a href="#cb17-46" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb18"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a>Fibonacci<span class="op">.</span><span class="fu">main</span><span class="op">(</span><span class="kw">new</span> <span class="bu">String</span><span class="op">[]{});</span></span></code></pre></div>
<p>This snippet makes use of sealed interfaces, a relatively recent addition to Java, for modeling getting either a legitimate value over the queue or a signal to stop consuming.</p>
<p>The other options for the same result would be to drop the generic types from the <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/BlockingQueue.html"><code>BlockingQueue</code></a> and use a special sentinel instance of <code>Object</code> or disallow <code>null</code> values for normal use and have that indicate that the queue is closed.</p>
<h2 id="example-5-select">Example 5. Select</h2>
<p><a href="https://go.dev/tour/concurrency/5">https://go.dev/tour/concurrency/5</a></p>
<div class="sourceCode" id="cb19"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span> main</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="st">&quot;fmt&quot;</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> fibonacci<span class="op">(</span>c<span class="op">,</span> quit <span class="kw">chan</span> <span class="dt">int</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>    x<span class="op">,</span> y <span class="op">:=</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">1</span></span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">for</span> <span class="op">{</span></span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">select</span> <span class="op">{</span></span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">case</span> c <span class="op">&lt;-</span> x<span class="op">:</span></span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a>            x<span class="op">,</span> y <span class="op">=</span> y<span class="op">,</span> x<span class="op">+</span>y</span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a>        <span class="kw">case</span> <span class="op">&lt;-</span>quit<span class="op">:</span></span>
<span id="cb19-12"><a href="#cb19-12" aria-hidden="true" tabindex="-1"></a>            fmt<span class="op">.</span>Println<span class="op">(</span><span class="st">&quot;quit&quot;</span><span class="op">)</span></span>
<span id="cb19-13"><a href="#cb19-13" aria-hidden="true" tabindex="-1"></a>            <span class="kw">return</span></span>
<span id="cb19-14"><a href="#cb19-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb19-15"><a href="#cb19-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb19-16"><a href="#cb19-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb19-17"><a href="#cb19-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-18"><a href="#cb19-18" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb19-19"><a href="#cb19-19" aria-hidden="true" tabindex="-1"></a>    c <span class="op">:=</span> <span class="bu">make</span><span class="op">(</span><span class="kw">chan</span> <span class="dt">int</span><span class="op">)</span></span>
<span id="cb19-20"><a href="#cb19-20" aria-hidden="true" tabindex="-1"></a>    quit <span class="op">:=</span> <span class="bu">make</span><span class="op">(</span><span class="kw">chan</span> <span class="dt">int</span><span class="op">)</span></span>
<span id="cb19-21"><a href="#cb19-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">go</span> <span class="kw">func</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb19-22"><a href="#cb19-22" aria-hidden="true" tabindex="-1"></a>        <span class="kw">for</span> i <span class="op">:=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">10</span><span class="op">;</span> i<span class="op">++</span> <span class="op">{</span></span>
<span id="cb19-23"><a href="#cb19-23" aria-hidden="true" tabindex="-1"></a>            fmt<span class="op">.</span>Println<span class="op">(&lt;-</span>c<span class="op">)</span></span>
<span id="cb19-24"><a href="#cb19-24" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb19-25"><a href="#cb19-25" aria-hidden="true" tabindex="-1"></a>        quit <span class="op">&lt;-</span> <span class="dv">0</span></span>
<span id="cb19-26"><a href="#cb19-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">}()</span></span>
<span id="cb19-27"><a href="#cb19-27" aria-hidden="true" tabindex="-1"></a>    fibonacci<span class="op">(</span>c<span class="op">,</span> quit<span class="op">)</span></span>
<span id="cb19-28"><a href="#cb19-28" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>There is also no equivalent to <code>select</code> for <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/BlockingQueue.html"><code>BlockingQueue</code></a>s. We have to implement that logic in a hand rolled loop.</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">ArrayBlockingQueue</span><span class="op">;</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">BlockingQueue</span><span class="op">;</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">Executors</span><span class="op">;</span></span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> SelectQueues <span class="op">{</span></span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">SelectQueues</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">void</span> <span class="fu">fibonacci</span><span class="op">(</span><span class="bu">BlockingQueue</span><span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;</span> queue<span class="op">,</span></span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a>                          <span class="bu">BlockingQueue</span><span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;</span> quit<span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> x <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb20-11"><a href="#cb20-11" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> y <span class="op">=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb20-12"><a href="#cb20-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-13"><a href="#cb20-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">while</span> <span class="op">(</span><span class="kw">true</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-14"><a href="#cb20-14" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>queue<span class="op">.</span><span class="fu">offer</span><span class="op">(</span>x<span class="op">))</span> <span class="op">{</span></span>
<span id="cb20-15"><a href="#cb20-15" aria-hidden="true" tabindex="-1"></a>                <span class="dt">int</span> temp <span class="op">=</span> x<span class="op">;</span></span>
<span id="cb20-16"><a href="#cb20-16" aria-hidden="true" tabindex="-1"></a>                x <span class="op">=</span> y<span class="op">;</span></span>
<span id="cb20-17"><a href="#cb20-17" aria-hidden="true" tabindex="-1"></a>                y <span class="op">=</span> temp <span class="op">+</span> x<span class="op">;</span></span>
<span id="cb20-18"><a href="#cb20-18" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb20-19"><a href="#cb20-19" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>quit<span class="op">.</span><span class="fu">poll</span><span class="op">()</span> <span class="op">!=</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-20"><a href="#cb20-20" aria-hidden="true" tabindex="-1"></a>                <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;quit&quot;</span><span class="op">);</span></span>
<span id="cb20-21"><a href="#cb20-21" aria-hidden="true" tabindex="-1"></a>                <span class="cf">break</span><span class="op">;</span></span>
<span id="cb20-22"><a href="#cb20-22" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb20-23"><a href="#cb20-23" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb20-24"><a href="#cb20-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-25"><a href="#cb20-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-26"><a href="#cb20-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-27"><a href="#cb20-27" aria-hidden="true" tabindex="-1"></a>        var queue <span class="op">=</span> <span class="kw">new</span> <span class="bu">ArrayBlockingQueue</span><span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;(</span><span class="dv">1</span><span class="op">);</span></span>
<span id="cb20-28"><a href="#cb20-28" aria-hidden="true" tabindex="-1"></a>        var quit <span class="op">=</span> <span class="kw">new</span> <span class="bu">ArrayBlockingQueue</span><span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;(</span><span class="dv">1</span><span class="op">);</span></span>
<span id="cb20-29"><a href="#cb20-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-30"><a href="#cb20-30" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span>var executor <span class="op">=</span> </span>
<span id="cb20-31"><a href="#cb20-31" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Executors</span><span class="op">.</span><span class="fu">newVirtualThreadPerTaskExecutor</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb20-32"><a href="#cb20-32" aria-hidden="true" tabindex="-1"></a>            executor<span class="op">.</span><span class="fu">submit</span><span class="op">(()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb20-33"><a href="#cb20-33" aria-hidden="true" tabindex="-1"></a>                <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">10</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb20-34"><a href="#cb20-34" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>queue<span class="op">.</span><span class="fu">take</span><span class="op">());</span></span>
<span id="cb20-35"><a href="#cb20-35" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb20-36"><a href="#cb20-36" aria-hidden="true" tabindex="-1"></a>                quit<span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="dv">0</span><span class="op">);</span></span>
<span id="cb20-37"><a href="#cb20-37" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb20-38"><a href="#cb20-38" aria-hidden="true" tabindex="-1"></a>            <span class="op">});</span></span>
<span id="cb20-39"><a href="#cb20-39" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-40"><a href="#cb20-40" aria-hidden="true" tabindex="-1"></a>            <span class="fu">fibonacci</span><span class="op">(</span>queue<span class="op">,</span> quit<span class="op">);</span></span>
<span id="cb20-41"><a href="#cb20-41" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb20-42"><a href="#cb20-42" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-43"><a href="#cb20-43" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb21"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>SelectQueues<span class="op">.</span><span class="fu">main</span><span class="op">(</span><span class="kw">new</span> <span class="bu">String</span><span class="op">[]{});</span></span></code></pre></div>
<p>I'm unsure for what purpose the Go version uses a channel of integers as its quit mechanism. In Java it is more natural to use something like a shared <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/atomic/AtomicBoolean.html"><code>AtomicBoolean</code></a> as a signal for shutdowwn.</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">ArrayBlockingQueue</span><span class="op">;</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">BlockingQueue</span><span class="op">;</span></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">Executors</span><span class="op">;</span></span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">atomic</span><span class="op">.</span><span class="im">AtomicBoolean</span><span class="op">;</span></span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> SelectQueues <span class="op">{</span></span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">SelectQueues</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">void</span> <span class="fu">fibonacci</span><span class="op">(</span><span class="bu">BlockingQueue</span><span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;</span> queue<span class="op">,</span></span>
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a>                          <span class="bu">AtomicBoolean</span> quit<span class="op">)</span> <span class="op">{</span></span>
<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> x <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> y <span class="op">=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb22-13"><a href="#cb22-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-14"><a href="#cb22-14" aria-hidden="true" tabindex="-1"></a>        <span class="cf">while</span> <span class="op">(!</span>quit<span class="op">.</span><span class="fu">get</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb22-15"><a href="#cb22-15" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>queue<span class="op">.</span><span class="fu">offer</span><span class="op">(</span>x<span class="op">))</span> <span class="op">{</span></span>
<span id="cb22-16"><a href="#cb22-16" aria-hidden="true" tabindex="-1"></a>                <span class="dt">int</span> temp <span class="op">=</span> x<span class="op">;</span></span>
<span id="cb22-17"><a href="#cb22-17" aria-hidden="true" tabindex="-1"></a>                x <span class="op">=</span> y<span class="op">;</span></span>
<span id="cb22-18"><a href="#cb22-18" aria-hidden="true" tabindex="-1"></a>                y <span class="op">=</span> temp <span class="op">+</span> x<span class="op">;</span></span>
<span id="cb22-19"><a href="#cb22-19" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb22-20"><a href="#cb22-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb22-21"><a href="#cb22-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-22"><a href="#cb22-22" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;quit&quot;</span><span class="op">);</span></span>
<span id="cb22-23"><a href="#cb22-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb22-24"><a href="#cb22-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-25"><a href="#cb22-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="kw">throws</span> <span class="bu">InterruptedException</span> <span class="op">{</span></span>
<span id="cb22-26"><a href="#cb22-26" aria-hidden="true" tabindex="-1"></a>        var queue <span class="op">=</span> <span class="kw">new</span> <span class="bu">ArrayBlockingQueue</span><span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;(</span><span class="dv">1</span><span class="op">);</span></span>
<span id="cb22-27"><a href="#cb22-27" aria-hidden="true" tabindex="-1"></a>        var quit <span class="op">=</span> <span class="kw">new</span> <span class="bu">AtomicBoolean</span><span class="op">(</span><span class="kw">false</span><span class="op">);</span></span>
<span id="cb22-28"><a href="#cb22-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-29"><a href="#cb22-29" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span>var executor <span class="op">=</span> <span class="bu">Executors</span><span class="op">.</span><span class="fu">newVirtualThreadPerTaskExecutor</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb22-30"><a href="#cb22-30" aria-hidden="true" tabindex="-1"></a>            executor<span class="op">.</span><span class="fu">submit</span><span class="op">(()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb22-31"><a href="#cb22-31" aria-hidden="true" tabindex="-1"></a>                <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">10</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb22-32"><a href="#cb22-32" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>queue<span class="op">.</span><span class="fu">take</span><span class="op">());</span></span>
<span id="cb22-33"><a href="#cb22-33" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb22-34"><a href="#cb22-34" aria-hidden="true" tabindex="-1"></a>                quit<span class="op">.</span><span class="fu">set</span><span class="op">(</span><span class="kw">true</span><span class="op">);</span></span>
<span id="cb22-35"><a href="#cb22-35" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb22-36"><a href="#cb22-36" aria-hidden="true" tabindex="-1"></a>            <span class="op">});</span></span>
<span id="cb22-37"><a href="#cb22-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-38"><a href="#cb22-38" aria-hidden="true" tabindex="-1"></a>            <span class="fu">fibonacci</span><span class="op">(</span>queue<span class="op">,</span> quit<span class="op">);</span></span>
<span id="cb22-39"><a href="#cb22-39" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb22-40"><a href="#cb22-40" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb22-41"><a href="#cb22-41" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>If it were a situation with multiple "one shot" queues then <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/CompletableFuture.html#anyOf(java.util.concurrent.CompletableFuture...)"><code>CompletableFuture#anyOf</code></a> and similar methods might suffice.</p>
<h2 id="example-6-default-selection">Example 6. Default Selection</h2>
<p><a href="https://go.dev/tour/concurrency/6">https://go.dev/tour/concurrency/6</a></p>
<div class="sourceCode" id="cb23"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span> main</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="op">(</span></span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;fmt&quot;</span></span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;time&quot;</span></span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a><span class="op">)</span></span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb23-9"><a href="#cb23-9" aria-hidden="true" tabindex="-1"></a>    tick <span class="op">:=</span> time<span class="op">.</span>Tick<span class="op">(</span><span class="dv">100</span> <span class="op">*</span> time<span class="op">.</span>Millisecond<span class="op">)</span></span>
<span id="cb23-10"><a href="#cb23-10" aria-hidden="true" tabindex="-1"></a>    boom <span class="op">:=</span> time<span class="op">.</span>After<span class="op">(</span><span class="dv">500</span> <span class="op">*</span> time<span class="op">.</span>Millisecond<span class="op">)</span></span>
<span id="cb23-11"><a href="#cb23-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">for</span> <span class="op">{</span></span>
<span id="cb23-12"><a href="#cb23-12" aria-hidden="true" tabindex="-1"></a>        <span class="kw">select</span> <span class="op">{</span></span>
<span id="cb23-13"><a href="#cb23-13" aria-hidden="true" tabindex="-1"></a>        <span class="kw">case</span> <span class="op">&lt;-</span>tick<span class="op">:</span></span>
<span id="cb23-14"><a href="#cb23-14" aria-hidden="true" tabindex="-1"></a>            fmt<span class="op">.</span>Println<span class="op">(</span><span class="st">&quot;tick.&quot;</span><span class="op">)</span></span>
<span id="cb23-15"><a href="#cb23-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">case</span> <span class="op">&lt;-</span>boom<span class="op">:</span></span>
<span id="cb23-16"><a href="#cb23-16" aria-hidden="true" tabindex="-1"></a>            fmt<span class="op">.</span>Println<span class="op">(</span><span class="st">&quot;BOOM!&quot;</span><span class="op">)</span></span>
<span id="cb23-17"><a href="#cb23-17" aria-hidden="true" tabindex="-1"></a>            <span class="kw">return</span></span>
<span id="cb23-18"><a href="#cb23-18" aria-hidden="true" tabindex="-1"></a>        <span class="kw">default</span><span class="op">:</span></span>
<span id="cb23-19"><a href="#cb23-19" aria-hidden="true" tabindex="-1"></a>            fmt<span class="op">.</span>Println<span class="op">(</span><span class="st">&quot;    .&quot;</span><span class="op">)</span></span>
<span id="cb23-20"><a href="#cb23-20" aria-hidden="true" tabindex="-1"></a>            time<span class="op">.</span>Sleep<span class="op">(</span><span class="dv">50</span> <span class="op">*</span> time<span class="op">.</span>Millisecond<span class="op">)</span></span>
<span id="cb23-21"><a href="#cb23-21" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb23-22"><a href="#cb23-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb23-23"><a href="#cb23-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>There isn't a novel transformation of this default case syntax, but it is worth noting how Go's time library directly returns its channels as the mechanism for handling delays.</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">time</span><span class="op">.</span><span class="im">Duration</span><span class="op">;</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">time</span><span class="op">.</span><span class="im">Instant</span><span class="op">;</span></span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">ArrayBlockingQueue</span><span class="op">;</span></span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">Executors</span><span class="op">;</span></span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> GreenThreadDress <span class="op">{</span></span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">GreenThreadDress</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> </span>
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a>            <span class="kw">throws</span> <span class="bu">InterruptedException</span> <span class="op">{</span></span>
<span id="cb24-11"><a href="#cb24-11" aria-hidden="true" tabindex="-1"></a>        var executor <span class="op">=</span> </span>
<span id="cb24-12"><a href="#cb24-12" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Executors</span><span class="op">.</span><span class="fu">newVirtualThreadPerTaskExecutor</span><span class="op">();</span></span>
<span id="cb24-13"><a href="#cb24-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb24-14"><a href="#cb24-14" aria-hidden="true" tabindex="-1"></a>            var tick <span class="op">=</span> <span class="kw">new</span> <span class="bu">ArrayBlockingQueue</span><span class="op">&lt;</span>Instant<span class="op">&gt;(</span><span class="dv">1</span><span class="op">);</span></span>
<span id="cb24-15"><a href="#cb24-15" aria-hidden="true" tabindex="-1"></a>            var boom <span class="op">=</span> <span class="kw">new</span> <span class="bu">ArrayBlockingQueue</span><span class="op">&lt;</span>Instant<span class="op">&gt;(</span><span class="dv">1</span><span class="op">);</span></span>
<span id="cb24-16"><a href="#cb24-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-17"><a href="#cb24-17" aria-hidden="true" tabindex="-1"></a>            executor<span class="op">.</span><span class="fu">submit</span><span class="op">(()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb24-18"><a href="#cb24-18" aria-hidden="true" tabindex="-1"></a>                <span class="cf">while</span> <span class="op">(</span><span class="kw">true</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb24-19"><a href="#cb24-19" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">Thread</span><span class="op">.</span><span class="fu">sleep</span><span class="op">(</span><span class="bu">Duration</span><span class="op">.</span><span class="fu">ofMillis</span><span class="op">(</span><span class="dv">100</span><span class="op">));</span></span>
<span id="cb24-20"><a href="#cb24-20" aria-hidden="true" tabindex="-1"></a>                    tick<span class="op">.</span><span class="fu">put</span><span class="op">(</span>Instant<span class="op">.</span><span class="fu">now</span><span class="op">());</span></span>
<span id="cb24-21"><a href="#cb24-21" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb24-22"><a href="#cb24-22" aria-hidden="true" tabindex="-1"></a>            <span class="op">});</span></span>
<span id="cb24-23"><a href="#cb24-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-24"><a href="#cb24-24" aria-hidden="true" tabindex="-1"></a>            executor<span class="op">.</span><span class="fu">submit</span><span class="op">(()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb24-25"><a href="#cb24-25" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Thread</span><span class="op">.</span><span class="fu">sleep</span><span class="op">(</span><span class="dv">500</span><span class="op">);</span></span>
<span id="cb24-26"><a href="#cb24-26" aria-hidden="true" tabindex="-1"></a>                boom<span class="op">.</span><span class="fu">put</span><span class="op">(</span>Instant<span class="op">.</span><span class="fu">now</span><span class="op">());</span></span>
<span id="cb24-27"><a href="#cb24-27" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb24-28"><a href="#cb24-28" aria-hidden="true" tabindex="-1"></a>            <span class="op">});</span></span>
<span id="cb24-29"><a href="#cb24-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-30"><a href="#cb24-30" aria-hidden="true" tabindex="-1"></a>            <span class="cf">while</span> <span class="op">(</span><span class="kw">true</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb24-31"><a href="#cb24-31" aria-hidden="true" tabindex="-1"></a>                <span class="cf">if</span> <span class="op">(</span>tick<span class="op">.</span><span class="fu">poll</span><span class="op">()</span> <span class="op">!=</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb24-32"><a href="#cb24-32" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;tick.&quot;</span><span class="op">);</span></span>
<span id="cb24-33"><a href="#cb24-33" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb24-34"><a href="#cb24-34" aria-hidden="true" tabindex="-1"></a>                <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>boom<span class="op">.</span><span class="fu">poll</span><span class="op">()</span> <span class="op">!=</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb24-35"><a href="#cb24-35" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;BOOM!&quot;</span><span class="op">);</span></span>
<span id="cb24-36"><a href="#cb24-36" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">break</span><span class="op">;</span></span>
<span id="cb24-37"><a href="#cb24-37" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb24-38"><a href="#cb24-38" aria-hidden="true" tabindex="-1"></a>                <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb24-39"><a href="#cb24-39" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;    .&quot;</span><span class="op">);</span></span>
<span id="cb24-40"><a href="#cb24-40" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">Thread</span><span class="op">.</span><span class="fu">sleep</span><span class="op">(</span><span class="bu">Duration</span><span class="op">.</span><span class="fu">ofMillis</span><span class="op">(</span><span class="dv">50</span><span class="op">));</span></span>
<span id="cb24-41"><a href="#cb24-41" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb24-42"><a href="#cb24-42" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb24-43"><a href="#cb24-43" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">finally</span> <span class="op">{</span></span>
<span id="cb24-44"><a href="#cb24-44" aria-hidden="true" tabindex="-1"></a>            executor<span class="op">.</span><span class="fu">shutdownNow</span><span class="op">();</span></span>
<span id="cb24-45"><a href="#cb24-45" aria-hidden="true" tabindex="-1"></a>            executor<span class="op">.</span><span class="fu">close</span><span class="op">();</span></span>
<span id="cb24-46"><a href="#cb24-46" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb24-47"><a href="#cb24-47" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb24-48"><a href="#cb24-48" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb25"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a>GreenThreadDress<span class="op">.</span><span class="fu">main</span><span class="op">(</span><span class="kw">new</span> <span class="bu">String</span><span class="op">[]{});</span></span></code></pre></div>
<p>Here we rely on the behavior of <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/ExecutorService.html#shutdownNow()"><code>ExecutorService#shutdownNow</code></a> to interrupt the task pushing to the <code>tick</code> queue. Unlike with the built in Go <a href="https://pkg.go.dev/time#Tick"><code>time.Tick</code></a> where the underlying goroutine is never cancelled and is a "leak."</p>
<h2 id="example-7-equivalent-binary-trees">Example 7: Equivalent Binary Trees</h2>
<p><a href="https://go.dev/tour/concurrency/7">https://go.dev/tour/concurrency/7</a> <a href="https://go.dev/tour/concurrency/8">https://go.dev/tour/concurrency/8</a></p>
<div class="sourceCode" id="cb26"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span> main</span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="st">&quot;golang.org/x/tour/tree&quot;</span></span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a><span class="co">// Walk walks the tree t sending all values</span></span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a><span class="co">// from the tree to the channel ch.</span></span>
<span id="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> Walk<span class="op">(</span>t <span class="op">*</span>tree<span class="op">.</span>Tree<span class="op">,</span> ch <span class="kw">chan</span> <span class="dt">int</span><span class="op">)</span></span>
<span id="cb26-8"><a href="#cb26-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-9"><a href="#cb26-9" aria-hidden="true" tabindex="-1"></a><span class="co">// Same determines whether the trees</span></span>
<span id="cb26-10"><a href="#cb26-10" aria-hidden="true" tabindex="-1"></a><span class="co">// t1 and t2 contain the same values.</span></span>
<span id="cb26-11"><a href="#cb26-11" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> Same<span class="op">(</span>t1<span class="op">,</span> t2 <span class="op">*</span>tree<span class="op">.</span>Tree<span class="op">)</span> <span class="dt">bool</span></span>
<span id="cb26-12"><a href="#cb26-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-13"><a href="#cb26-13" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb26-14"><a href="#cb26-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This one is a little bit different since its not a straight example, but instead a challenge you are meant to complete.</p>
<p>A full solution can be found on <a href="https://stackoverflow.com/questions/12224042/go-tour-exercise-7-binary-trees-equivalence">this StackOverflow question</a>.</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span> main</span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="st">&quot;fmt&quot;</span></span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="st">&quot;golang.org/x/tour/tree&quot;</span></span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-6"><a href="#cb27-6" aria-hidden="true" tabindex="-1"></a><span class="co">// Walk walks the tree t sending all values</span></span>
<span id="cb27-7"><a href="#cb27-7" aria-hidden="true" tabindex="-1"></a><span class="co">// from the tree to the channel ch.</span></span>
<span id="cb27-8"><a href="#cb27-8" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> Walk<span class="op">(</span>t <span class="op">*</span>tree<span class="op">.</span>Tree<span class="op">,</span> ch <span class="kw">chan</span> <span class="dt">int</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb27-9"><a href="#cb27-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">var</span> walker <span class="kw">func</span><span class="op">(</span>t <span class="op">*</span>tree<span class="op">.</span>Tree<span class="op">)</span></span>
<span id="cb27-10"><a href="#cb27-10" aria-hidden="true" tabindex="-1"></a>    walker <span class="op">=</span> <span class="kw">func</span> <span class="op">(</span>t <span class="op">*</span>tree<span class="op">.</span>Tree<span class="op">)</span> <span class="op">{</span></span>
<span id="cb27-11"><a href="#cb27-11" aria-hidden="true" tabindex="-1"></a>        <span class="kw">if</span> <span class="op">(</span>t <span class="op">==</span> <span class="ot">nil</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb27-12"><a href="#cb27-12" aria-hidden="true" tabindex="-1"></a>            <span class="kw">return</span></span>
<span id="cb27-13"><a href="#cb27-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb27-14"><a href="#cb27-14" aria-hidden="true" tabindex="-1"></a>        walker<span class="op">(</span>t<span class="op">.</span>Left<span class="op">)</span></span>
<span id="cb27-15"><a href="#cb27-15" aria-hidden="true" tabindex="-1"></a>        ch <span class="op">&lt;-</span> t<span class="op">.</span>Value</span>
<span id="cb27-16"><a href="#cb27-16" aria-hidden="true" tabindex="-1"></a>        walker<span class="op">(</span>t<span class="op">.</span>Right<span class="op">)</span></span>
<span id="cb27-17"><a href="#cb27-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb27-18"><a href="#cb27-18" aria-hidden="true" tabindex="-1"></a>    walker<span class="op">(</span>t<span class="op">)</span></span>
<span id="cb27-19"><a href="#cb27-19" aria-hidden="true" tabindex="-1"></a>    <span class="bu">close</span><span class="op">(</span>ch<span class="op">)</span></span>
<span id="cb27-20"><a href="#cb27-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb27-21"><a href="#cb27-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-22"><a href="#cb27-22" aria-hidden="true" tabindex="-1"></a><span class="co">// Same determines whether the trees</span></span>
<span id="cb27-23"><a href="#cb27-23" aria-hidden="true" tabindex="-1"></a><span class="co">// t1 and t2 contain the same values.</span></span>
<span id="cb27-24"><a href="#cb27-24" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> Same<span class="op">(</span>t1<span class="op">,</span> t2 <span class="op">*</span>tree<span class="op">.</span>Tree<span class="op">)</span> <span class="dt">bool</span> <span class="op">{</span></span>
<span id="cb27-25"><a href="#cb27-25" aria-hidden="true" tabindex="-1"></a>    ch1<span class="op">,</span> ch2 <span class="op">:=</span> <span class="bu">make</span><span class="op">(</span><span class="kw">chan</span> <span class="dt">int</span><span class="op">),</span> <span class="bu">make</span><span class="op">(</span><span class="kw">chan</span> <span class="dt">int</span><span class="op">)</span></span>
<span id="cb27-26"><a href="#cb27-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-27"><a href="#cb27-27" aria-hidden="true" tabindex="-1"></a>    <span class="kw">go</span> Walk<span class="op">(</span>t1<span class="op">,</span> ch1<span class="op">)</span></span>
<span id="cb27-28"><a href="#cb27-28" aria-hidden="true" tabindex="-1"></a>    <span class="kw">go</span> Walk<span class="op">(</span>t2<span class="op">,</span> ch2<span class="op">)</span></span>
<span id="cb27-29"><a href="#cb27-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-30"><a href="#cb27-30" aria-hidden="true" tabindex="-1"></a>    <span class="kw">for</span> <span class="op">{</span></span>
<span id="cb27-31"><a href="#cb27-31" aria-hidden="true" tabindex="-1"></a>        v1<span class="op">,</span>ok1 <span class="op">:=</span> <span class="op">&lt;-</span> ch1</span>
<span id="cb27-32"><a href="#cb27-32" aria-hidden="true" tabindex="-1"></a>        v2<span class="op">,</span>ok2 <span class="op">:=</span> <span class="op">&lt;-</span> ch2</span>
<span id="cb27-33"><a href="#cb27-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-34"><a href="#cb27-34" aria-hidden="true" tabindex="-1"></a>        <span class="kw">if</span> v1 <span class="op">!=</span> v2 <span class="op">||</span> ok1 <span class="op">!=</span> ok2 <span class="op">{</span></span>
<span id="cb27-35"><a href="#cb27-35" aria-hidden="true" tabindex="-1"></a>            <span class="kw">return</span> <span class="ot">false</span></span>
<span id="cb27-36"><a href="#cb27-36" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb27-37"><a href="#cb27-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-38"><a href="#cb27-38" aria-hidden="true" tabindex="-1"></a>        <span class="kw">if</span> <span class="op">!</span>ok1 <span class="op">{</span></span>
<span id="cb27-39"><a href="#cb27-39" aria-hidden="true" tabindex="-1"></a>            <span class="kw">break</span></span>
<span id="cb27-40"><a href="#cb27-40" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb27-41"><a href="#cb27-41" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb27-42"><a href="#cb27-42" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-43"><a href="#cb27-43" aria-hidden="true" tabindex="-1"></a>    <span class="kw">return</span> <span class="ot">true</span></span>
<span id="cb27-44"><a href="#cb27-44" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb27-45"><a href="#cb27-45" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-46"><a href="#cb27-46" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb27-47"><a href="#cb27-47" aria-hidden="true" tabindex="-1"></a>    fmt<span class="op">.</span>Println<span class="op">(</span><span class="st">&quot;1 and 1 same: &quot;</span><span class="op">,</span> Same<span class="op">(</span>tree<span class="op">.</span>New<span class="op">(</span><span class="dv">1</span><span class="op">),</span> tree<span class="op">.</span>New<span class="op">(</span><span class="dv">1</span><span class="op">)))</span></span>
<span id="cb27-48"><a href="#cb27-48" aria-hidden="true" tabindex="-1"></a>    fmt<span class="op">.</span>Println<span class="op">(</span><span class="st">&quot;1 and 2 same: &quot;</span><span class="op">,</span> Same<span class="op">(</span>tree<span class="op">.</span>New<span class="op">(</span><span class="dv">1</span><span class="op">),</span> tree<span class="op">.</span>New<span class="op">(</span><span class="dv">2</span><span class="op">)))</span></span>
<span id="cb27-49"><a href="#cb27-49" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-50"><a href="#cb27-50" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Where the <code>Tree</code> type is defined seperately <a href="https://cs.opensource.google/go/x/tour/+/master:tree/tree.go">here</a>.</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Copyright 2011 The Go Authors.  All rights reserved.</span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a><span class="co">// Use of this source code is governed by a BSD-style</span></span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a><span class="co">// license that can be found in the LICENSE file.</span></span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span> tree <span class="co">// import &quot;golang.org/x/tour/tree&quot;</span></span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="op">(</span></span>
<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;fmt&quot;</span></span>
<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;math/rand&quot;</span></span>
<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a><span class="op">)</span></span>
<span id="cb28-11"><a href="#cb28-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-12"><a href="#cb28-12" aria-hidden="true" tabindex="-1"></a><span class="co">// A Tree is a binary tree with integer values.</span></span>
<span id="cb28-13"><a href="#cb28-13" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> Tree <span class="kw">struct</span> <span class="op">{</span></span>
<span id="cb28-14"><a href="#cb28-14" aria-hidden="true" tabindex="-1"></a>    Left  <span class="op">*</span>Tree</span>
<span id="cb28-15"><a href="#cb28-15" aria-hidden="true" tabindex="-1"></a>    Value <span class="dt">int</span></span>
<span id="cb28-16"><a href="#cb28-16" aria-hidden="true" tabindex="-1"></a>    Right <span class="op">*</span>Tree</span>
<span id="cb28-17"><a href="#cb28-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb28-18"><a href="#cb28-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-19"><a href="#cb28-19" aria-hidden="true" tabindex="-1"></a><span class="co">// New returns a new, random binary tree holding the values k, 2k, ..., 10k.</span></span>
<span id="cb28-20"><a href="#cb28-20" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> New<span class="op">(</span>k <span class="dt">int</span><span class="op">)</span> <span class="op">*</span>Tree <span class="op">{</span></span>
<span id="cb28-21"><a href="#cb28-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">var</span> t <span class="op">*</span>Tree</span>
<span id="cb28-22"><a href="#cb28-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">for</span> _<span class="op">,</span> v <span class="op">:=</span> <span class="kw">range</span> rand<span class="op">.</span>Perm<span class="op">(</span><span class="dv">10</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-23"><a href="#cb28-23" aria-hidden="true" tabindex="-1"></a>        t <span class="op">=</span> insert<span class="op">(</span>t<span class="op">,</span> <span class="op">(</span><span class="dv">1</span><span class="op">+</span>v<span class="op">)*</span>k<span class="op">)</span></span>
<span id="cb28-24"><a href="#cb28-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-25"><a href="#cb28-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">return</span> t</span>
<span id="cb28-26"><a href="#cb28-26" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb28-27"><a href="#cb28-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-28"><a href="#cb28-28" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> insert<span class="op">(</span>t <span class="op">*</span>Tree<span class="op">,</span> v <span class="dt">int</span><span class="op">)</span> <span class="op">*</span>Tree <span class="op">{</span></span>
<span id="cb28-29"><a href="#cb28-29" aria-hidden="true" tabindex="-1"></a>    <span class="kw">if</span> t <span class="op">==</span> <span class="ot">nil</span> <span class="op">{</span></span>
<span id="cb28-30"><a href="#cb28-30" aria-hidden="true" tabindex="-1"></a>        <span class="kw">return</span> <span class="op">&amp;</span>Tree<span class="op">{</span><span class="ot">nil</span><span class="op">,</span> v<span class="op">,</span> <span class="ot">nil</span><span class="op">}</span></span>
<span id="cb28-31"><a href="#cb28-31" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-32"><a href="#cb28-32" aria-hidden="true" tabindex="-1"></a>    <span class="kw">if</span> v <span class="op">&lt;</span> t<span class="op">.</span>Value <span class="op">{</span></span>
<span id="cb28-33"><a href="#cb28-33" aria-hidden="true" tabindex="-1"></a>        t<span class="op">.</span>Left <span class="op">=</span> insert<span class="op">(</span>t<span class="op">.</span>Left<span class="op">,</span> v<span class="op">)</span></span>
<span id="cb28-34"><a href="#cb28-34" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="kw">else</span> <span class="op">{</span></span>
<span id="cb28-35"><a href="#cb28-35" aria-hidden="true" tabindex="-1"></a>        t<span class="op">.</span>Right <span class="op">=</span> insert<span class="op">(</span>t<span class="op">.</span>Right<span class="op">,</span> v<span class="op">)</span></span>
<span id="cb28-36"><a href="#cb28-36" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-37"><a href="#cb28-37" aria-hidden="true" tabindex="-1"></a>    <span class="kw">return</span> t</span>
<span id="cb28-38"><a href="#cb28-38" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb28-39"><a href="#cb28-39" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-40"><a href="#cb28-40" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> <span class="op">(</span>t <span class="op">*</span>Tree<span class="op">)</span> String<span class="op">()</span> <span class="dt">string</span> <span class="op">{</span></span>
<span id="cb28-41"><a href="#cb28-41" aria-hidden="true" tabindex="-1"></a>    <span class="kw">if</span> t <span class="op">==</span> <span class="ot">nil</span> <span class="op">{</span></span>
<span id="cb28-42"><a href="#cb28-42" aria-hidden="true" tabindex="-1"></a>        <span class="kw">return</span> <span class="st">&quot;()&quot;</span></span>
<span id="cb28-43"><a href="#cb28-43" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-44"><a href="#cb28-44" aria-hidden="true" tabindex="-1"></a>    s <span class="op">:=</span> <span class="st">&quot;&quot;</span></span>
<span id="cb28-45"><a href="#cb28-45" aria-hidden="true" tabindex="-1"></a>    <span class="kw">if</span> t<span class="op">.</span>Left <span class="op">!=</span> <span class="ot">nil</span> <span class="op">{</span></span>
<span id="cb28-46"><a href="#cb28-46" aria-hidden="true" tabindex="-1"></a>        s <span class="op">+=</span> t<span class="op">.</span>Left<span class="op">.</span>String<span class="op">()</span> <span class="op">+</span> <span class="st">&quot; &quot;</span></span>
<span id="cb28-47"><a href="#cb28-47" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-48"><a href="#cb28-48" aria-hidden="true" tabindex="-1"></a>    s <span class="op">+=</span> fmt<span class="op">.</span>Sprint<span class="op">(</span>t<span class="op">.</span>Value<span class="op">)</span></span>
<span id="cb28-49"><a href="#cb28-49" aria-hidden="true" tabindex="-1"></a>    <span class="kw">if</span> t<span class="op">.</span>Right <span class="op">!=</span> <span class="ot">nil</span> <span class="op">{</span></span>
<span id="cb28-50"><a href="#cb28-50" aria-hidden="true" tabindex="-1"></a>        s <span class="op">+=</span> <span class="st">&quot; &quot;</span> <span class="op">+</span> t<span class="op">.</span>Right<span class="op">.</span>String<span class="op">()</span></span>
<span id="cb28-51"><a href="#cb28-51" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-52"><a href="#cb28-52" aria-hidden="true" tabindex="-1"></a>    <span class="kw">return</span> <span class="st">&quot;(&quot;</span> <span class="op">+</span> s <span class="op">+</span> <span class="st">&quot;)&quot;</span></span>
<span id="cb28-53"><a href="#cb28-53" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>So before touching the concurrency bits we need to translate this <code>Tree</code> type.</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">Collections</span><span class="op">;</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">stream</span><span class="op">.</span><span class="im">Collectors</span><span class="op">;</span></span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">stream</span><span class="op">.</span><span class="im">IntStream</span><span class="op">;</span></span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> sealed <span class="kw">interface</span> Tree <span class="op">{</span></span>
<span id="cb29-6"><a href="#cb29-6" aria-hidden="true" tabindex="-1"></a>    Tree <span class="fu">insert</span><span class="op">(</span><span class="dt">int</span> v<span class="op">);</span></span>
<span id="cb29-7"><a href="#cb29-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-8"><a href="#cb29-8" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">NotEmpty</span><span class="op">(</span></span>
<span id="cb29-9"><a href="#cb29-9" aria-hidden="true" tabindex="-1"></a>            Tree left<span class="op">,</span></span>
<span id="cb29-10"><a href="#cb29-10" aria-hidden="true" tabindex="-1"></a>            <span class="dt">int</span> value<span class="op">,</span></span>
<span id="cb29-11"><a href="#cb29-11" aria-hidden="true" tabindex="-1"></a>            Tree right</span>
<span id="cb29-12"><a href="#cb29-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">implements</span> Tree <span class="op">{</span></span>
<span id="cb29-13"><a href="#cb29-13" aria-hidden="true" tabindex="-1"></a>        <span class="at">@Override</span></span>
<span id="cb29-14"><a href="#cb29-14" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Tree <span class="fu">insert</span><span class="op">(</span><span class="dt">int</span> v<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-15"><a href="#cb29-15" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>v <span class="op">&lt;</span> <span class="kw">this</span><span class="op">.</span><span class="fu">value</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-16"><a href="#cb29-16" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="kw">new</span> <span class="bu">NotEmpty</span><span class="op">(</span></span>
<span id="cb29-17"><a href="#cb29-17" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">this</span><span class="op">.</span><span class="fu">left</span><span class="op">.</span><span class="fu">insert</span><span class="op">(</span>v<span class="op">),</span></span>
<span id="cb29-18"><a href="#cb29-18" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">this</span><span class="op">.</span><span class="fu">value</span><span class="op">,</span></span>
<span id="cb29-19"><a href="#cb29-19" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">this</span><span class="op">.</span><span class="fu">right</span></span>
<span id="cb29-20"><a href="#cb29-20" aria-hidden="true" tabindex="-1"></a>                <span class="op">);</span></span>
<span id="cb29-21"><a href="#cb29-21" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb29-22"><a href="#cb29-22" aria-hidden="true" tabindex="-1"></a>            <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb29-23"><a href="#cb29-23" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="kw">new</span> <span class="bu">NotEmpty</span><span class="op">(</span></span>
<span id="cb29-24"><a href="#cb29-24" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">this</span><span class="op">.</span><span class="fu">left</span><span class="op">,</span></span>
<span id="cb29-25"><a href="#cb29-25" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">this</span><span class="op">.</span><span class="fu">value</span><span class="op">,</span></span>
<span id="cb29-26"><a href="#cb29-26" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">this</span><span class="op">.</span><span class="fu">right</span><span class="op">.</span><span class="fu">insert</span><span class="op">(</span>v<span class="op">)</span></span>
<span id="cb29-27"><a href="#cb29-27" aria-hidden="true" tabindex="-1"></a>                <span class="op">);</span></span>
<span id="cb29-28"><a href="#cb29-28" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb29-29"><a href="#cb29-29" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb29-30"><a href="#cb29-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-31"><a href="#cb29-31" aria-hidden="true" tabindex="-1"></a>        <span class="at">@Override</span></span>
<span id="cb29-32"><a href="#cb29-32" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="bu">String</span> <span class="fu">toString</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb29-33"><a href="#cb29-33" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="st">&quot;( &quot;</span> <span class="op">+</span></span>
<span id="cb29-34"><a href="#cb29-34" aria-hidden="true" tabindex="-1"></a>                <span class="kw">this</span><span class="op">.</span><span class="fu">left</span> <span class="op">+</span></span>
<span id="cb29-35"><a href="#cb29-35" aria-hidden="true" tabindex="-1"></a>                <span class="kw">this</span><span class="op">.</span><span class="fu">value</span> <span class="op">+</span></span>
<span id="cb29-36"><a href="#cb29-36" aria-hidden="true" tabindex="-1"></a>                <span class="kw">this</span><span class="op">.</span><span class="fu">right</span> <span class="op">+</span></span>
<span id="cb29-37"><a href="#cb29-37" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot; )&quot;</span><span class="op">;</span></span>
<span id="cb29-38"><a href="#cb29-38" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb29-39"><a href="#cb29-39" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb29-40"><a href="#cb29-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-41"><a href="#cb29-41" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">Empty</span><span class="op">()</span> <span class="kw">implements</span> Tree <span class="op">{</span></span>
<span id="cb29-42"><a href="#cb29-42" aria-hidden="true" tabindex="-1"></a>        <span class="at">@Override</span></span>
<span id="cb29-43"><a href="#cb29-43" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Tree <span class="fu">insert</span><span class="op">(</span><span class="dt">int</span> v<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-44"><a href="#cb29-44" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">new</span> <span class="bu">NotEmpty</span><span class="op">(</span><span class="kw">new</span> <span class="fu">Empty</span><span class="op">(),</span> v<span class="op">,</span> <span class="kw">new</span> <span class="fu">Empty</span><span class="op">());</span></span>
<span id="cb29-45"><a href="#cb29-45" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb29-46"><a href="#cb29-46" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-47"><a href="#cb29-47" aria-hidden="true" tabindex="-1"></a>        <span class="at">@Override</span></span>
<span id="cb29-48"><a href="#cb29-48" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="bu">String</span> <span class="fu">toString</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb29-49"><a href="#cb29-49" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="st">&quot;&quot;</span><span class="op">;</span></span>
<span id="cb29-50"><a href="#cb29-50" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb29-51"><a href="#cb29-51" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb29-52"><a href="#cb29-52" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-53"><a href="#cb29-53" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> Tree <span class="fu">random</span><span class="op">(</span><span class="dt">int</span> k<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-54"><a href="#cb29-54" aria-hidden="true" tabindex="-1"></a>        var vs <span class="op">=</span> IntStream<span class="op">.</span><span class="fu">range</span><span class="op">(</span><span class="dv">0</span><span class="op">,</span> <span class="dv">10</span><span class="op">)</span></span>
<span id="cb29-55"><a href="#cb29-55" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">boxed</span><span class="op">()</span></span>
<span id="cb29-56"><a href="#cb29-56" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">collect</span><span class="op">(</span>Collectors<span class="op">.</span><span class="fu">toList</span><span class="op">());</span></span>
<span id="cb29-57"><a href="#cb29-57" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Collections</span><span class="op">.</span><span class="fu">shuffle</span><span class="op">(</span>vs<span class="op">);</span></span>
<span id="cb29-58"><a href="#cb29-58" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb29-59"><a href="#cb29-59" aria-hidden="true" tabindex="-1"></a>        Tree t <span class="op">=</span> <span class="kw">new</span> <span class="fu">Empty</span><span class="op">();</span></span>
<span id="cb29-60"><a href="#cb29-60" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> v <span class="op">:</span> vs<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-61"><a href="#cb29-61" aria-hidden="true" tabindex="-1"></a>            t <span class="op">=</span> t<span class="op">.</span><span class="fu">insert</span><span class="op">((</span><span class="dv">1</span> <span class="op">+</span> v<span class="op">)</span> <span class="op">*</span> k<span class="op">);</span></span>
<span id="cb29-62"><a href="#cb29-62" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb29-63"><a href="#cb29-63" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> t<span class="op">;</span></span>
<span id="cb29-64"><a href="#cb29-64" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb29-65"><a href="#cb29-65" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>A 1-1 translation of the Go wouldn't be fun Java, so I opted to translate it instead to an immutable sum type. This won't affect the concurrent part other than a stronger conceptual guarentee that we can safely share the tree across multiple threads.</p>
<p>With this version the Go maps pretty straight forwardly to this.</p>
<div class="sourceCode" id="cb30"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">ArrayBlockingQueue</span><span class="op">;</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">BlockingQueue</span><span class="op">;</span></span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">Executors</span><span class="op">;</span></span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> TakeResult<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a>    record GotValue<span class="op">&lt;</span>T<span class="op">&gt;(</span>T value<span class="op">)</span> <span class="kw">implements</span> TakeResult<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">{}</span></span>
<span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a>    record NoValue<span class="op">&lt;</span>T<span class="op">&gt;()</span> <span class="kw">implements</span> TakeResult<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">{}</span></span>
<span id="cb30-8"><a href="#cb30-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb30-9"><a href="#cb30-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-10"><a href="#cb30-10" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> TreeWalker <span class="op">{</span></span>
<span id="cb30-11"><a href="#cb30-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">TreeWalker</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb30-12"><a href="#cb30-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-13"><a href="#cb30-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">walkHelper</span><span class="op">(</span></span>
<span id="cb30-14"><a href="#cb30-14" aria-hidden="true" tabindex="-1"></a>            Tree tree<span class="op">,</span></span>
<span id="cb30-15"><a href="#cb30-15" aria-hidden="true" tabindex="-1"></a>            <span class="bu">BlockingQueue</span><span class="op">&lt;</span>TakeResult<span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;&gt;</span> queue</span>
<span id="cb30-16"><a href="#cb30-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">throws</span> <span class="bu">InterruptedException</span> <span class="op">{</span></span>
<span id="cb30-17"><a href="#cb30-17" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>tree <span class="op">==</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb30-18"><a href="#cb30-18" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span><span class="op">;</span></span>
<span id="cb30-19"><a href="#cb30-19" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb30-20"><a href="#cb30-20" aria-hidden="true" tabindex="-1"></a>        <span class="fu">walkHelper</span><span class="op">(</span>tree<span class="op">.</span><span class="fu">left</span><span class="op">,</span> queue<span class="op">);</span></span>
<span id="cb30-21"><a href="#cb30-21" aria-hidden="true" tabindex="-1"></a>        queue<span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="kw">new</span> TakeResult<span class="op">.</span><span class="fu">GotValue</span><span class="op">&lt;&gt;(</span></span>
<span id="cb30-22"><a href="#cb30-22" aria-hidden="true" tabindex="-1"></a>                tree<span class="op">.</span><span class="fu">value</span></span>
<span id="cb30-23"><a href="#cb30-23" aria-hidden="true" tabindex="-1"></a>        <span class="op">));</span></span>
<span id="cb30-24"><a href="#cb30-24" aria-hidden="true" tabindex="-1"></a>        <span class="fu">walkHelper</span><span class="op">(</span>tree<span class="op">.</span><span class="fu">right</span><span class="op">,</span> queue<span class="op">);</span></span>
<span id="cb30-25"><a href="#cb30-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb30-26"><a href="#cb30-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-27"><a href="#cb30-27" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">void</span> <span class="fu">walk</span><span class="op">(</span></span>
<span id="cb30-28"><a href="#cb30-28" aria-hidden="true" tabindex="-1"></a>            Tree tree<span class="op">,</span></span>
<span id="cb30-29"><a href="#cb30-29" aria-hidden="true" tabindex="-1"></a>            <span class="bu">BlockingQueue</span><span class="op">&lt;</span>TakeResult<span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;&gt;</span> queue</span>
<span id="cb30-30"><a href="#cb30-30" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="kw">throws</span> <span class="bu">InterruptedException</span> <span class="op">{</span></span>
<span id="cb30-31"><a href="#cb30-31" aria-hidden="true" tabindex="-1"></a>        <span class="fu">walkHelper</span><span class="op">(</span>tree<span class="op">,</span> queue<span class="op">);</span></span>
<span id="cb30-32"><a href="#cb30-32" aria-hidden="true" tabindex="-1"></a>        queue<span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="kw">new</span> TakeResult<span class="op">.</span><span class="fu">NoValue</span><span class="op">&lt;&gt;());</span></span>
<span id="cb30-33"><a href="#cb30-33" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb30-34"><a href="#cb30-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-35"><a href="#cb30-35" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">boolean</span> <span class="fu">same</span><span class="op">(</span>Tree t1<span class="op">,</span> Tree t2<span class="op">)</span> </span>
<span id="cb30-36"><a href="#cb30-36" aria-hidden="true" tabindex="-1"></a>            <span class="kw">throws</span> <span class="bu">InterruptedException</span> <span class="op">{</span></span>
<span id="cb30-37"><a href="#cb30-37" aria-hidden="true" tabindex="-1"></a>        var queue1 <span class="op">=</span> <span class="kw">new</span> <span class="bu">ArrayBlockingQueue</span><span class="op">&lt;</span>TakeResult<span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;&gt;(</span><span class="dv">1</span><span class="op">);</span></span>
<span id="cb30-38"><a href="#cb30-38" aria-hidden="true" tabindex="-1"></a>        var queue2 <span class="op">=</span> <span class="kw">new</span> <span class="bu">ArrayBlockingQueue</span><span class="op">&lt;</span>TakeResult<span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;&gt;(</span><span class="dv">1</span><span class="op">);</span></span>
<span id="cb30-39"><a href="#cb30-39" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-40"><a href="#cb30-40" aria-hidden="true" tabindex="-1"></a>        var executor <span class="op">=</span></span>
<span id="cb30-41"><a href="#cb30-41" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Executors</span><span class="op">.</span><span class="fu">newVirtualThreadPerTaskExecutor</span><span class="op">();</span></span>
<span id="cb30-42"><a href="#cb30-42" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb30-43"><a href="#cb30-43" aria-hidden="true" tabindex="-1"></a>            executor<span class="op">.</span><span class="fu">submit</span><span class="op">(()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb30-44"><a href="#cb30-44" aria-hidden="true" tabindex="-1"></a>                <span class="fu">walk</span><span class="op">(</span>t1<span class="op">,</span> queue1<span class="op">);</span></span>
<span id="cb30-45"><a href="#cb30-45" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb30-46"><a href="#cb30-46" aria-hidden="true" tabindex="-1"></a>            <span class="op">});</span></span>
<span id="cb30-47"><a href="#cb30-47" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-48"><a href="#cb30-48" aria-hidden="true" tabindex="-1"></a>            executor<span class="op">.</span><span class="fu">submit</span><span class="op">(()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb30-49"><a href="#cb30-49" aria-hidden="true" tabindex="-1"></a>                <span class="fu">walk</span><span class="op">(</span>t2<span class="op">,</span> queue2<span class="op">);</span></span>
<span id="cb30-50"><a href="#cb30-50" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb30-51"><a href="#cb30-51" aria-hidden="true" tabindex="-1"></a>            <span class="op">});</span></span>
<span id="cb30-52"><a href="#cb30-52" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-53"><a href="#cb30-53" aria-hidden="true" tabindex="-1"></a>            <span class="cf">while</span> <span class="op">(</span><span class="kw">true</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb30-54"><a href="#cb30-54" aria-hidden="true" tabindex="-1"></a>                var result1 <span class="op">=</span> queue1<span class="op">.</span><span class="fu">take</span><span class="op">();</span></span>
<span id="cb30-55"><a href="#cb30-55" aria-hidden="true" tabindex="-1"></a>                var result2 <span class="op">=</span> queue2<span class="op">.</span><span class="fu">take</span><span class="op">();</span></span>
<span id="cb30-56"><a href="#cb30-56" aria-hidden="true" tabindex="-1"></a>                <span class="cf">if</span> <span class="op">(!</span>result1<span class="op">.</span><span class="fu">equals</span><span class="op">(</span>result2<span class="op">))</span> <span class="op">{</span></span>
<span id="cb30-57"><a href="#cb30-57" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">return</span> <span class="kw">false</span><span class="op">;</span></span>
<span id="cb30-58"><a href="#cb30-58" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb30-59"><a href="#cb30-59" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-60"><a href="#cb30-60" aria-hidden="true" tabindex="-1"></a>                <span class="cf">if</span> <span class="op">(</span>result1 <span class="kw">instanceof</span> TakeResult<span class="op">.</span><span class="fu">NoValue</span><span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;)</span> <span class="op">{</span></span>
<span id="cb30-61"><a href="#cb30-61" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">break</span><span class="op">;</span></span>
<span id="cb30-62"><a href="#cb30-62" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb30-63"><a href="#cb30-63" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb30-64"><a href="#cb30-64" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">true</span><span class="op">;</span></span>
<span id="cb30-65"><a href="#cb30-65" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">finally</span> <span class="op">{</span></span>
<span id="cb30-66"><a href="#cb30-66" aria-hidden="true" tabindex="-1"></a>            executor<span class="op">.</span><span class="fu">shutdownNow</span><span class="op">();</span></span>
<span id="cb30-67"><a href="#cb30-67" aria-hidden="true" tabindex="-1"></a>            executor<span class="op">.</span><span class="fu">close</span><span class="op">();</span></span>
<span id="cb30-68"><a href="#cb30-68" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb30-69"><a href="#cb30-69" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb30-70"><a href="#cb30-70" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-71"><a href="#cb30-71" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> </span>
<span id="cb30-72"><a href="#cb30-72" aria-hidden="true" tabindex="-1"></a>            <span class="kw">throws</span> <span class="bu">InterruptedException</span> <span class="op">{</span></span>
<span id="cb30-73"><a href="#cb30-73" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span></span>
<span id="cb30-74"><a href="#cb30-74" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;1 and 1 same: &quot;</span> <span class="op">+</span> </span>
<span id="cb30-75"><a href="#cb30-75" aria-hidden="true" tabindex="-1"></a>            <span class="fu">same</span><span class="op">(</span>Tree<span class="op">.</span><span class="fu">random</span><span class="op">(</span><span class="dv">1</span><span class="op">),</span> Tree<span class="op">.</span><span class="fu">random</span><span class="op">(</span><span class="dv">1</span><span class="op">))</span></span>
<span id="cb30-76"><a href="#cb30-76" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb30-77"><a href="#cb30-77" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span></span>
<span id="cb30-78"><a href="#cb30-78" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;1 and 2 same: &quot;</span> <span class="op">+</span> </span>
<span id="cb30-79"><a href="#cb30-79" aria-hidden="true" tabindex="-1"></a>            <span class="fu">same</span><span class="op">(</span>Tree<span class="op">.</span><span class="fu">random</span><span class="op">(</span><span class="dv">1</span><span class="op">),</span> Tree<span class="op">.</span><span class="fu">random</span><span class="op">(</span><span class="dv">2</span><span class="op">))</span></span>
<span id="cb30-80"><a href="#cb30-80" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb30-81"><a href="#cb30-81" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb30-82"><a href="#cb30-82" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb31"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a>TreeWalker<span class="op">.</span><span class="fu">main</span><span class="op">(</span><span class="kw">new</span> <span class="bu">String</span><span class="op">[]{});</span></span></code></pre></div>
<p>We use the same tricks as before to emulate a closable queue with <code>TakeResult</code>. Then we translate the <code>select</code> statement to a loop calling <code>offer</code> and <code>poll</code>.</p>
<p>The example Go solution had a recursive local closure for walk. While technically possible via some wizardry, its more straight forward in Java to make a helper method.</p>
<p>There is also a reliance on the walk tasks responding correctly to <code>shutdownNow</code>. If they did not, <code>executor.close()</code> would hang and the scope wouldn't exit.</p>
<h2 id="example-8-syncmutex">Example 8: sync.Mutex</h2>
<p><a href="https://go.dev/tour/concurrency/9">https://go.dev/tour/concurrency/9</a></p>
<div class="sourceCode" id="cb32"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span> main</span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="op">(</span></span>
<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;fmt&quot;</span></span>
<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;sync&quot;</span></span>
<span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;time&quot;</span></span>
<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a><span class="op">)</span></span>
<span id="cb32-8"><a href="#cb32-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-9"><a href="#cb32-9" aria-hidden="true" tabindex="-1"></a><span class="co">// SafeCounter is safe to use concurrently.</span></span>
<span id="cb32-10"><a href="#cb32-10" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> SafeCounter <span class="kw">struct</span> <span class="op">{</span></span>
<span id="cb32-11"><a href="#cb32-11" aria-hidden="true" tabindex="-1"></a>    mu sync<span class="op">.</span>Mutex</span>
<span id="cb32-12"><a href="#cb32-12" aria-hidden="true" tabindex="-1"></a>    v  <span class="kw">map</span><span class="op">[</span><span class="dt">string</span><span class="op">]</span><span class="dt">int</span></span>
<span id="cb32-13"><a href="#cb32-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb32-14"><a href="#cb32-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-15"><a href="#cb32-15" aria-hidden="true" tabindex="-1"></a><span class="co">// Inc increments the counter for the given key.</span></span>
<span id="cb32-16"><a href="#cb32-16" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> <span class="op">(</span>c <span class="op">*</span>SafeCounter<span class="op">)</span> Inc<span class="op">(</span>key <span class="dt">string</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb32-17"><a href="#cb32-17" aria-hidden="true" tabindex="-1"></a>    c<span class="op">.</span>mu<span class="op">.</span>Lock<span class="op">()</span></span>
<span id="cb32-18"><a href="#cb32-18" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Lock so only one goroutine at a time can access the map c.v.</span></span>
<span id="cb32-19"><a href="#cb32-19" aria-hidden="true" tabindex="-1"></a>    c<span class="op">.</span>v<span class="op">[</span>key<span class="op">]++</span></span>
<span id="cb32-20"><a href="#cb32-20" aria-hidden="true" tabindex="-1"></a>    c<span class="op">.</span>mu<span class="op">.</span>Unlock<span class="op">()</span></span>
<span id="cb32-21"><a href="#cb32-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb32-22"><a href="#cb32-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-23"><a href="#cb32-23" aria-hidden="true" tabindex="-1"></a><span class="co">// Value returns the current value of the counter for the given key.</span></span>
<span id="cb32-24"><a href="#cb32-24" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> <span class="op">(</span>c <span class="op">*</span>SafeCounter<span class="op">)</span> Value<span class="op">(</span>key <span class="dt">string</span><span class="op">)</span> <span class="dt">int</span> <span class="op">{</span></span>
<span id="cb32-25"><a href="#cb32-25" aria-hidden="true" tabindex="-1"></a>    c<span class="op">.</span>mu<span class="op">.</span>Lock<span class="op">()</span></span>
<span id="cb32-26"><a href="#cb32-26" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Lock so only one goroutine at a time can access the map c.v.</span></span>
<span id="cb32-27"><a href="#cb32-27" aria-hidden="true" tabindex="-1"></a>    <span class="kw">defer</span> c<span class="op">.</span>mu<span class="op">.</span>Unlock<span class="op">()</span></span>
<span id="cb32-28"><a href="#cb32-28" aria-hidden="true" tabindex="-1"></a>    <span class="kw">return</span> c<span class="op">.</span>v<span class="op">[</span>key<span class="op">]</span></span>
<span id="cb32-29"><a href="#cb32-29" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb32-30"><a href="#cb32-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-31"><a href="#cb32-31" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb32-32"><a href="#cb32-32" aria-hidden="true" tabindex="-1"></a>    c <span class="op">:=</span> SafeCounter<span class="op">{</span>v<span class="op">:</span> <span class="bu">make</span><span class="op">(</span><span class="kw">map</span><span class="op">[</span><span class="dt">string</span><span class="op">]</span><span class="dt">int</span><span class="op">)}</span></span>
<span id="cb32-33"><a href="#cb32-33" aria-hidden="true" tabindex="-1"></a>    <span class="kw">for</span> i <span class="op">:=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">1000</span><span class="op">;</span> i<span class="op">++</span> <span class="op">{</span></span>
<span id="cb32-34"><a href="#cb32-34" aria-hidden="true" tabindex="-1"></a>        <span class="kw">go</span> c<span class="op">.</span>Inc<span class="op">(</span><span class="st">&quot;somekey&quot;</span><span class="op">)</span></span>
<span id="cb32-35"><a href="#cb32-35" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb32-36"><a href="#cb32-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-37"><a href="#cb32-37" aria-hidden="true" tabindex="-1"></a>    time<span class="op">.</span>Sleep<span class="op">(</span>time<span class="op">.</span>Second<span class="op">)</span></span>
<span id="cb32-38"><a href="#cb32-38" aria-hidden="true" tabindex="-1"></a>    fmt<span class="op">.</span>Println<span class="op">(</span>c<span class="op">.</span>Value<span class="op">(</span><span class="st">&quot;somekey&quot;</span><span class="op">))</span></span>
<span id="cb32-39"><a href="#cb32-39" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Java has a direct analogue to <a href="https://pkg.go.dev/sync#Mutex"><code>sync.Mutex</code></a> in <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/locks/ReentrantLock.html"><code>ReentrantLock</code></a>. We can make this same program without much issue.</p>
<div class="sourceCode" id="cb33"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">time</span><span class="op">.</span><span class="im">Duration</span><span class="op">;</span></span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">HashMap</span><span class="op">;</span></span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">Map</span><span class="op">;</span></span>
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">locks</span><span class="op">.</span><span class="im">ReentrantLock</span><span class="op">;</span></span>
<span id="cb33-5"><a href="#cb33-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-6"><a href="#cb33-6" aria-hidden="true" tabindex="-1"></a><span class="dt">final</span> <span class="kw">class</span> SafeCounter <span class="op">{</span></span>
<span id="cb33-7"><a href="#cb33-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="bu">Map</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">,</span> <span class="bu">Integer</span><span class="op">&gt;</span> v<span class="op">;</span></span>
<span id="cb33-8"><a href="#cb33-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="bu">ReentrantLock</span> lock<span class="op">;</span></span>
<span id="cb33-9"><a href="#cb33-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-10"><a href="#cb33-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">SafeCounter</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb33-11"><a href="#cb33-11" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">v</span> <span class="op">=</span> <span class="kw">new</span> <span class="bu">HashMap</span><span class="op">&lt;&gt;();</span></span>
<span id="cb33-12"><a href="#cb33-12" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">lock</span> <span class="op">=</span> <span class="kw">new</span> <span class="bu">ReentrantLock</span><span class="op">();</span></span>
<span id="cb33-13"><a href="#cb33-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb33-14"><a href="#cb33-14" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">inc</span><span class="op">(</span><span class="bu">String</span> key<span class="op">)</span> <span class="op">{</span></span>
<span id="cb33-15"><a href="#cb33-15" aria-hidden="true" tabindex="-1"></a>        lock<span class="op">.</span><span class="fu">lock</span><span class="op">();</span></span>
<span id="cb33-16"><a href="#cb33-16" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb33-17"><a href="#cb33-17" aria-hidden="true" tabindex="-1"></a>            v<span class="op">.</span><span class="fu">put</span><span class="op">(</span>key<span class="op">,</span> v<span class="op">.</span><span class="fu">getOrDefault</span><span class="op">(</span>key<span class="op">,</span> <span class="dv">0</span><span class="op">)</span> <span class="op">+</span> <span class="dv">1</span><span class="op">);</span></span>
<span id="cb33-18"><a href="#cb33-18" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">finally</span> <span class="op">{</span></span>
<span id="cb33-19"><a href="#cb33-19" aria-hidden="true" tabindex="-1"></a>            lock<span class="op">.</span><span class="fu">unlock</span><span class="op">();</span></span>
<span id="cb33-20"><a href="#cb33-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb33-21"><a href="#cb33-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb33-22"><a href="#cb33-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-23"><a href="#cb33-23" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">value</span><span class="op">(</span><span class="bu">String</span> key<span class="op">)</span> <span class="op">{</span></span>
<span id="cb33-24"><a href="#cb33-24" aria-hidden="true" tabindex="-1"></a>        lock<span class="op">.</span><span class="fu">lock</span><span class="op">();</span></span>
<span id="cb33-25"><a href="#cb33-25" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb33-26"><a href="#cb33-26" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> v<span class="op">.</span><span class="fu">getOrDefault</span><span class="op">(</span>key<span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb33-27"><a href="#cb33-27" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">finally</span> <span class="op">{</span></span>
<span id="cb33-28"><a href="#cb33-28" aria-hidden="true" tabindex="-1"></a>            lock<span class="op">.</span><span class="fu">unlock</span><span class="op">();</span></span>
<span id="cb33-29"><a href="#cb33-29" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb33-30"><a href="#cb33-30" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb33-31"><a href="#cb33-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb33-32"><a href="#cb33-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-33"><a href="#cb33-33" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> Mutex <span class="op">{</span></span>
<span id="cb33-34"><a href="#cb33-34" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Mutex</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb33-35"><a href="#cb33-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-36"><a href="#cb33-36" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> </span>
<span id="cb33-37"><a href="#cb33-37" aria-hidden="true" tabindex="-1"></a>            <span class="kw">throws</span> <span class="bu">InterruptedException</span> <span class="op">{</span></span>
<span id="cb33-38"><a href="#cb33-38" aria-hidden="true" tabindex="-1"></a>        var c <span class="op">=</span> <span class="kw">new</span> <span class="fu">SafeCounter</span><span class="op">();</span></span>
<span id="cb33-39"><a href="#cb33-39" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">1000</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb33-40"><a href="#cb33-40" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Thread</span><span class="op">.</span><span class="fu">startVirtualThread</span><span class="op">(</span></span>
<span id="cb33-41"><a href="#cb33-41" aria-hidden="true" tabindex="-1"></a>                    <span class="op">()</span> <span class="op">-&gt;</span> c<span class="op">.</span><span class="fu">inc</span><span class="op">(</span><span class="st">&quot;somekey&quot;</span><span class="op">)</span></span>
<span id="cb33-42"><a href="#cb33-42" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb33-43"><a href="#cb33-43" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb33-44"><a href="#cb33-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-45"><a href="#cb33-45" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Thread</span><span class="op">.</span><span class="fu">sleep</span><span class="op">(</span><span class="bu">Duration</span><span class="op">.</span><span class="fu">ofSeconds</span><span class="op">(</span><span class="dv">1</span><span class="op">));</span></span>
<span id="cb33-46"><a href="#cb33-46" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>c<span class="op">.</span><span class="fu">value</span><span class="op">(</span><span class="st">&quot;somekey&quot;</span><span class="op">));</span></span>
<span id="cb33-47"><a href="#cb33-47" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb33-48"><a href="#cb33-48" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb34"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a>Mutex<span class="op">.</span><span class="fu">main</span><span class="op">(</span><span class="kw">new</span> <span class="bu">String</span><span class="op">[]{});</span></span></code></pre></div>
<p>The only thing of note is that unlike Go where you can <code>defer</code> some arbitrary action like releasing your hold on a lock, in Java the general mechanism for "cleanup that must happen" is using the <code>finally</code> clause of a <code>try</code> block.</p>
<p>For Java <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/locks/ReentrantLock.html"><code>ReentrantLock</code></a> is special in that its locks can "escape" a lexical scope. You can lock before entering a method and unlock in a totally unrelated one.</p>
<p>If you don't need this ability then you can use the fact that every "identity" having object in Java can be used as a lock with <code>synchronized</code>.</p>
<div class="sourceCode" id="cb35"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a><span class="dt">final</span> <span class="kw">class</span> SafeCounter <span class="op">{</span></span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="bu">Map</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">,</span> <span class="bu">Integer</span><span class="op">&gt;</span> v<span class="op">;</span></span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">SafeCounter</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb35-5"><a href="#cb35-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">v</span> <span class="op">=</span> <span class="kw">new</span> <span class="bu">HashMap</span><span class="op">&lt;&gt;();</span></span>
<span id="cb35-6"><a href="#cb35-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb35-7"><a href="#cb35-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">inc</span><span class="op">(</span><span class="bu">String</span> key<span class="op">)</span> <span class="op">{</span></span>
<span id="cb35-8"><a href="#cb35-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">synchronized</span> <span class="op">(</span><span class="kw">this</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb35-9"><a href="#cb35-9" aria-hidden="true" tabindex="-1"></a>            v<span class="op">.</span><span class="fu">put</span><span class="op">(</span>key<span class="op">,</span> v<span class="op">.</span><span class="fu">getOrDefault</span><span class="op">(</span>key<span class="op">,</span> <span class="dv">0</span><span class="op">)</span> <span class="op">+</span> <span class="dv">1</span><span class="op">);</span></span>
<span id="cb35-10"><a href="#cb35-10" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb35-11"><a href="#cb35-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb35-12"><a href="#cb35-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-13"><a href="#cb35-13" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">value</span><span class="op">(</span><span class="bu">String</span> key<span class="op">)</span> <span class="op">{</span></span>
<span id="cb35-14"><a href="#cb35-14" aria-hidden="true" tabindex="-1"></a>        <span class="kw">synchronized</span> <span class="op">(</span><span class="kw">this</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb35-15"><a href="#cb35-15" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> v<span class="op">.</span><span class="fu">getOrDefault</span><span class="op">(</span>key<span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb35-16"><a href="#cb35-16" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb35-17"><a href="#cb35-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb35-18"><a href="#cb35-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>If the thing being synchronized on is just <code>this</code> and that synchronization lasts the entire scope of the method, we can just mark the method as <code>synchronized</code> for the same effect.</p>
<div class="sourceCode" id="cb36"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a><span class="dt">final</span> <span class="kw">class</span> SafeCounter <span class="op">{</span></span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="bu">Map</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">,</span> <span class="bu">Integer</span><span class="op">&gt;</span> v<span class="op">;</span></span>
<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-4"><a href="#cb36-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">SafeCounter</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb36-5"><a href="#cb36-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">v</span> <span class="op">=</span> <span class="kw">new</span> <span class="bu">HashMap</span><span class="op">&lt;&gt;();</span></span>
<span id="cb36-6"><a href="#cb36-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb36-7"><a href="#cb36-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-8"><a href="#cb36-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">synchronized</span> <span class="dt">void</span> <span class="fu">inc</span><span class="op">(</span><span class="bu">String</span> key<span class="op">)</span> <span class="op">{</span></span>
<span id="cb36-9"><a href="#cb36-9" aria-hidden="true" tabindex="-1"></a>        v<span class="op">.</span><span class="fu">put</span><span class="op">(</span>key<span class="op">,</span> v<span class="op">.</span><span class="fu">getOrDefault</span><span class="op">(</span>key<span class="op">,</span> <span class="dv">0</span><span class="op">)</span> <span class="op">+</span> <span class="dv">1</span><span class="op">);</span></span>
<span id="cb36-10"><a href="#cb36-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb36-11"><a href="#cb36-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-12"><a href="#cb36-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">synchronized</span> <span class="dt">int</span> <span class="fu">value</span><span class="op">(</span><span class="bu">String</span> key<span class="op">)</span> <span class="op">{</span></span>
<span id="cb36-13"><a href="#cb36-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> v<span class="op">.</span><span class="fu">getOrDefault</span><span class="op">(</span>key<span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb36-14"><a href="#cb36-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb36-15"><a href="#cb36-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="example-9-web-crawler">Example 9: Web Crawler</h2>
<p><a href="https://go.dev/tour/concurrency/10">https://go.dev/tour/concurrency/10</a></p>
<div class="sourceCode" id="cb37"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span> main</span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-3"><a href="#cb37-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="op">(</span></span>
<span id="cb37-4"><a href="#cb37-4" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;fmt&quot;</span></span>
<span id="cb37-5"><a href="#cb37-5" aria-hidden="true" tabindex="-1"></a><span class="op">)</span></span>
<span id="cb37-6"><a href="#cb37-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-7"><a href="#cb37-7" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> Fetcher <span class="kw">interface</span> <span class="op">{</span></span>
<span id="cb37-8"><a href="#cb37-8" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Fetch returns the body of URL and</span></span>
<span id="cb37-9"><a href="#cb37-9" aria-hidden="true" tabindex="-1"></a>    <span class="co">// a slice of URLs found on that page.</span></span>
<span id="cb37-10"><a href="#cb37-10" aria-hidden="true" tabindex="-1"></a>    Fetch<span class="op">(</span>url <span class="dt">string</span><span class="op">)</span> <span class="op">(</span>body <span class="dt">string</span><span class="op">,</span> urls <span class="op">[]</span><span class="dt">string</span><span class="op">,</span> err <span class="dt">error</span><span class="op">)</span></span>
<span id="cb37-11"><a href="#cb37-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb37-12"><a href="#cb37-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-13"><a href="#cb37-13" aria-hidden="true" tabindex="-1"></a><span class="co">// Crawl uses fetcher to recursively crawl</span></span>
<span id="cb37-14"><a href="#cb37-14" aria-hidden="true" tabindex="-1"></a><span class="co">// pages starting with url, to a maximum of depth.</span></span>
<span id="cb37-15"><a href="#cb37-15" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> Crawl<span class="op">(</span>url <span class="dt">string</span><span class="op">,</span> depth <span class="dt">int</span><span class="op">,</span> fetcher Fetcher<span class="op">)</span> <span class="op">{</span></span>
<span id="cb37-16"><a href="#cb37-16" aria-hidden="true" tabindex="-1"></a>    <span class="co">// </span><span class="al">TODO</span><span class="co">: Fetch URLs in parallel.</span></span>
<span id="cb37-17"><a href="#cb37-17" aria-hidden="true" tabindex="-1"></a>    <span class="co">// </span><span class="al">TODO</span><span class="co">: Don&#39;t fetch the same URL twice.</span></span>
<span id="cb37-18"><a href="#cb37-18" aria-hidden="true" tabindex="-1"></a>    <span class="co">// This implementation doesn&#39;t do either:</span></span>
<span id="cb37-19"><a href="#cb37-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">if</span> depth <span class="op">&lt;=</span> <span class="dv">0</span> <span class="op">{</span></span>
<span id="cb37-20"><a href="#cb37-20" aria-hidden="true" tabindex="-1"></a>        <span class="kw">return</span></span>
<span id="cb37-21"><a href="#cb37-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb37-22"><a href="#cb37-22" aria-hidden="true" tabindex="-1"></a>    body<span class="op">,</span> urls<span class="op">,</span> err <span class="op">:=</span> fetcher<span class="op">.</span>Fetch<span class="op">(</span>url<span class="op">)</span></span>
<span id="cb37-23"><a href="#cb37-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">if</span> err <span class="op">!=</span> <span class="ot">nil</span> <span class="op">{</span></span>
<span id="cb37-24"><a href="#cb37-24" aria-hidden="true" tabindex="-1"></a>        fmt<span class="op">.</span>Println<span class="op">(</span>err<span class="op">)</span></span>
<span id="cb37-25"><a href="#cb37-25" aria-hidden="true" tabindex="-1"></a>        <span class="kw">return</span></span>
<span id="cb37-26"><a href="#cb37-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb37-27"><a href="#cb37-27" aria-hidden="true" tabindex="-1"></a>    fmt<span class="op">.</span>Printf<span class="op">(</span><span class="st">&quot;found: %s %q</span><span class="ch">\n</span><span class="st">&quot;</span><span class="op">,</span> url<span class="op">,</span> body<span class="op">)</span></span>
<span id="cb37-28"><a href="#cb37-28" aria-hidden="true" tabindex="-1"></a>    <span class="kw">for</span> _<span class="op">,</span> u <span class="op">:=</span> <span class="kw">range</span> urls <span class="op">{</span></span>
<span id="cb37-29"><a href="#cb37-29" aria-hidden="true" tabindex="-1"></a>        Crawl<span class="op">(</span>u<span class="op">,</span> depth<span class="dv">-1</span><span class="op">,</span> fetcher<span class="op">)</span></span>
<span id="cb37-30"><a href="#cb37-30" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb37-31"><a href="#cb37-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">return</span></span>
<span id="cb37-32"><a href="#cb37-32" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb37-33"><a href="#cb37-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-34"><a href="#cb37-34" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb37-35"><a href="#cb37-35" aria-hidden="true" tabindex="-1"></a>    Crawl<span class="op">(</span><span class="st">&quot;https://golang.org/&quot;</span><span class="op">,</span> <span class="dv">4</span><span class="op">,</span> fetcher<span class="op">)</span></span>
<span id="cb37-36"><a href="#cb37-36" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb37-37"><a href="#cb37-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-38"><a href="#cb37-38" aria-hidden="true" tabindex="-1"></a><span class="co">// fakeFetcher is Fetcher that returns canned results.</span></span>
<span id="cb37-39"><a href="#cb37-39" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> fakeFetcher <span class="kw">map</span><span class="op">[</span><span class="dt">string</span><span class="op">]*</span>fakeResult</span>
<span id="cb37-40"><a href="#cb37-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-41"><a href="#cb37-41" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> fakeResult <span class="kw">struct</span> <span class="op">{</span></span>
<span id="cb37-42"><a href="#cb37-42" aria-hidden="true" tabindex="-1"></a>    body <span class="dt">string</span></span>
<span id="cb37-43"><a href="#cb37-43" aria-hidden="true" tabindex="-1"></a>    urls <span class="op">[]</span><span class="dt">string</span></span>
<span id="cb37-44"><a href="#cb37-44" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb37-45"><a href="#cb37-45" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-46"><a href="#cb37-46" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> <span class="op">(</span>f fakeFetcher<span class="op">)</span> Fetch<span class="op">(</span>url <span class="dt">string</span><span class="op">)</span> <span class="op">(</span><span class="dt">string</span><span class="op">,</span> <span class="op">[]</span><span class="dt">string</span><span class="op">,</span> <span class="dt">error</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb37-47"><a href="#cb37-47" aria-hidden="true" tabindex="-1"></a>    <span class="kw">if</span> res<span class="op">,</span> ok <span class="op">:=</span> f<span class="op">[</span>url<span class="op">];</span> ok <span class="op">{</span></span>
<span id="cb37-48"><a href="#cb37-48" aria-hidden="true" tabindex="-1"></a>        <span class="kw">return</span> res<span class="op">.</span>body<span class="op">,</span> res<span class="op">.</span>urls<span class="op">,</span> <span class="ot">nil</span></span>
<span id="cb37-49"><a href="#cb37-49" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb37-50"><a href="#cb37-50" aria-hidden="true" tabindex="-1"></a>    <span class="kw">return</span> <span class="st">&quot;&quot;</span><span class="op">,</span> <span class="ot">nil</span><span class="op">,</span> fmt<span class="op">.</span>Errorf<span class="op">(</span><span class="st">&quot;not found: %s&quot;</span><span class="op">,</span> url<span class="op">)</span></span>
<span id="cb37-51"><a href="#cb37-51" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb37-52"><a href="#cb37-52" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-53"><a href="#cb37-53" aria-hidden="true" tabindex="-1"></a><span class="co">// fetcher is a populated fakeFetcher.</span></span>
<span id="cb37-54"><a href="#cb37-54" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> fetcher <span class="op">=</span> fakeFetcher<span class="op">{</span></span>
<span id="cb37-55"><a href="#cb37-55" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;https://golang.org/&quot;</span><span class="op">:</span> <span class="op">&amp;</span>fakeResult<span class="op">{</span></span>
<span id="cb37-56"><a href="#cb37-56" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;The Go Programming Language&quot;</span><span class="op">,</span></span>
<span id="cb37-57"><a href="#cb37-57" aria-hidden="true" tabindex="-1"></a>        <span class="op">[]</span><span class="dt">string</span><span class="op">{</span></span>
<span id="cb37-58"><a href="#cb37-58" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;https://golang.org/pkg/&quot;</span><span class="op">,</span></span>
<span id="cb37-59"><a href="#cb37-59" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;https://golang.org/cmd/&quot;</span><span class="op">,</span></span>
<span id="cb37-60"><a href="#cb37-60" aria-hidden="true" tabindex="-1"></a>        <span class="op">},</span></span>
<span id="cb37-61"><a href="#cb37-61" aria-hidden="true" tabindex="-1"></a>    <span class="op">},</span></span>
<span id="cb37-62"><a href="#cb37-62" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;https://golang.org/pkg/&quot;</span><span class="op">:</span> <span class="op">&amp;</span>fakeResult<span class="op">{</span></span>
<span id="cb37-63"><a href="#cb37-63" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;Packages&quot;</span><span class="op">,</span></span>
<span id="cb37-64"><a href="#cb37-64" aria-hidden="true" tabindex="-1"></a>            <span class="op">[]</span><span class="dt">string</span><span class="op">{</span></span>
<span id="cb37-65"><a href="#cb37-65" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;https://golang.org/&quot;</span><span class="op">,</span></span>
<span id="cb37-66"><a href="#cb37-66" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;https://golang.org/cmd/&quot;</span><span class="op">,</span></span>
<span id="cb37-67"><a href="#cb37-67" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;https://golang.org/pkg/fmt/&quot;</span><span class="op">,</span></span>
<span id="cb37-68"><a href="#cb37-68" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;https://golang.org/pkg/os/&quot;</span><span class="op">,</span></span>
<span id="cb37-69"><a href="#cb37-69" aria-hidden="true" tabindex="-1"></a>            <span class="op">},</span></span>
<span id="cb37-70"><a href="#cb37-70" aria-hidden="true" tabindex="-1"></a>        <span class="op">},</span></span>
<span id="cb37-71"><a href="#cb37-71" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;https://golang.org/pkg/fmt/&quot;</span><span class="op">:</span> <span class="op">&amp;</span>fakeResult<span class="op">{</span></span>
<span id="cb37-72"><a href="#cb37-72" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;Package fmt&quot;</span><span class="op">,</span></span>
<span id="cb37-73"><a href="#cb37-73" aria-hidden="true" tabindex="-1"></a>            <span class="op">[]</span><span class="dt">string</span><span class="op">{</span></span>
<span id="cb37-74"><a href="#cb37-74" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;https://golang.org/&quot;</span><span class="op">,</span></span>
<span id="cb37-75"><a href="#cb37-75" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;https://golang.org/pkg/&quot;</span><span class="op">,</span></span>
<span id="cb37-76"><a href="#cb37-76" aria-hidden="true" tabindex="-1"></a>            <span class="op">},</span></span>
<span id="cb37-77"><a href="#cb37-77" aria-hidden="true" tabindex="-1"></a>        <span class="op">},</span></span>
<span id="cb37-78"><a href="#cb37-78" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;https://golang.org/pkg/os/&quot;</span><span class="op">:</span> <span class="op">&amp;</span>fakeResult<span class="op">{</span></span>
<span id="cb37-79"><a href="#cb37-79" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;Package os&quot;</span><span class="op">,</span></span>
<span id="cb37-80"><a href="#cb37-80" aria-hidden="true" tabindex="-1"></a>            <span class="op">[]</span><span class="dt">string</span><span class="op">{</span></span>
<span id="cb37-81"><a href="#cb37-81" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;https://golang.org/&quot;</span><span class="op">,</span></span>
<span id="cb37-82"><a href="#cb37-82" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;https://golang.org/pkg/&quot;</span><span class="op">,</span></span>
<span id="cb37-83"><a href="#cb37-83" aria-hidden="true" tabindex="-1"></a>            <span class="op">},</span></span>
<span id="cb37-84"><a href="#cb37-84" aria-hidden="true" tabindex="-1"></a>        <span class="op">},</span></span>
<span id="cb37-85"><a href="#cb37-85" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Another challenge problem. Before going to a reference solution, I am going to translate the synchronous example.</p>
<p>Go has a pattern of returning an error as a conditionally filled in extra return value. This isn't super idiomatic in Java, so instead I am going to model the error case as an <code>Exception</code>.</p>
<p>The Go version also returns both a body and an array of urls from a single call. For Java we can accomplish this by making an aggregate containing both values.</p>
<div class="sourceCode" id="cb38"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a><span class="dt">final</span> <span class="kw">class</span> FetcherException <span class="kw">extends</span> <span class="bu">Exception</span> <span class="op">{</span></span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a>    <span class="fu">FetcherException</span><span class="op">(</span><span class="bu">String</span> message<span class="op">)</span> <span class="op">{</span></span>
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">(</span>message<span class="op">);</span></span>
<span id="cb38-4"><a href="#cb38-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb38-5"><a href="#cb38-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb38-6"><a href="#cb38-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-7"><a href="#cb38-7" aria-hidden="true" tabindex="-1"></a><span class="kw">interface</span> Fetcher <span class="op">{</span></span>
<span id="cb38-8"><a href="#cb38-8" aria-hidden="true" tabindex="-1"></a>    record <span class="bu">Result</span><span class="op">(</span><span class="bu">String</span> body<span class="op">,</span> <span class="bu">String</span><span class="op">[]</span> urls<span class="op">)</span> <span class="op">{</span></span>
<span id="cb38-9"><a href="#cb38-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb38-10"><a href="#cb38-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-11"><a href="#cb38-11" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Result</span> <span class="fu">fetch</span><span class="op">(</span><span class="bu">String</span> url<span class="op">)</span> <span class="kw">throws</span> FetcherException<span class="op">;</span></span>
<span id="cb38-12"><a href="#cb38-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>We can make a "fake" implementation of fetcher using the same technique as Go by backing it with an in-memory map.</p>
<div class="sourceCode" id="cb39"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">Map</span><span class="op">;</span></span>
<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb39-3"><a href="#cb39-3" aria-hidden="true" tabindex="-1"></a><span class="dt">final</span> <span class="kw">class</span> FakeFetcher <span class="kw">implements</span> Fetcher <span class="op">{</span></span>
<span id="cb39-4"><a href="#cb39-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="bu">Map</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">,</span> <span class="bu">Result</span><span class="op">&gt;</span> results<span class="op">;</span></span>
<span id="cb39-5"><a href="#cb39-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb39-6"><a href="#cb39-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">FakeFetcher</span><span class="op">(</span><span class="bu">Map</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">,</span> <span class="bu">Result</span><span class="op">&gt;</span> results<span class="op">)</span> <span class="op">{</span></span>
<span id="cb39-7"><a href="#cb39-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">results</span> <span class="op">=</span> results<span class="op">;</span></span>
<span id="cb39-8"><a href="#cb39-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb39-9"><a href="#cb39-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb39-10"><a href="#cb39-10" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb39-11"><a href="#cb39-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">Result</span> <span class="fu">fetch</span><span class="op">(</span><span class="bu">String</span> url<span class="op">)</span> <span class="kw">throws</span> FetcherException <span class="op">{</span></span>
<span id="cb39-12"><a href="#cb39-12" aria-hidden="true" tabindex="-1"></a>        var result <span class="op">=</span> <span class="kw">this</span><span class="op">.</span><span class="fu">results</span><span class="op">.</span><span class="fu">get</span><span class="op">(</span>url<span class="op">);</span></span>
<span id="cb39-13"><a href="#cb39-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>result <span class="op">==</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb39-14"><a href="#cb39-14" aria-hidden="true" tabindex="-1"></a>            <span class="cf">throw</span> <span class="kw">new</span> <span class="fu">FetcherException</span><span class="op">(</span><span class="st">&quot;Not Found: &quot;</span> <span class="op">+</span> url<span class="op">);</span></span>
<span id="cb39-15"><a href="#cb39-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb39-16"><a href="#cb39-16" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> result<span class="op">;</span></span>
<span id="cb39-17"><a href="#cb39-17" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb39-18"><a href="#cb39-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb39-19"><a href="#cb39-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb39-20"><a href="#cb39-20" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> Fetcher <span class="fu">example</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb39-21"><a href="#cb39-21" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">FakeFetcher</span><span class="op">(</span><span class="bu">Map</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb39-22"><a href="#cb39-22" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;https://golang.org/&quot;</span><span class="op">,</span> <span class="kw">new</span> Fetcher<span class="op">.</span><span class="fu">Result</span><span class="op">(</span></span>
<span id="cb39-23"><a href="#cb39-23" aria-hidden="true" tabindex="-1"></a>                        <span class="st">&quot;The Go Programming Language&quot;</span><span class="op">,</span></span>
<span id="cb39-24"><a href="#cb39-24" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">new</span> <span class="bu">String</span><span class="op">[]{</span></span>
<span id="cb39-25"><a href="#cb39-25" aria-hidden="true" tabindex="-1"></a>                                <span class="st">&quot;https://golang.org/pkg/&quot;</span><span class="op">,</span></span>
<span id="cb39-26"><a href="#cb39-26" aria-hidden="true" tabindex="-1"></a>                                <span class="st">&quot;https://golang.org/cmd/&quot;</span></span>
<span id="cb39-27"><a href="#cb39-27" aria-hidden="true" tabindex="-1"></a>                        <span class="op">}</span></span>
<span id="cb39-28"><a href="#cb39-28" aria-hidden="true" tabindex="-1"></a>                <span class="op">),</span></span>
<span id="cb39-29"><a href="#cb39-29" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;https://golang.org/pkg/&quot;</span><span class="op">,</span> <span class="kw">new</span> Fetcher<span class="op">.</span><span class="fu">Result</span><span class="op">(</span></span>
<span id="cb39-30"><a href="#cb39-30" aria-hidden="true" tabindex="-1"></a>                        <span class="st">&quot;Packages&quot;</span><span class="op">,</span></span>
<span id="cb39-31"><a href="#cb39-31" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">new</span> <span class="bu">String</span><span class="op">[]{</span></span>
<span id="cb39-32"><a href="#cb39-32" aria-hidden="true" tabindex="-1"></a>                                <span class="st">&quot;https://golang.org/&quot;</span><span class="op">,</span></span>
<span id="cb39-33"><a href="#cb39-33" aria-hidden="true" tabindex="-1"></a>                                <span class="st">&quot;https://golang.org/cmd/&quot;</span><span class="op">,</span></span>
<span id="cb39-34"><a href="#cb39-34" aria-hidden="true" tabindex="-1"></a>                                <span class="st">&quot;https://golang.org/pkg/fmt/&quot;</span><span class="op">,</span></span>
<span id="cb39-35"><a href="#cb39-35" aria-hidden="true" tabindex="-1"></a>                                <span class="st">&quot;https://golang.org/pkg/os/&quot;</span><span class="op">,</span></span>
<span id="cb39-36"><a href="#cb39-36" aria-hidden="true" tabindex="-1"></a>                        <span class="op">}</span></span>
<span id="cb39-37"><a href="#cb39-37" aria-hidden="true" tabindex="-1"></a>                <span class="op">),</span></span>
<span id="cb39-38"><a href="#cb39-38" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;https://golang.org/pkg/fmt/&quot;</span><span class="op">,</span> <span class="kw">new</span> Fetcher<span class="op">.</span><span class="fu">Result</span><span class="op">(</span></span>
<span id="cb39-39"><a href="#cb39-39" aria-hidden="true" tabindex="-1"></a>                        <span class="st">&quot;Package fmt&quot;</span><span class="op">,</span></span>
<span id="cb39-40"><a href="#cb39-40" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">new</span> <span class="bu">String</span><span class="op">[]{</span></span>
<span id="cb39-41"><a href="#cb39-41" aria-hidden="true" tabindex="-1"></a>                                <span class="st">&quot;https://golang.org/&quot;</span><span class="op">,</span></span>
<span id="cb39-42"><a href="#cb39-42" aria-hidden="true" tabindex="-1"></a>                                <span class="st">&quot;https://golang.org/pkg/&quot;</span><span class="op">,</span></span>
<span id="cb39-43"><a href="#cb39-43" aria-hidden="true" tabindex="-1"></a>                        <span class="op">}</span></span>
<span id="cb39-44"><a href="#cb39-44" aria-hidden="true" tabindex="-1"></a>                <span class="op">),</span></span>
<span id="cb39-45"><a href="#cb39-45" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;https://golang.org/pkg/os/&quot;</span><span class="op">,</span> <span class="kw">new</span> Fetcher<span class="op">.</span><span class="fu">Result</span><span class="op">(</span></span>
<span id="cb39-46"><a href="#cb39-46" aria-hidden="true" tabindex="-1"></a>                        <span class="st">&quot;Package os&quot;</span><span class="op">,</span></span>
<span id="cb39-47"><a href="#cb39-47" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">new</span> <span class="bu">String</span><span class="op">[]{</span></span>
<span id="cb39-48"><a href="#cb39-48" aria-hidden="true" tabindex="-1"></a>                                <span class="st">&quot;https://golang.org/&quot;</span><span class="op">,</span></span>
<span id="cb39-49"><a href="#cb39-49" aria-hidden="true" tabindex="-1"></a>                                <span class="st">&quot;https://golang.org/pkg/&quot;</span><span class="op">,</span></span>
<span id="cb39-50"><a href="#cb39-50" aria-hidden="true" tabindex="-1"></a>                        <span class="op">}</span></span>
<span id="cb39-51"><a href="#cb39-51" aria-hidden="true" tabindex="-1"></a>                <span class="op">)</span></span>
<span id="cb39-52"><a href="#cb39-52" aria-hidden="true" tabindex="-1"></a>        <span class="op">));</span></span>
<span id="cb39-53"><a href="#cb39-53" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb39-54"><a href="#cb39-54" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Then the synchronous fetcher is just a regular recursive function as it was in Go.</p>
<div class="sourceCode" id="cb40"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> WebCrawler <span class="op">{</span></span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">WebCrawler</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb40-3"><a href="#cb40-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb40-4"><a href="#cb40-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-5"><a href="#cb40-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">void</span> <span class="fu">crawl</span><span class="op">(</span></span>
<span id="cb40-6"><a href="#cb40-6" aria-hidden="true" tabindex="-1"></a>        <span class="bu">String</span> url<span class="op">,</span> </span>
<span id="cb40-7"><a href="#cb40-7" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> depth<span class="op">,</span> </span>
<span id="cb40-8"><a href="#cb40-8" aria-hidden="true" tabindex="-1"></a>        Fetcher fetcher</span>
<span id="cb40-9"><a href="#cb40-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb40-10"><a href="#cb40-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>depth <span class="op">&lt;=</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb40-11"><a href="#cb40-11" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span><span class="op">;</span></span>
<span id="cb40-12"><a href="#cb40-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb40-13"><a href="#cb40-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-14"><a href="#cb40-14" aria-hidden="true" tabindex="-1"></a>        Fetcher<span class="op">.</span><span class="fu">Result</span> result<span class="op">;</span></span>
<span id="cb40-15"><a href="#cb40-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb40-16"><a href="#cb40-16" aria-hidden="true" tabindex="-1"></a>            result <span class="op">=</span> fetcher<span class="op">.</span><span class="fu">fetch</span><span class="op">(</span>url<span class="op">);</span></span>
<span id="cb40-17"><a href="#cb40-17" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span>FetcherException e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb40-18"><a href="#cb40-18" aria-hidden="true" tabindex="-1"></a>            <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>e<span class="op">.</span><span class="fu">getMessage</span><span class="op">());</span></span>
<span id="cb40-19"><a href="#cb40-19" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span><span class="op">;</span></span>
<span id="cb40-20"><a href="#cb40-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb40-21"><a href="#cb40-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-22"><a href="#cb40-22" aria-hidden="true" tabindex="-1"></a>        var body <span class="op">=</span> result<span class="op">.</span><span class="fu">body</span><span class="op">();</span></span>
<span id="cb40-23"><a href="#cb40-23" aria-hidden="true" tabindex="-1"></a>        var urls <span class="op">=</span> result<span class="op">.</span><span class="fu">urls</span><span class="op">();</span></span>
<span id="cb40-24"><a href="#cb40-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-25"><a href="#cb40-25" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">printf</span><span class="op">(</span></span>
<span id="cb40-26"><a href="#cb40-26" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;Found: </span><span class="sc">%s</span><span class="st"> </span><span class="sc">%s\n</span><span class="st">&quot;</span><span class="op">,</span> </span>
<span id="cb40-27"><a href="#cb40-27" aria-hidden="true" tabindex="-1"></a>            body<span class="op">,</span> </span>
<span id="cb40-28"><a href="#cb40-28" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Arrays</span><span class="op">.</span><span class="fu">toString</span><span class="op">(</span>urls<span class="op">)</span></span>
<span id="cb40-29"><a href="#cb40-29" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb40-30"><a href="#cb40-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-31"><a href="#cb40-31" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span>var u <span class="op">:</span> urls<span class="op">)</span> <span class="op">{</span></span>
<span id="cb40-32"><a href="#cb40-32" aria-hidden="true" tabindex="-1"></a>            <span class="fu">crawl</span><span class="op">(</span>u<span class="op">,</span> depth <span class="op">-</span> <span class="dv">1</span><span class="op">,</span> fetcher<span class="op">);</span></span>
<span id="cb40-33"><a href="#cb40-33" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb40-34"><a href="#cb40-34" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb40-35"><a href="#cb40-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-36"><a href="#cb40-36" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb40-37"><a href="#cb40-37" aria-hidden="true" tabindex="-1"></a>        var fetcher <span class="op">=</span> FakeFetcher<span class="op">.</span><span class="fu">example</span><span class="op">();</span></span>
<span id="cb40-38"><a href="#cb40-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-39"><a href="#cb40-39" aria-hidden="true" tabindex="-1"></a>        <span class="fu">crawl</span><span class="op">(</span><span class="st">&quot;https://golang.org/&quot;</span><span class="op">,</span> <span class="dv">4</span><span class="op">,</span> fetcher<span class="op">);</span></span>
<span id="cb40-40"><a href="#cb40-40" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb40-41"><a href="#cb40-41" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb41"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a>WebCrawler<span class="op">.</span><span class="fu">main</span><span class="op">(</span><span class="kw">new</span> <span class="bu">String</span><span class="op">[]{});</span></span></code></pre></div>
<p>Now I am going to pull an answer to the exercise from <a href="https://stackoverflow.com/questions/13217547/tour-of-go-exercise-10-crawler">this StackOverflow post</a>.</p>
<div class="sourceCode" id="cb42"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb42-1"><a href="#cb42-1" aria-hidden="true" tabindex="-1"></a><span class="co">// SafeUrlMap is safe to use concurrently.</span></span>
<span id="cb42-2"><a href="#cb42-2" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> SafeUrlMap <span class="kw">struct</span> <span class="op">{</span></span>
<span id="cb42-3"><a href="#cb42-3" aria-hidden="true" tabindex="-1"></a>    v   <span class="kw">map</span><span class="op">[</span><span class="dt">string</span><span class="op">]</span><span class="dt">string</span></span>
<span id="cb42-4"><a href="#cb42-4" aria-hidden="true" tabindex="-1"></a>    mux sync<span class="op">.</span>Mutex</span>
<span id="cb42-5"><a href="#cb42-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb42-6"><a href="#cb42-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-7"><a href="#cb42-7" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> <span class="op">(</span>c <span class="op">*</span>SafeUrlMap<span class="op">)</span> Set<span class="op">(</span>key <span class="dt">string</span><span class="op">,</span> body <span class="dt">string</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb42-8"><a href="#cb42-8" aria-hidden="true" tabindex="-1"></a>    c<span class="op">.</span>mux<span class="op">.</span>Lock<span class="op">()</span></span>
<span id="cb42-9"><a href="#cb42-9" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Lock so only one goroutine at a time can access the map c.v.</span></span>
<span id="cb42-10"><a href="#cb42-10" aria-hidden="true" tabindex="-1"></a>    c<span class="op">.</span>v<span class="op">[</span>key<span class="op">]</span> <span class="op">=</span> body</span>
<span id="cb42-11"><a href="#cb42-11" aria-hidden="true" tabindex="-1"></a>    c<span class="op">.</span>mux<span class="op">.</span>Unlock<span class="op">()</span></span>
<span id="cb42-12"><a href="#cb42-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb42-13"><a href="#cb42-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-14"><a href="#cb42-14" aria-hidden="true" tabindex="-1"></a><span class="co">// Value returns mapped value for the given key.</span></span>
<span id="cb42-15"><a href="#cb42-15" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> <span class="op">(</span>c <span class="op">*</span>SafeUrlMap<span class="op">)</span> Value<span class="op">(</span>key <span class="dt">string</span><span class="op">)</span> <span class="op">(</span><span class="dt">string</span><span class="op">,</span> <span class="dt">bool</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb42-16"><a href="#cb42-16" aria-hidden="true" tabindex="-1"></a>    c<span class="op">.</span>mux<span class="op">.</span>Lock<span class="op">()</span></span>
<span id="cb42-17"><a href="#cb42-17" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Lock so only one goroutine at a time can access the map c.v.</span></span>
<span id="cb42-18"><a href="#cb42-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">defer</span> c<span class="op">.</span>mux<span class="op">.</span>Unlock<span class="op">()</span></span>
<span id="cb42-19"><a href="#cb42-19" aria-hidden="true" tabindex="-1"></a>    val<span class="op">,</span> ok <span class="op">:=</span> c<span class="op">.</span>v<span class="op">[</span>key<span class="op">]</span></span>
<span id="cb42-20"><a href="#cb42-20" aria-hidden="true" tabindex="-1"></a>    <span class="kw">return</span> val<span class="op">,</span> ok</span>
<span id="cb42-21"><a href="#cb42-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb42-22"><a href="#cb42-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-23"><a href="#cb42-23" aria-hidden="true" tabindex="-1"></a><span class="co">// Crawl uses fetcher to recursively crawl</span></span>
<span id="cb42-24"><a href="#cb42-24" aria-hidden="true" tabindex="-1"></a><span class="co">// pages starting with url, to a maximum of depth.</span></span>
<span id="cb42-25"><a href="#cb42-25" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> Crawl<span class="op">(</span>url <span class="dt">string</span><span class="op">,</span> depth <span class="dt">int</span><span class="op">,</span> fetcher Fetcher<span class="op">,</span> urlMap SafeUrlMap<span class="op">)</span> <span class="op">{</span></span>
<span id="cb42-26"><a href="#cb42-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">defer</span> wg<span class="op">.</span>Done<span class="op">()</span></span>
<span id="cb42-27"><a href="#cb42-27" aria-hidden="true" tabindex="-1"></a>    urlMap<span class="op">.</span>Set<span class="op">(</span>url<span class="op">,</span> body<span class="op">)</span></span>
<span id="cb42-28"><a href="#cb42-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-29"><a href="#cb42-29" aria-hidden="true" tabindex="-1"></a>    <span class="kw">if</span> depth <span class="op">&lt;=</span> <span class="dv">0</span> <span class="op">{</span></span>
<span id="cb42-30"><a href="#cb42-30" aria-hidden="true" tabindex="-1"></a>        <span class="kw">return</span></span>
<span id="cb42-31"><a href="#cb42-31" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb42-32"><a href="#cb42-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-33"><a href="#cb42-33" aria-hidden="true" tabindex="-1"></a>    body<span class="op">,</span> urls<span class="op">,</span> err <span class="op">:=</span> fetcher<span class="op">.</span>Fetch<span class="op">(</span>url<span class="op">)</span></span>
<span id="cb42-34"><a href="#cb42-34" aria-hidden="true" tabindex="-1"></a>    <span class="kw">if</span> err <span class="op">!=</span> <span class="ot">nil</span> <span class="op">{</span></span>
<span id="cb42-35"><a href="#cb42-35" aria-hidden="true" tabindex="-1"></a>        fmt<span class="op">.</span>Println<span class="op">(</span>err<span class="op">)</span></span>
<span id="cb42-36"><a href="#cb42-36" aria-hidden="true" tabindex="-1"></a>        <span class="kw">return</span></span>
<span id="cb42-37"><a href="#cb42-37" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb42-38"><a href="#cb42-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-39"><a href="#cb42-39" aria-hidden="true" tabindex="-1"></a>    <span class="kw">for</span> _<span class="op">,</span> u <span class="op">:=</span> <span class="kw">range</span> urls <span class="op">{</span></span>
<span id="cb42-40"><a href="#cb42-40" aria-hidden="true" tabindex="-1"></a>        <span class="kw">if</span> _<span class="op">,</span> ok <span class="op">:=</span> urlMap<span class="op">.</span>Value<span class="op">(</span>u<span class="op">);</span> <span class="op">!</span>ok <span class="op">{</span></span>
<span id="cb42-41"><a href="#cb42-41" aria-hidden="true" tabindex="-1"></a>            wg<span class="op">.</span>Add<span class="op">(</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb42-42"><a href="#cb42-42" aria-hidden="true" tabindex="-1"></a>            <span class="kw">go</span> Crawl<span class="op">(</span>u<span class="op">,</span> depth<span class="dv">-1</span><span class="op">,</span> fetcher<span class="op">,</span> urlMap<span class="op">)</span></span>
<span id="cb42-43"><a href="#cb42-43" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb42-44"><a href="#cb42-44" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb42-45"><a href="#cb42-45" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-46"><a href="#cb42-46" aria-hidden="true" tabindex="-1"></a>    <span class="kw">return</span></span>
<span id="cb42-47"><a href="#cb42-47" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb42-48"><a href="#cb42-48" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-49"><a href="#cb42-49" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> wg sync<span class="op">.</span>WaitGroup</span>
<span id="cb42-50"><a href="#cb42-50" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-51"><a href="#cb42-51" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb42-52"><a href="#cb42-52" aria-hidden="true" tabindex="-1"></a>    urlMap <span class="op">:=</span> SafeUrlMap<span class="op">{</span>v<span class="op">:</span> <span class="bu">make</span><span class="op">(</span><span class="kw">map</span><span class="op">[</span><span class="dt">string</span><span class="op">]</span><span class="dt">string</span><span class="op">)}</span></span>
<span id="cb42-53"><a href="#cb42-53" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-54"><a href="#cb42-54" aria-hidden="true" tabindex="-1"></a>    wg<span class="op">.</span>Add<span class="op">(</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb42-55"><a href="#cb42-55" aria-hidden="true" tabindex="-1"></a>    <span class="kw">go</span> Crawl<span class="op">(</span><span class="st">&quot;http://golang.org/&quot;</span><span class="op">,</span> <span class="dv">4</span><span class="op">,</span> fetcher<span class="op">,</span> urlMap<span class="op">)</span></span>
<span id="cb42-56"><a href="#cb42-56" aria-hidden="true" tabindex="-1"></a>    wg<span class="op">.</span>Wait<span class="op">()</span></span>
<span id="cb42-57"><a href="#cb42-57" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-58"><a href="#cb42-58" aria-hidden="true" tabindex="-1"></a>    <span class="kw">for</span> url <span class="op">:=</span> <span class="kw">range</span> urlMap<span class="op">.</span>v <span class="op">{</span></span>
<span id="cb42-59"><a href="#cb42-59" aria-hidden="true" tabindex="-1"></a>        body<span class="op">,</span> _ <span class="op">:=</span> urlMap<span class="op">.</span>Value<span class="op">(</span>url<span class="op">)</span></span>
<span id="cb42-60"><a href="#cb42-60" aria-hidden="true" tabindex="-1"></a>        fmt<span class="op">.</span>Printf<span class="op">(</span><span class="st">&quot;found: %s %q</span><span class="ch">\n</span><span class="st">&quot;</span><span class="op">,</span> url<span class="op">,</span> body<span class="op">)</span></span>
<span id="cb42-61"><a href="#cb42-61" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb42-62"><a href="#cb42-62" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This solution makes use of a <a href="https://pkg.go.dev/sync#WaitGroup"><code>sync.WaitGroup</code></a>. There is no direct analogue in Java, but we can pretty easily make something that has similar semantics.</p>
<p>I am taking the implementation <a href="https://stackoverflow.com/questions/29655531/what-is-the-java-equivalent-of-golangs-waitgroup">from this StackOverflow question</a>.</p>
<div class="sourceCode" id="cb43"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb43-1"><a href="#cb43-1" aria-hidden="true" tabindex="-1"></a><span class="dt">final</span> <span class="kw">class</span> WaitGroup <span class="op">{</span></span>
<span id="cb43-2"><a href="#cb43-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">int</span> jobs <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb43-3"><a href="#cb43-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb43-4"><a href="#cb43-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="kw">synchronized</span> <span class="dt">void</span> <span class="fu">add</span><span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb43-5"><a href="#cb43-5" aria-hidden="true" tabindex="-1"></a>        jobs <span class="op">+=</span> i<span class="op">;</span></span>
<span id="cb43-6"><a href="#cb43-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb43-7"><a href="#cb43-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb43-8"><a href="#cb43-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="kw">synchronized</span> <span class="dt">void</span> <span class="fu">done</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb43-9"><a href="#cb43-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(--</span>jobs <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb43-10"><a href="#cb43-10" aria-hidden="true" tabindex="-1"></a>            <span class="fu">notifyAll</span><span class="op">();</span></span>
<span id="cb43-11"><a href="#cb43-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb43-12"><a href="#cb43-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb43-13"><a href="#cb43-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb43-14"><a href="#cb43-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="kw">synchronized</span> <span class="dt">void</span> <span class="fu">await</span><span class="op">()</span> </span>
<span id="cb43-15"><a href="#cb43-15" aria-hidden="true" tabindex="-1"></a>            <span class="kw">throws</span> <span class="bu">InterruptedException</span> <span class="op">{</span></span>
<span id="cb43-16"><a href="#cb43-16" aria-hidden="true" tabindex="-1"></a>        <span class="cf">while</span> <span class="op">(</span>jobs <span class="op">&gt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb43-17"><a href="#cb43-17" aria-hidden="true" tabindex="-1"></a>            <span class="fu">wait</span><span class="op">();</span></span>
<span id="cb43-18"><a href="#cb43-18" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb43-19"><a href="#cb43-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb43-20"><a href="#cb43-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The <code>SafeUrlMap</code> type is also fairly trivial to assemble, but instead of that I am going to pass around a normal <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/HashSet.html"><code>HashSet</code></a> and manually synchronize on it.</p>
<p>There are many other options, including using <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/Collections.html#synchronizedSet(java.util.Set)"><code>Collections#synchronizedSet</code></a> or wrapping a <a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/ConcurrentHashMap.html"><code>ConcurrentHashMap</code></a>, but I think this will be the easiest to follow.</p>
<div class="sourceCode" id="cb44"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb44-1"><a href="#cb44-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> WebCrawler <span class="op">{</span></span>
<span id="cb44-2"><a href="#cb44-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">WebCrawler</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb44-3"><a href="#cb44-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb44-4"><a href="#cb44-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb44-5"><a href="#cb44-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">void</span> <span class="fu">crawlTask</span><span class="op">(</span></span>
<span id="cb44-6"><a href="#cb44-6" aria-hidden="true" tabindex="-1"></a>            <span class="bu">String</span> url<span class="op">,</span></span>
<span id="cb44-7"><a href="#cb44-7" aria-hidden="true" tabindex="-1"></a>            <span class="dt">int</span> depth<span class="op">,</span></span>
<span id="cb44-8"><a href="#cb44-8" aria-hidden="true" tabindex="-1"></a>            Fetcher fetcher<span class="op">,</span></span>
<span id="cb44-9"><a href="#cb44-9" aria-hidden="true" tabindex="-1"></a>            <span class="bu">ExecutorService</span> executor<span class="op">,</span></span>
<span id="cb44-10"><a href="#cb44-10" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Set</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> seen<span class="op">,</span></span>
<span id="cb44-11"><a href="#cb44-11" aria-hidden="true" tabindex="-1"></a>            WaitGroup waitGroup</span>
<span id="cb44-12"><a href="#cb44-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb44-13"><a href="#cb44-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb44-14"><a href="#cb44-14" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>depth <span class="op">&lt;=</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb44-15"><a href="#cb44-15" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span><span class="op">;</span></span>
<span id="cb44-16"><a href="#cb44-16" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb44-17"><a href="#cb44-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb44-18"><a href="#cb44-18" aria-hidden="true" tabindex="-1"></a>            Fetcher<span class="op">.</span><span class="fu">Result</span> result<span class="op">;</span></span>
<span id="cb44-19"><a href="#cb44-19" aria-hidden="true" tabindex="-1"></a>            <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb44-20"><a href="#cb44-20" aria-hidden="true" tabindex="-1"></a>                result <span class="op">=</span> fetcher<span class="op">.</span><span class="fu">fetch</span><span class="op">(</span>url<span class="op">);</span></span>
<span id="cb44-21"><a href="#cb44-21" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span>FetcherException e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb44-22"><a href="#cb44-22" aria-hidden="true" tabindex="-1"></a>                <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>e<span class="op">.</span><span class="fu">getMessage</span><span class="op">());</span></span>
<span id="cb44-23"><a href="#cb44-23" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span><span class="op">;</span></span>
<span id="cb44-24"><a href="#cb44-24" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb44-25"><a href="#cb44-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb44-26"><a href="#cb44-26" aria-hidden="true" tabindex="-1"></a>            var body <span class="op">=</span> result<span class="op">.</span><span class="fu">body</span><span class="op">();</span></span>
<span id="cb44-27"><a href="#cb44-27" aria-hidden="true" tabindex="-1"></a>            var urls <span class="op">=</span> result<span class="op">.</span><span class="fu">urls</span><span class="op">();</span></span>
<span id="cb44-28"><a href="#cb44-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb44-29"><a href="#cb44-29" aria-hidden="true" tabindex="-1"></a>            <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">printf</span><span class="op">(</span></span>
<span id="cb44-30"><a href="#cb44-30" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;Found: </span><span class="sc">%s</span><span class="st"> </span><span class="sc">%s\n</span><span class="st">&quot;</span><span class="op">,</span> </span>
<span id="cb44-31"><a href="#cb44-31" aria-hidden="true" tabindex="-1"></a>                body<span class="op">,</span> </span>
<span id="cb44-32"><a href="#cb44-32" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Arrays</span><span class="op">.</span><span class="fu">toString</span><span class="op">(</span>urls<span class="op">)</span></span>
<span id="cb44-33"><a href="#cb44-33" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb44-34"><a href="#cb44-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb44-35"><a href="#cb44-35" aria-hidden="true" tabindex="-1"></a>            <span class="cf">for</span> <span class="op">(</span>var u <span class="op">:</span> urls<span class="op">)</span> <span class="op">{</span></span>
<span id="cb44-36"><a href="#cb44-36" aria-hidden="true" tabindex="-1"></a>                <span class="kw">synchronized</span> <span class="op">(</span>seen<span class="op">)</span> <span class="op">{</span></span>
<span id="cb44-37"><a href="#cb44-37" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">if</span> <span class="op">(!</span>seen<span class="op">.</span><span class="fu">contains</span><span class="op">(</span>u<span class="op">))</span> <span class="op">{</span></span>
<span id="cb44-38"><a href="#cb44-38" aria-hidden="true" tabindex="-1"></a>                        seen<span class="op">.</span><span class="fu">add</span><span class="op">(</span>u<span class="op">);</span></span>
<span id="cb44-39"><a href="#cb44-39" aria-hidden="true" tabindex="-1"></a>                        waitGroup<span class="op">.</span><span class="fu">add</span><span class="op">(</span><span class="dv">1</span><span class="op">);</span></span>
<span id="cb44-40"><a href="#cb44-40" aria-hidden="true" tabindex="-1"></a>                        executor<span class="op">.</span><span class="fu">submit</span><span class="op">(()</span> <span class="op">-&gt;</span> <span class="fu">crawlTask</span><span class="op">(</span></span>
<span id="cb44-41"><a href="#cb44-41" aria-hidden="true" tabindex="-1"></a>                                u<span class="op">,</span></span>
<span id="cb44-42"><a href="#cb44-42" aria-hidden="true" tabindex="-1"></a>                                depth <span class="op">-</span> <span class="dv">1</span><span class="op">,</span></span>
<span id="cb44-43"><a href="#cb44-43" aria-hidden="true" tabindex="-1"></a>                                fetcher<span class="op">,</span></span>
<span id="cb44-44"><a href="#cb44-44" aria-hidden="true" tabindex="-1"></a>                                executor<span class="op">,</span></span>
<span id="cb44-45"><a href="#cb44-45" aria-hidden="true" tabindex="-1"></a>                                seen<span class="op">,</span></span>
<span id="cb44-46"><a href="#cb44-46" aria-hidden="true" tabindex="-1"></a>                                waitGroup</span>
<span id="cb44-47"><a href="#cb44-47" aria-hidden="true" tabindex="-1"></a>                        <span class="op">));</span></span>
<span id="cb44-48"><a href="#cb44-48" aria-hidden="true" tabindex="-1"></a>                    <span class="op">}</span></span>
<span id="cb44-49"><a href="#cb44-49" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb44-50"><a href="#cb44-50" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb44-51"><a href="#cb44-51" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">finally</span> <span class="op">{</span></span>
<span id="cb44-52"><a href="#cb44-52" aria-hidden="true" tabindex="-1"></a>            waitGroup<span class="op">.</span><span class="fu">done</span><span class="op">();</span></span>
<span id="cb44-53"><a href="#cb44-53" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb44-54"><a href="#cb44-54" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb44-55"><a href="#cb44-55" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb44-56"><a href="#cb44-56" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">void</span> <span class="fu">crawl</span><span class="op">(</span><span class="bu">String</span> url<span class="op">,</span> <span class="dt">int</span> depth<span class="op">,</span> Fetcher fetcher<span class="op">)</span></span>
<span id="cb44-57"><a href="#cb44-57" aria-hidden="true" tabindex="-1"></a>            <span class="kw">throws</span> <span class="bu">InterruptedException</span> <span class="op">{</span></span>
<span id="cb44-58"><a href="#cb44-58" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span>var executor <span class="op">=</span></span>
<span id="cb44-59"><a href="#cb44-59" aria-hidden="true" tabindex="-1"></a>                     <span class="bu">Executors</span><span class="op">.</span><span class="fu">newVirtualThreadPerTaskExecutor</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb44-60"><a href="#cb44-60" aria-hidden="true" tabindex="-1"></a>            var waitGroup <span class="op">=</span> <span class="kw">new</span> <span class="fu">WaitGroup</span><span class="op">();</span></span>
<span id="cb44-61"><a href="#cb44-61" aria-hidden="true" tabindex="-1"></a>            waitGroup<span class="op">.</span><span class="fu">add</span><span class="op">(</span><span class="dv">1</span><span class="op">);</span></span>
<span id="cb44-62"><a href="#cb44-62" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb44-63"><a href="#cb44-63" aria-hidden="true" tabindex="-1"></a>            executor<span class="op">.</span><span class="fu">submit</span><span class="op">(()</span> <span class="op">-&gt;</span> <span class="fu">crawlTask</span><span class="op">(</span></span>
<span id="cb44-64"><a href="#cb44-64" aria-hidden="true" tabindex="-1"></a>                    url<span class="op">,</span></span>
<span id="cb44-65"><a href="#cb44-65" aria-hidden="true" tabindex="-1"></a>                    depth<span class="op">,</span></span>
<span id="cb44-66"><a href="#cb44-66" aria-hidden="true" tabindex="-1"></a>                    fetcher<span class="op">,</span></span>
<span id="cb44-67"><a href="#cb44-67" aria-hidden="true" tabindex="-1"></a>                    executor<span class="op">,</span></span>
<span id="cb44-68"><a href="#cb44-68" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">new</span> <span class="bu">HashSet</span><span class="op">&lt;&gt;(),</span></span>
<span id="cb44-69"><a href="#cb44-69" aria-hidden="true" tabindex="-1"></a>                    waitGroup</span>
<span id="cb44-70"><a href="#cb44-70" aria-hidden="true" tabindex="-1"></a>            <span class="op">));</span></span>
<span id="cb44-71"><a href="#cb44-71" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb44-72"><a href="#cb44-72" aria-hidden="true" tabindex="-1"></a>            waitGroup<span class="op">.</span><span class="fu">await</span><span class="op">();</span></span>
<span id="cb44-73"><a href="#cb44-73" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb44-74"><a href="#cb44-74" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb44-75"><a href="#cb44-75" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb44-76"><a href="#cb44-76" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> </span>
<span id="cb44-77"><a href="#cb44-77" aria-hidden="true" tabindex="-1"></a>            <span class="kw">throws</span> <span class="bu">InterruptedException</span> <span class="op">{</span></span>
<span id="cb44-78"><a href="#cb44-78" aria-hidden="true" tabindex="-1"></a>        var fetcher <span class="op">=</span> FakeFetcher<span class="op">.</span><span class="fu">example</span><span class="op">();</span></span>
<span id="cb44-79"><a href="#cb44-79" aria-hidden="true" tabindex="-1"></a>        <span class="fu">crawl</span><span class="op">(</span><span class="st">&quot;https://golang.org/&quot;</span><span class="op">,</span> <span class="dv">4</span><span class="op">,</span> fetcher<span class="op">);</span></span>
<span id="cb44-80"><a href="#cb44-80" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb44-81"><a href="#cb44-81" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb45"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb45-1"><a href="#cb45-1" aria-hidden="true" tabindex="-1"></a>WebCrawler<span class="op">.</span><span class="fu">main</span><span class="op">(</span><span class="kw">new</span> <span class="bu">String</span><span class="op">[]{});</span></span></code></pre></div>
<p>We could stop there, but there is one api that is in an incubator module in the early access builds that can replace our home rolled <code>WaitGroup</code>.</p>
<p>This is why I had <code>--add-modules=jdk.incubator.concurrent</code> in the jshell command up top.</p>
<p>A <code>StructuredTaskScope.ShutdownOnFailure</code> lets us submit an arbitrary number of tasks to the scope recursively and will only close after either all those tasks are complete. There is another implementation <code>StructuredTaskScope.ShutdownOnSuccess</code> that will finish after a single task succeeds.</p>
<p>This obviates the need to manually count up and down with a <code>WaitGroup</code>.</p>
<div class="sourceCode" id="cb46"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb46-1"><a href="#cb46-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">Arrays</span><span class="op">;</span></span>
<span id="cb46-2"><a href="#cb46-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">HashSet</span><span class="op">;</span></span>
<span id="cb46-3"><a href="#cb46-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">Set</span><span class="op">;</span></span>
<span id="cb46-4"><a href="#cb46-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">jdk</span><span class="op">.</span><span class="im">incubator</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">StructuredTaskScope</span><span class="op">;</span></span>
<span id="cb46-5"><a href="#cb46-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-6"><a href="#cb46-6" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> WebCrawler <span class="op">{</span></span>
<span id="cb46-7"><a href="#cb46-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">WebCrawler</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb46-8"><a href="#cb46-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb46-9"><a href="#cb46-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-10"><a href="#cb46-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">void</span> <span class="fu">crawlTask</span><span class="op">(</span></span>
<span id="cb46-11"><a href="#cb46-11" aria-hidden="true" tabindex="-1"></a>            <span class="bu">String</span> url<span class="op">,</span></span>
<span id="cb46-12"><a href="#cb46-12" aria-hidden="true" tabindex="-1"></a>            <span class="dt">int</span> depth<span class="op">,</span></span>
<span id="cb46-13"><a href="#cb46-13" aria-hidden="true" tabindex="-1"></a>            Fetcher fetcher<span class="op">,</span></span>
<span id="cb46-14"><a href="#cb46-14" aria-hidden="true" tabindex="-1"></a>            StructuredTaskScope<span class="op">.</span><span class="fu">ShutdownOnFailure</span></span>
<span id="cb46-15"><a href="#cb46-15" aria-hidden="true" tabindex="-1"></a>                    structuredTaskScope<span class="op">,</span></span>
<span id="cb46-16"><a href="#cb46-16" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Set</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> seen</span>
<span id="cb46-17"><a href="#cb46-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb46-18"><a href="#cb46-18" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>depth <span class="op">&lt;=</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb46-19"><a href="#cb46-19" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span><span class="op">;</span></span>
<span id="cb46-20"><a href="#cb46-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb46-21"><a href="#cb46-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-22"><a href="#cb46-22" aria-hidden="true" tabindex="-1"></a>        Fetcher<span class="op">.</span><span class="fu">Result</span> result<span class="op">;</span></span>
<span id="cb46-23"><a href="#cb46-23" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb46-24"><a href="#cb46-24" aria-hidden="true" tabindex="-1"></a>            result <span class="op">=</span> fetcher<span class="op">.</span><span class="fu">fetch</span><span class="op">(</span>url<span class="op">);</span></span>
<span id="cb46-25"><a href="#cb46-25" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span>FetcherException e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb46-26"><a href="#cb46-26" aria-hidden="true" tabindex="-1"></a>            <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>e<span class="op">.</span><span class="fu">getMessage</span><span class="op">());</span></span>
<span id="cb46-27"><a href="#cb46-27" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span><span class="op">;</span></span>
<span id="cb46-28"><a href="#cb46-28" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb46-29"><a href="#cb46-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-30"><a href="#cb46-30" aria-hidden="true" tabindex="-1"></a>        var body <span class="op">=</span> result<span class="op">.</span><span class="fu">body</span><span class="op">();</span></span>
<span id="cb46-31"><a href="#cb46-31" aria-hidden="true" tabindex="-1"></a>        var urls <span class="op">=</span> result<span class="op">.</span><span class="fu">urls</span><span class="op">();</span></span>
<span id="cb46-32"><a href="#cb46-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-33"><a href="#cb46-33" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">printf</span><span class="op">(</span></span>
<span id="cb46-34"><a href="#cb46-34" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;Found: </span><span class="sc">%s</span><span class="st"> </span><span class="sc">%s\n</span><span class="st">&quot;</span><span class="op">,</span> </span>
<span id="cb46-35"><a href="#cb46-35" aria-hidden="true" tabindex="-1"></a>            body<span class="op">,</span> </span>
<span id="cb46-36"><a href="#cb46-36" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Arrays</span><span class="op">.</span><span class="fu">toString</span><span class="op">(</span>urls<span class="op">)</span></span>
<span id="cb46-37"><a href="#cb46-37" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb46-38"><a href="#cb46-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-39"><a href="#cb46-39" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span>var u <span class="op">:</span> urls<span class="op">)</span> <span class="op">{</span></span>
<span id="cb46-40"><a href="#cb46-40" aria-hidden="true" tabindex="-1"></a>            <span class="kw">synchronized</span> <span class="op">(</span>seen<span class="op">)</span> <span class="op">{</span></span>
<span id="cb46-41"><a href="#cb46-41" aria-hidden="true" tabindex="-1"></a>                <span class="cf">if</span> <span class="op">(!</span>seen<span class="op">.</span><span class="fu">contains</span><span class="op">(</span>u<span class="op">))</span> <span class="op">{</span></span>
<span id="cb46-42"><a href="#cb46-42" aria-hidden="true" tabindex="-1"></a>                    seen<span class="op">.</span><span class="fu">add</span><span class="op">(</span>u<span class="op">);</span></span>
<span id="cb46-43"><a href="#cb46-43" aria-hidden="true" tabindex="-1"></a>                    structuredTaskScope<span class="op">.</span><span class="fu">fork</span><span class="op">(()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb46-44"><a href="#cb46-44" aria-hidden="true" tabindex="-1"></a>                        <span class="fu">crawlTask</span><span class="op">(</span></span>
<span id="cb46-45"><a href="#cb46-45" aria-hidden="true" tabindex="-1"></a>                                u<span class="op">,</span></span>
<span id="cb46-46"><a href="#cb46-46" aria-hidden="true" tabindex="-1"></a>                                depth <span class="op">-</span> <span class="dv">1</span><span class="op">,</span></span>
<span id="cb46-47"><a href="#cb46-47" aria-hidden="true" tabindex="-1"></a>                                fetcher<span class="op">,</span></span>
<span id="cb46-48"><a href="#cb46-48" aria-hidden="true" tabindex="-1"></a>                                structuredTaskScope<span class="op">,</span></span>
<span id="cb46-49"><a href="#cb46-49" aria-hidden="true" tabindex="-1"></a>                                seen</span>
<span id="cb46-50"><a href="#cb46-50" aria-hidden="true" tabindex="-1"></a>                        <span class="op">);</span></span>
<span id="cb46-51"><a href="#cb46-51" aria-hidden="true" tabindex="-1"></a>                        <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb46-52"><a href="#cb46-52" aria-hidden="true" tabindex="-1"></a>                    <span class="op">});</span></span>
<span id="cb46-53"><a href="#cb46-53" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb46-54"><a href="#cb46-54" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb46-55"><a href="#cb46-55" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb46-56"><a href="#cb46-56" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-57"><a href="#cb46-57" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb46-58"><a href="#cb46-58" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-59"><a href="#cb46-59" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">void</span> <span class="fu">crawl</span><span class="op">(</span><span class="bu">String</span> url<span class="op">,</span> <span class="dt">int</span> depth<span class="op">,</span> Fetcher fetcher<span class="op">)</span></span>
<span id="cb46-60"><a href="#cb46-60" aria-hidden="true" tabindex="-1"></a>            <span class="kw">throws</span> <span class="bu">InterruptedException</span> <span class="op">{</span></span>
<span id="cb46-61"><a href="#cb46-61" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span>var structuredTaskScope <span class="op">=</span></span>
<span id="cb46-62"><a href="#cb46-62" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">new</span> StructuredTaskScope<span class="op">.</span><span class="fu">ShutdownOnFailure</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb46-63"><a href="#cb46-63" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-64"><a href="#cb46-64" aria-hidden="true" tabindex="-1"></a>            structuredTaskScope<span class="op">.</span><span class="fu">fork</span><span class="op">(()</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb46-65"><a href="#cb46-65" aria-hidden="true" tabindex="-1"></a>                <span class="fu">crawlTask</span><span class="op">(</span></span>
<span id="cb46-66"><a href="#cb46-66" aria-hidden="true" tabindex="-1"></a>                        url<span class="op">,</span></span>
<span id="cb46-67"><a href="#cb46-67" aria-hidden="true" tabindex="-1"></a>                        depth<span class="op">,</span></span>
<span id="cb46-68"><a href="#cb46-68" aria-hidden="true" tabindex="-1"></a>                        fetcher<span class="op">,</span></span>
<span id="cb46-69"><a href="#cb46-69" aria-hidden="true" tabindex="-1"></a>                        structuredTaskScope<span class="op">,</span></span>
<span id="cb46-70"><a href="#cb46-70" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">new</span> <span class="bu">HashSet</span><span class="op">&lt;&gt;()</span></span>
<span id="cb46-71"><a href="#cb46-71" aria-hidden="true" tabindex="-1"></a>                <span class="op">);</span></span>
<span id="cb46-72"><a href="#cb46-72" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb46-73"><a href="#cb46-73" aria-hidden="true" tabindex="-1"></a>            <span class="op">});</span></span>
<span id="cb46-74"><a href="#cb46-74" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-75"><a href="#cb46-75" aria-hidden="true" tabindex="-1"></a>            structuredTaskScope<span class="op">.</span><span class="fu">join</span><span class="op">();</span></span>
<span id="cb46-76"><a href="#cb46-76" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb46-77"><a href="#cb46-77" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb46-78"><a href="#cb46-78" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-79"><a href="#cb46-79" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> </span>
<span id="cb46-80"><a href="#cb46-80" aria-hidden="true" tabindex="-1"></a>            <span class="kw">throws</span> <span class="bu">InterruptedException</span> <span class="op">{</span></span>
<span id="cb46-81"><a href="#cb46-81" aria-hidden="true" tabindex="-1"></a>        var fetcher <span class="op">=</span> FakeFetcher<span class="op">.</span><span class="fu">example</span><span class="op">();</span></span>
<span id="cb46-82"><a href="#cb46-82" aria-hidden="true" tabindex="-1"></a>        <span class="fu">crawl</span><span class="op">(</span><span class="st">&quot;https://golang.org/&quot;</span><span class="op">,</span> <span class="dv">4</span><span class="op">,</span> fetcher<span class="op">);</span></span>
<span id="cb46-83"><a href="#cb46-83" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb46-84"><a href="#cb46-84" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb47"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb47-1"><a href="#cb47-1" aria-hidden="true" tabindex="-1"></a>WebCrawler<span class="op">.</span><span class="fu">main</span><span class="op">(</span><span class="kw">new</span> <span class="bu">String</span><span class="op">[]{});</span></span></code></pre></div>
<p>This combines the role of the <code>ExecutorService</code> and the <code>WorkGroup</code> into one object which at the least makes for one less point of coordination and slightly cleaner code.</p>
<p>The exact shape the <code>StructuredTaskScope</code> api will take is very much in flux so if you are reading this a year or so in the future this snippet might not work.</p>
<h2 id="wrapping-up">Wrapping up</h2>
<p>Hopefully this was informative. If not thats fine too.</p>
<p>Leave questions, comments, and suggestions in the comments.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Java Serialization is Fun</title><link>https://mccue.dev/pages/4-28-22-serialization</link><description></description><pubDate>Thu, 28 Apr 0022 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Java Serialization is Fun</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Java Serialization is Fun</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
## What is serialization

<p>Serialization is the process of taking an in-memory representation of data and transforming it to a representation suitable for sending to another location.</p>
<p><img src="/pages/3-15-22-serialization-diagram.svg" 
alt="Diagram showing the serialization flow" ></img></p>
<p>Deserialization is the reverse of that process. Code takes a structured representation of data from some location and transforms it to a representation in-memory.</p>
<p><img src="/pages/3-15-22-deserialization-diagram.svg"
alt="Diagram showing the deserialization flow"></img></p>
<p>Every programming language has a myriad of approaches for performing these tasks. These approaches vary greatly depending on the semantics of the language, the semantics of the output format, and the culture surrounding both.</p>
<p>What sets Java's serialization mechanism apart is that the semantics of the language map extremely closely to that of the output format.</p>
<p>To fully appreciate the implications of this, allow me to take you on a bit of a tour of some other data formats.</p>
<h2 id="csv">CSV</h2>
<p>CSV, Comma Separated Values, is one of the most "basic" data formats out there.</p>
<p>Data is written one line at a time, with each value in a "row" separated by commas.</p>
<pre class="csv"><code>frankie,25,yes,Jun 8, 2023
casca,63,no,none</code></pre>
<p>By convention sometimes the very first row is used to store a "label" of what each "column" means.</p>
<pre class="csv"><code>First Name,Number of Cats,Tax Fraud?,Upcoming Court Date
frankie,25,yes,Jun 8, 2023
casca,63,no,none</code></pre>
<p>While labels can add contextual information, the actual "data model" that is directly encoded here is just rows of strings. Interpretation of these rows is dependent on a combination of convention and "out of band" information.</p>
<pre><code>CSV is
- a list of Rows

A Row is
- a list of strings</code></pre>
<p>CSV is popular in quite a few domains. It's easy to import and export to Spreadsheets, write out from sensors on an Arduino, and feed into Machine Learning libraries.</p>
<p>But its data model is not close to how most programs represent data. To go from a representation in memory to CSV is most always going to be a "lossy" process. To go from CSV back to that same representation in memory is requires knowledge about how to interpret the order of elements in a row, what each element means, etc.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">time</span><span class="op">.</span><span class="im">LocalDate</span><span class="op">;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Person</span><span class="op">(</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>        <span class="co">// have to assume that the first element is the name</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>        <span class="bu">String</span> name<span class="op">,</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>        <span class="co">// have to assume that the second element is this</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> numberOfCats<span class="op">,</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>        <span class="co">// How should a boolean be encoded?</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>        <span class="dt">boolean</span> taxFraud<span class="op">,</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>        <span class="co">// What format is the date in?</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>        <span class="co">// What is done when no value is known?</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>        LocalDate upcomingCourtDate</span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> Person <span class="fu">fromCsvRow</span><span class="op">(</span><span class="bu">List</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> row<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>        <span class="co">// Code here could be autogenerated if you assume</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>        <span class="co">// conventions, but it probably won&#39;t be</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>         </span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>row<span class="op">.</span><span class="fu">size</span><span class="op">()</span> <span class="op">!=</span> <span class="dv">4</span><span class="op">)</span> <span class="op">{</span> <span class="kw">...</span> <span class="op">}</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a>         </span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a>        <span class="bu">String</span> name <span class="op">=</span> row<span class="op">.</span><span class="fu">get</span><span class="op">(</span><span class="dv">0</span><span class="op">);</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> numberOfCats<span class="op">;</span></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true" tabindex="-1"></a>            numberOfCats <span class="op">=</span> <span class="bu">Integer</span><span class="op">.</span><span class="fu">parseInt</span><span class="op">(</span>row<span class="op">.</span><span class="fu">get</span><span class="op">(</span><span class="dv">1</span><span class="op">));</span></span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span><span class="bu">NumberFormatException</span> __<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-26"><a href="#cb4-26" aria-hidden="true" tabindex="-1"></a>             <span class="kw">...</span></span>
<span id="cb4-27"><a href="#cb4-27" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb4-28"><a href="#cb4-28" aria-hidden="true" tabindex="-1"></a>         </span>
<span id="cb4-29"><a href="#cb4-29" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ... and so on ...</span></span>
<span id="cb4-30"><a href="#cb4-30" aria-hidden="true" tabindex="-1"></a>         </span>
<span id="cb4-31"><a href="#cb4-31" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Person</span><span class="op">(</span>name<span class="op">,</span> numberOfCats<span class="op">,</span> <span class="kw">...</span><span class="op">);</span></span>
<span id="cb4-32"><a href="#cb4-32" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-33"><a href="#cb4-33" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb4-34"><a href="#cb4-34" aria-hidden="true" tabindex="-1"></a>    <span class="bu">List</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> <span class="fu">toCsvRow</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb4-35"><a href="#cb4-35" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ...</span></span>
<span id="cb4-36"><a href="#cb4-36" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="kw">this</span><span class="op">.</span><span class="fu">name</span><span class="op">,</span> <span class="kw">...</span><span class="op">);</span></span>
<span id="cb4-37"><a href="#cb4-37" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-38"><a href="#cb4-38" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="json">JSON</h2>
<p>"JavaScript Object Notation" is a format derived from the syntax of declaring object literals in JavaScript.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span> </span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>     <span class="dt">&quot;stockName&quot;</span><span class="fu">:</span> <span class="st">&quot;IDK&quot;</span><span class="fu">,</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>     <span class="dt">&quot;stockPrice&quot;</span><span class="fu">:</span> <span class="st">&quot;100USD&quot;</span><span class="fu">,</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>     <span class="dt">&quot;twitterComments&quot;</span><span class="fu">:</span> <span class="ot">[</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>          <span class="fu">{</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>               <span class="dt">&quot;retweets&quot;</span><span class="fu">:</span> <span class="dv">10</span><span class="fu">,</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>               <span class="dt">&quot;text&quot;</span><span class="fu">:</span> <span class="st">&quot;...&quot;</span><span class="fu">,</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>          <span class="fu">}</span><span class="ot">,</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>          <span class="fu">{</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>               <span class="dt">&quot;retweets&quot;</span><span class="fu">:</span> <span class="dv">20</span><span class="fu">,</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>               <span class="dt">&quot;text&quot;</span><span class="fu">:</span> <span class="st">&quot;...&quot;</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>          <span class="fu">}</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>     <span class="ot">]</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a><span class="fu">}</span></span></code></pre></div>
<p>Compared to CSV it is way more expressive. Instead of just rows of strings the data model includes dedicated representations for booleans, numbers, lists, and more.</p>
<pre><code>JSON is one of
- null
- a string
- a number
- a boolean
- a list of JSON
- a map of string to JSON</code></pre>
<p>This makes it somewhat of a "lowest common denominator" data format. Most modern languages have support for these data types and the structure can represent nested data much more ergonomically than "flat" formats like CSV.</p>
<p>The translation from a model in memory to JSON is still "lossy" in quite a few common cases though.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Recruiter</span><span class="op">(</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>        <span class="co">// Often enums will be translated to Strings</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>        TellsYouTheSalary tellsYouTheSalary<span class="op">,</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>        <span class="co">// Times might be put into a ISO-8601 format String </span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>        <span class="co">// or a Unix Time integer</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>        Instant postedFirstCringeStatus<span class="op">,</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>        <span class="co">// Sets aren&#39;t representable, so often</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>        <span class="co">// they will be encoded as lists</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Set</span><span class="op">&lt;</span>ReservationsAtDorsier<span class="op">&gt;</span> reservations<span class="op">,</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>        <span class="co">// Multiple possibilities with overlapping fields need a</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>        <span class="co">// convention for representing which is present</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>        LovedOne lovedOne</span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{}</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> TellsYouTheSalary <span class="op">{</span></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a>     UP_FRONT<span class="op">,</span></span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true" tabindex="-1"></a>     IF_YOU_ASK<span class="op">,</span></span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true" tabindex="-1"></a>     NEVER</span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> LovedOne <span class="op">{}</span></span>
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Cat</span><span class="op">(</span><span class="bu">String</span> name<span class="op">)</span> <span class="kw">implements</span> LovedOne <span class="op">{}</span></span>
<span id="cb7-23"><a href="#cb7-23" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Dog</span><span class="op">(</span><span class="bu">String</span> name<span class="op">)</span> <span class="kw">implements</span> LovedOne <span class="op">{}</span></span>
<span id="cb7-24"><a href="#cb7-24" aria-hidden="true" tabindex="-1"></a>record <span class="fu">NoOne</span><span class="op">()</span> <span class="kw">implements</span> LovedOne <span class="op">{}</span></span>
<span id="cb7-25"><a href="#cb7-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-26"><a href="#cb7-26" aria-hidden="true" tabindex="-1"></a><span class="co">// Both of these would be valid representations </span></span>
<span id="cb7-27"><a href="#cb7-27" aria-hidden="true" tabindex="-1"></a><span class="co">// depending on your conventions</span></span>
<span id="cb7-28"><a href="#cb7-28" aria-hidden="true" tabindex="-1"></a><span class="co">//</span></span>
<span id="cb7-29"><a href="#cb7-29" aria-hidden="true" tabindex="-1"></a><span class="co">// { &quot;tellsYouTheSalary&quot;: &quot;UP_FRONT&quot;,</span></span>
<span id="cb7-30"><a href="#cb7-30" aria-hidden="true" tabindex="-1"></a><span class="co">//   &quot;postedFirstCringeStatus&quot;: 1234,</span></span>
<span id="cb7-31"><a href="#cb7-31" aria-hidden="true" tabindex="-1"></a><span class="co">//   &quot;reservations&quot;: [],</span></span>
<span id="cb7-32"><a href="#cb7-32" aria-hidden="true" tabindex="-1"></a><span class="co">//   &quot;lovedOne&quot;: {&quot;type&quot;: &quot;cat&quot;, &quot;name&quot;: &quot;fred&quot; } }</span></span>
<span id="cb7-33"><a href="#cb7-33" aria-hidden="true" tabindex="-1"></a><span class="co">//</span></span>
<span id="cb7-34"><a href="#cb7-34" aria-hidden="true" tabindex="-1"></a><span class="co">// { &quot;tells_you_the_salary&quot;: &quot;up_front&quot;,</span></span>
<span id="cb7-35"><a href="#cb7-35" aria-hidden="true" tabindex="-1"></a><span class="co">//   &quot;posted_first_cringe_status&quot;: &quot;2020-07-10 15:00:00.000&quot;,</span></span>
<span id="cb7-36"><a href="#cb7-36" aria-hidden="true" tabindex="-1"></a><span class="co">//   &quot;reservations&quot;: {&quot;kind&quot;: &quot;set&quot;, &quot;contents&quot;: []},</span></span>
<span id="cb7-37"><a href="#cb7-37" aria-hidden="true" tabindex="-1"></a><span class="co">//   &quot;loved_one&quot;: {&quot;kind&quot;: &quot;cat&quot;, &quot;name&quot;: &quot;fred&quot;} } </span></span></code></pre></div>
<h2 id="edn">EDN</h2>
<p>"Extensible Data Notation" is a format that came out of the syntax of the Clojure programming language.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>{ </span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>     <span class="at">:teethLeft</span>       #{<span class="dv">5</span> <span class="dv">12</span> <span class="dv">14</span> <span class="dv">23</span>}</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>     <span class="at">:countryOfOrigin</span> <span class="st">&quot;United States of America&quot;</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>     <span class="at">:whelped</span>         #inst <span class="st">&quot;2006-04-12T00:00:00.000-00:00&quot;</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>     <span class="at">:parents</span>         #{#pokemon <span class="st">&quot;Skitty&quot;</span> </span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>                        #pokemon <span class="st">&quot;Wailord&quot;</span>}</span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>     <span class="at">:moves</span>           [<span class="at">:quick-attack</span> <span class="at">:tail-whip</span>]</span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<p>More likely than not you have not heard of it. That's a shame because it's pretty cool.</p>
<p>Compared to JSON it has a larger base set of types and a defined mechanism for extending that set.</p>
<pre><code>EDN is one of
- null
- a string
- an integer
- a vector of EDN
- a map of EDN to EDN
- a set of EDN
- a keyword
- a symbol
- an element with a tag and an EDN value

... and a few other base types ...</code></pre>
<p>The key capability for the purposes of this discussion is that you are able to attach an arbitrary tag to any EDN value.</p>
<p>This serves the same purpose as the <code>{ "type": ..., "data": ... }</code> pattern in JSON, but by virtue of being part of the format that encoding is not "positional".</p>
<p>As an example of what I mean, in JSON the way you know that a given field contains a moment in time is by knowing implicitly that the string under a specific name like "createdAt" will be formatted in as a timestamp.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span> <span class="dt">&quot;createdAt&quot;</span><span class="fu">:</span> <span class="st">&quot;2020-08-12T00:00:00.000-00:00&quot;</span> <span class="fu">}</span></span></code></pre></div>
<p>In EDN if you know how a given tag like <code>#inst</code> should be interpreted then you can automatically do that interpretation no matter where in the structure of the document it appears.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>{ <span class="st">&quot;createdAt&quot;</span> #inst<span class="st">&quot;2020-08-12T00:00:00.000-00:00&quot;</span> }</span></code></pre></div>
<p>This means that translation to and from EDN doesn't have to be lossy in the same way JSON serialization is. If you have a custom aggregate, you can define a tag for that aggregate and include whatever data is needed to reconstruct it</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span><span class="im"> some</span><span class="op">.</span><span class="im">pack</span><span class="op">;</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Mascot <span class="op">{}</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Gecko</span><span class="op">(</span><span class="dt">int</span> age<span class="op">)</span> <span class="op">{}</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Sailor</span><span class="op">(</span><span class="dt">int</span> age<span class="op">,</span> <span class="dt">boolean</span> captain<span class="op">)</span> <span class="op">{}</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a><span class="co">// This could be encoded as</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a><span class="co">// #some.pack.Gecko{:age 12}</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a><span class="co">// #some.pack.Sailor{:age 35 :captain true}</span></span></code></pre></div>
<p>You can also have non-string keys <code>{{:map "key"} "whatever value"}</code>. Y'all are missing out.</p>
<h2 id="javas-serialization-format">Java's Serialization Format</h2>
<p>"Java Serialization" is a mechanism by which any object in memory can be serialized to and deserialized from a sequence of bytes while preserving the same semantics that object had in memory.</p>
<p>For regular classes, it accomplishes this by recursively scraping the fields of the class and producing bytes as specified <a href="https://docs.oracle.com/en/java/javase/18/docs/specs/serialization/protocol.html">here</a>. Then when the bytes are read back in, it reconstructs the object by doing the reverse.</p>
<p>For "special" classes (Strings, Enums, and Records) there are slightly different rules, but the effect is essentially the same.</p>
<p>This is exceedingly hard to properly communicate with words, so here is a quick walk-through.</p>
<p>You can follow along by pasting each snippet into <a href="https://tryjshell.org/">JShell</a>.</p>
<p>(If you have Java installed, run <code>jshell</code> on the command line)</p>
<h3 id="step-1-make-a-serializable-class">Step 1. Make a Serializable class</h3>
<p>Implement the <code>Serializable</code> marker interface and make sure every field of your class does as well or is a primitive.</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">io</span><span class="op">.</span><span class="im">Serializable</span><span class="op">;</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> LabeledPosition <span class="kw">implements</span> <span class="bu">Serializable</span> <span class="op">{</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="bu">String</span> label<span class="op">;</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">int</span> x<span class="op">;</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">int</span> y<span class="op">;</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">LabeledPosition</span><span class="op">(</span><span class="bu">String</span> label<span class="op">,</span> <span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">label</span> <span class="op">=</span> label<span class="op">;</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">x</span> <span class="op">=</span> x<span class="op">;</span></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">y</span> <span class="op">=</span> y<span class="op">;</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">String</span> <span class="fu">toString</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="st">&quot;LabeledPosition[label=&quot;</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">label</span> <span class="op">+</span></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, x=&quot;</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">x</span> <span class="op">+</span></span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, y=&quot;</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">y</span> <span class="op">+</span></span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;]&quot;</span><span class="op">;</span></span>
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 id="step-2-make-an-objectoutputstream">Step 2. Make an ObjectOutputStream</h3>
<p>You can make this special class by wrapping any existing <code>OutputStream</code>. This is where the bytes of your serialized form will be written.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">io</span><span class="op">.</span><span class="im">ByteArrayOutputStream</span><span class="op">;</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">io</span><span class="op">.</span><span class="im">ObjectOutputStream</span><span class="op">;</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>var byteArrayOutputStream <span class="op">=</span> <span class="kw">new</span> <span class="bu">ByteArrayOutputStream</span><span class="op">();</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>var objectOutputStream <span class="op">=</span> <span class="kw">new</span> <span class="bu">ObjectOutputStream</span><span class="op">(</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>        byteArrayOutputStream</span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span></code></pre></div>
<h3 id="step-3-write-your-object-to-the-objectoutputstream">Step 3. Write your object to the ObjectOutputStream</h3>
<p>This is a binary format, so there isn't any fun visual aid, but you can inspect and see that indeed we have written some bytes.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>objectOutputStream<span class="op">.</span><span class="fu">writeObject</span><span class="op">(</span><span class="kw">new</span> <span class="fu">LabeledPosition</span><span class="op">(</span><span class="st">&quot;bob&quot;</span><span class="op">,</span> <span class="dv">9</span><span class="op">,</span> <span class="dv">1</span><span class="op">));</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="dt">byte</span><span class="op">[]</span> bytes <span class="op">=</span> byteArrayOutputStream<span class="op">.</span><span class="fu">toByteArray</span><span class="op">();</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="bu">Arrays</span><span class="op">.</span><span class="fu">toString</span><span class="op">(</span>bytes<span class="op">));</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a><span class="co">// [-84, -19, 0, ..., 98, 111, 98]</span></span></code></pre></div>
<h3 id="step-4-create-an-objectinputstream">Step 4. Create an ObjectInputStream</h3>
<p>This is very similar to how we wrote the object out. Wrap any existing <code>InputStream</code>.</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">io</span><span class="op">.</span><span class="im">ByteArrayInputStream</span><span class="op">;</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">io</span><span class="op">.</span><span class="im">ObjectInputStream</span><span class="op">;</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>var byteArrayInputStream <span class="op">=</span> <span class="kw">new</span> <span class="bu">ByteArrayInputStream</span><span class="op">(</span>bytes<span class="op">);</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>var objectInputStream <span class="op">=</span> <span class="kw">new</span> <span class="bu">ObjectInputStream</span><span class="op">(</span>byteArrayInputStream<span class="op">);</span></span></code></pre></div>
<h3 id="step-5-read-in-the-object-you-wrote-out">Step 5. Read in the object you wrote out</h3>
<div class="sourceCode" id="cb17"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>var labeledPosition <span class="op">=</span> </span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>        <span class="op">(</span>LabeledPosition<span class="op">)</span> objectInputStream<span class="op">.</span><span class="fu">readObject</span><span class="op">();</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a><span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>labeledPosition<span class="op">);</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a><span class="co">// LabeledPosition[label=bob, x=9, y=1]</span></span></code></pre></div>
<h3 id="step-6-make-another-serializable-class">Step 6. Make another Serializable class</h3>
<p>Hold with me here, this gets good.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a>record <span class="fu">TwoLists</span><span class="op">(</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>     <span class="bu">List</span><span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;</span> listOne<span class="op">,</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>     <span class="bu">List</span><span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;</span> listTwo</span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="kw">implements</span> <span class="bu">Serializable</span> <span class="op">{}</span></span></code></pre></div>
<h3 id="step-7-make-a-mutable-object">Step 7. Make a mutable object</h3>
<p>So here we will make an instance of this TwoLists record where each List is the exact same list in memory.</p>
<p>This means that if we add to either <code>listOne</code> or <code>listTwo</code> both will be updated.</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>var theList <span class="op">=</span> <span class="kw">new</span> <span class="bu">ArrayList</span><span class="op">&lt;&gt;(</span><span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="dv">1</span><span class="op">,</span> <span class="dv">2</span><span class="op">,</span> <span class="dv">3</span><span class="op">));</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>var twoLists <span class="op">=</span> <span class="kw">new</span> <span class="fu">TwoLists</span><span class="op">(</span>theList<span class="op">,</span> theList<span class="op">);</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a><span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>twoLists<span class="op">);</span></span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a><span class="co">// TwoLists[listOne=[1, 2, 3], listTwo=[1, 2, 3]]</span></span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a>twoLists<span class="op">.</span><span class="fu">listOne</span><span class="op">().</span><span class="fu">add</span><span class="op">(</span><span class="dv">4</span><span class="op">);</span></span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a><span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>twoLists<span class="op">);</span></span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a><span class="co">// TwoLists[listOne=[1, 2, 3, 4], listTwo=[1, 2, 3, 4]]</span></span></code></pre></div>
<h3 id="step-8-write-that-mutable-object-to-an-objectoutputstream">Step 8. Write that mutable object to an ObjectOutputStream</h3>
<div class="sourceCode" id="cb20"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a>var byteArrayOutputStream <span class="op">=</span> <span class="kw">new</span> <span class="bu">ByteArrayOutputStream</span><span class="op">();</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>var objectOutputStream <span class="op">=</span> <span class="kw">new</span> <span class="bu">ObjectOutputStream</span><span class="op">(</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>        byteArrayOutputStream</span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a>objectOutputStream<span class="op">.</span><span class="fu">writeObject</span><span class="op">(</span>twoLists<span class="op">);</span></span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a><span class="dt">byte</span><span class="op">[]</span> bytes <span class="op">=</span> byteArrayOutputStream<span class="op">.</span><span class="fu">toByteArray</span><span class="op">();</span></span></code></pre></div>
<h3 id="step-9-read-that-mutable-object-from-an-objectinputstream">Step 9. Read that mutable object from an ObjectInputStream</h3>
<div class="sourceCode" id="cb21"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>var byteArrayInputStream <span class="op">=</span> <span class="kw">new</span> <span class="bu">ByteArrayInputStream</span><span class="op">(</span>bytes<span class="op">);</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>var objectInputStream <span class="op">=</span> <span class="kw">new</span> <span class="bu">ObjectInputStream</span><span class="op">(</span>byteArrayInputStream<span class="op">);</span></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>var roundTripped <span class="op">=</span> <span class="op">(</span>TwoLists<span class="op">)</span> objectInputStream<span class="op">.</span><span class="fu">readObject</span><span class="op">();</span></span></code></pre></div>
<h3 id="step-10-oh-no">Step 10. Oh no</h3>
<p>Oh yeah.</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>roundTripped<span class="op">);</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a><span class="co">// TwoLists[listOne=[1, 2, 3, 4], listTwo=[1, 2, 3, 4]]</span></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a><span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>roundTripped<span class="op">.</span><span class="fu">listOne</span><span class="op">()</span> <span class="op">==</span> roundTripped<span class="op">.</span><span class="fu">listTwo</span><span class="op">());</span></span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a><span class="co">// true</span></span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a>roundTripped<span class="op">.</span><span class="fu">listOne</span><span class="op">().</span><span class="fu">add</span><span class="op">(</span><span class="dv">5</span><span class="op">);</span></span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a><span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>roundTripped<span class="op">);</span></span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a><span class="co">// TwoLists[listOne=[1, 2, 3, 4, 5], listTwo=[1, 2, 3, 4, 5]]</span></span></code></pre></div>
<p>If you have the same object two places in the "object graph" of something you are serializing, the fact that those two places hold the same object is preserved.</p>
<p>Because of this, you can even seamlessly serialize things like circular linked lists.</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> CircularThing <span class="kw">implements</span> <span class="bu">Serializable</span> <span class="op">{</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>    CircularThing next<span class="op">;</span></span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a><span class="co">// How would you write this in JSON?</span></span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a>var circular <span class="op">=</span> <span class="kw">new</span> <span class="fu">CircularThing</span><span class="op">();</span></span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a>circular<span class="op">.</span><span class="fu">next</span> <span class="op">=</span> circular<span class="op">;</span></span></code></pre></div>
<h2 id="what-is-this-good-for">What is this good for?</h2>
<ul>
<li>Prototypes and Projects on a tight deadline.</li>
</ul>
<p>Since you can save any arbitrary object and there is no extra code needed to make that just "work", Java Serialization can be a very useful crutch for getting code working quickly.</p>
<ul>
<li>Saving arbitrary objects that were very expensive to create</li>
</ul>
<p>In the Python world, <a href="https://docs.python.org/3/library/pickle.html">a similar utility</a> is often used to save the results of training ML models. It's easy to imagine that Java Serialization could see similar use if Data Science ever took off on the JVM in the same way.</p>
<ul>
<li>Dynamically sending code to another machine</li>
</ul>
<p><a href="https://spark.apache.org/docs/latest/tuning.html#data-serialization">Spark</a> uses this mechanism for distributing Java objects across different nodes.</p>
<h2 id="what-is-this-bad-for">What is this bad for?</h2>
<ul>
<li>Models that will change over time</li>
</ul>
<p>While you can version serialized objects, doing so is non-obvious and error-prone. Making a class serializable, especially in a library, can therefore be a fairly large maintenance problem.</p>
<ul>
<li>Applications where an untrusted entity might be able to send data to your application</li>
</ul>
<p>If you read serialized data that you did not write, that is a giant security hole. There is more nuance to it, but basically if you read untrusted serialized data then any hacker can get full access to your system. I'm not going to go in to every way you can exploit serialization, but <a href="https://www.youtube.com/watch?v=dOgfWXw9VrI">this talk</a> should give you a basic idea.</p>
<p>This was a crucial part of the <a href="https://mogwailabs.de/en/blog/2021/12/vulnerability-notes-log4shell/">Log4Shell</a> vulnerability.</p>
<ul>
<li>Things that should be edited by humans like configuration files</li>
</ul>
<p>Because serialized objects are stored in a binary format, it is impossible to read without special tooling and prohibitively hard to write by hand.</p>
<ul>
<li>Sending data outside the Java/JVM world</li>
</ul>
<p>While technically you could write a parser for the binary format in your language of choice and recover the information, you would likely be the first. If you need to share values with programs in other languages, falling back to a "lowest common denominator" like JSON is a better strategy.</p>
<hr />
<p>Part of what made writing this so hard for me is that most people who I've seen be shown serialization were shown it very early in their curriculums. It's hard to explain nuance around the object model and encapsulation when talking to someone who learned what classes are two weeks back, so I left most of that out.</p>
<p>Leave a comment below if anything was unclear, incorrect, or you would like to learn more.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Java's options for options</title><link>https://mccue.dev/pages/2-8-22-options-for-options</link><description></description><pubDate>Tue, 08 Feb 0022 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Java's options for options</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Java's options for options</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
# Hypothetical 1
Imagine that you made a bit of code that outputs JSON.

<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> JsonWriter <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">JsonWriter</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>            Json json</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>By default your output contains no extra whitespace, but you want to provide an option to the user to print that JSON with some indentation.</p>
<h3 id="without-indentation">Without indentation</h3>
<div class="sourceCode" id="cb2"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">[</span><span class="fu">{</span><span class="dt">&quot;name&quot;</span><span class="fu">:</span><span class="st">&quot;joe&quot;</span><span class="fu">,</span><span class="dt">&quot;age&quot;</span><span class="fu">:</span><span class="dv">35</span><span class="fu">}</span><span class="ot">]</span></span></code></pre></div>
<h3 id="with-indentation">With indentation</h3>
<div class="sourceCode" id="cb3"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">[</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    <span class="fu">{</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>        <span class="dt">&quot;name&quot;</span><span class="fu">:</span><span class="st">&quot;joe&quot;</span><span class="fu">,</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>        <span class="dt">&quot;age&quot;</span><span class="fu">:</span><span class="dv">35</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    <span class="fu">}</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="ot">]</span></span></code></pre></div>
<h2 id="option-1-dont-support-it">Option 1. Don't support it</h2>
<p>Any toggles you add to your api are toggles you might need to support now and forever more. Depending on the code you are writing and who its consumers are, it might make more sense to provide a more restricted api.</p>
<h2 id="option-2-make-another-method">Option 2. Make another method</h2>
<p>With only a single option you want configurable, you can just expose a method with a different name.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> JsonWriter <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">JsonWriter</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>            Json json</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJsonWithIndentation</span><span class="op">(</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>            Json json</span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">);</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJsonWithIndentation</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">);</span></span></code></pre></div>
<h2 id="option-3-add-a-boolean-argument">Option 3. Add a boolean argument</h2>
<p>A single option is either on or off. True or false. That is often the domain of a boolean.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> JsonWriter <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">JsonWriter</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>            Json json<span class="op">,</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>            <span class="dt">boolean</span> indent</span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>indent<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>            <span class="kw">...</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>            <span class="kw">...</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb7"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> <span class="kw">true</span><span class="op">);</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> <span class="kw">false</span><span class="op">);</span></span></code></pre></div>
<h2 id="option-4-add-an-enum-argument">Option 4. Add an enum argument</h2>
<p>Booleans are great, but for understandability at the call-site you might want to provide an enum with two possible values instead.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">enum</span> Indentation <span class="op">{</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>    INDENT<span class="op">,</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>    DO_NOT_INDENT</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> JsonWriter <span class="op">{</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">JsonWriter</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>            Json json<span class="op">,</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>            Indentation indent</span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>        <span class="cf">switch</span> <span class="op">(</span>indent<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> INDENT <span class="op">-&gt;</span> <span class="kw">...</span></span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> DO_NOT_INDENT <span class="op">-&gt;</span> <span class="kw">...</span></span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb9"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> Indentation<span class="op">.</span><span class="fu">INDENT</span><span class="op">);</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> Indentation<span class="op">.</span><span class="fu">DO_NOT_INDENT</span><span class="op">);</span></span></code></pre></div>
<hr />
<h1 id="hypothetical-2">Hypothetical 2</h1>
<p>Say now you get some feedback that while the indentation style is great for objects, it is sometimes not great for JSON with long arrays.</p>
<h2 id="no-indentation">No indentation</h2>
<div class="sourceCode" id="cb10"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ot">[</span><span class="fu">{</span><span class="dt">&quot;numbers&quot;</span><span class="fu">:</span><span class="ot">[</span><span class="dv">1</span><span class="ot">,</span><span class="dv">2</span><span class="ot">,</span><span class="dv">3</span><span class="ot">]</span><span class="fu">}</span><span class="ot">]</span></span></code></pre></div>
<h3 id="indent-everything">Indent Everything</h3>
<div class="sourceCode" id="cb11"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ot">[</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>  <span class="fu">{</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">&quot;numbers&quot;</span><span class="fu">:</span> <span class="ot">[</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>        <span class="dv">1</span><span class="ot">,</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>        <span class="dv">2</span><span class="ot">,</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>        <span class="dv">3</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>    <span class="ot">]</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>  <span class="fu">}</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a><span class="ot">]</span></span></code></pre></div>
<h3 id="indent-objects">Indent Objects</h3>
<div class="sourceCode" id="cb12"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ot">[</span><span class="fu">{</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">&quot;numbers&quot;</span><span class="fu">:</span> <span class="ot">[</span><span class="dv">1</span><span class="ot">,</span> <span class="dv">2</span><span class="ot">,</span> <span class="dv">3</span><span class="ot">]</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a><span class="fu">}</span><span class="ot">]</span></span></code></pre></div>
<h3 id="indent-arrays">Indent Arrays</h3>
<div class="sourceCode" id="cb13"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ot">[</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>  <span class="fu">{</span><span class="dt">&quot;numbers&quot;</span><span class="fu">:</span> <span class="ot">[</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>        <span class="dv">1</span><span class="ot">,</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>        <span class="dv">2</span><span class="ot">,</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>        <span class="dv">3</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>  <span class="ot">]</span><span class="fu">}</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a><span class="ot">]</span></span></code></pre></div>
<h2 id="option-5-make-methods-for-requested-combinations">Option 5. Make methods for requested combinations</h2>
<p>Your users just want a way to turn off indentation for arrays. Give it to them.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> JsonWriter <span class="op">{</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">JsonWriter</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>            Json json</span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJsonIndentObjects</span><span class="op">(</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a>            Json json</span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb14-16"><a href="#cb14-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-17"><a href="#cb14-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-18"><a href="#cb14-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJsonIndentEverything</span><span class="op">(</span></span>
<span id="cb14-19"><a href="#cb14-19" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb14-20"><a href="#cb14-20" aria-hidden="true" tabindex="-1"></a>            Json json</span>
<span id="cb14-21"><a href="#cb14-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb14-22"><a href="#cb14-22" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb14-23"><a href="#cb14-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-24"><a href="#cb14-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb15"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">);</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJsonIndentObjects</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">);</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJsonIndentEverything</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">);</span></span></code></pre></div>
<h2 id="option-6-make-methods-for-every-combination">Option 6. Make methods for every combination</h2>
<p>There are four logical settings that come out of two different flags, so you can certainly provide all four options as methods. Could save you time later.</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> JsonWriter <span class="op">{</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">JsonWriter</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>            Json json</span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJsonIndentObjects</span><span class="op">(</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a>            Json json</span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJsonIndentArrays</span><span class="op">(</span></span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb16-20"><a href="#cb16-20" aria-hidden="true" tabindex="-1"></a>            Json json</span>
<span id="cb16-21"><a href="#cb16-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-22"><a href="#cb16-22" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb16-23"><a href="#cb16-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-24"><a href="#cb16-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-25"><a href="#cb16-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJsonIndentEverything</span><span class="op">(</span></span>
<span id="cb16-26"><a href="#cb16-26" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb16-27"><a href="#cb16-27" aria-hidden="true" tabindex="-1"></a>            Json json</span>
<span id="cb16-28"><a href="#cb16-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-29"><a href="#cb16-29" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb16-30"><a href="#cb16-30" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-31"><a href="#cb16-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb17"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">);</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJsonIndentObjects</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">);</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJsonIndentArrays</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">);</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJsonIndentEverything</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">);</span></span></code></pre></div>
<h2 id="option-7-have-two-boolean-arguments">Option 7. Have two boolean arguments</h2>
<p>Two logically independent things to configure, you can always take a boolean for each.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> JsonWriter <span class="op">{</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">JsonWriter</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>            Json json<span class="op">,</span></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a>            <span class="dt">boolean</span> indentObjects<span class="op">,</span></span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a>            <span class="dt">boolean</span> indentArrays</span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>indentObjects<span class="op">)</span> <span class="op">{</span></span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>indentArrays<span class="op">)</span> <span class="op">{</span></span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a>                <span class="kw">...</span></span>
<span id="cb18-13"><a href="#cb18-13" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb18-14"><a href="#cb18-14" aria-hidden="true" tabindex="-1"></a>            <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb18-15"><a href="#cb18-15" aria-hidden="true" tabindex="-1"></a>                <span class="kw">...</span></span>
<span id="cb18-16"><a href="#cb18-16" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb18-17"><a href="#cb18-17" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb18-18"><a href="#cb18-18" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb18-19"><a href="#cb18-19" aria-hidden="true" tabindex="-1"></a>            <span class="kw">...</span></span>
<span id="cb18-20"><a href="#cb18-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb18-21"><a href="#cb18-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb18-22"><a href="#cb18-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb19"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> <span class="kw">true</span><span class="op">,</span> <span class="kw">true</span><span class="op">);</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> <span class="kw">true</span><span class="op">,</span> <span class="kw">false</span><span class="op">);</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> <span class="kw">false</span><span class="op">,</span> <span class="kw">true</span><span class="op">);</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> <span class="kw">false</span><span class="op">,</span> <span class="kw">false</span><span class="op">);</span></span></code></pre></div>
<h2 id="option-8-have-two-enum-arguments">Option 8. Have two enum arguments</h2>
<p>Booleans describe everything, but enums are still more explicit.</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">enum</span> Indentation <span class="op">{</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>    INDENT<span class="op">,</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>    DO_NOT_INDENT</span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> JsonWriter <span class="op">{</span></span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">JsonWriter</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb20-11"><a href="#cb20-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb20-12"><a href="#cb20-12" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb20-13"><a href="#cb20-13" aria-hidden="true" tabindex="-1"></a>            Json json<span class="op">,</span></span>
<span id="cb20-14"><a href="#cb20-14" aria-hidden="true" tabindex="-1"></a>            Indentation indentObjects<span class="op">,</span></span>
<span id="cb20-15"><a href="#cb20-15" aria-hidden="true" tabindex="-1"></a>            Indentation indentArrays</span>
<span id="cb20-16"><a href="#cb20-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-17"><a href="#cb20-17" aria-hidden="true" tabindex="-1"></a>        <span class="cf">switch</span> <span class="op">(</span>indentObjects<span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-18"><a href="#cb20-18" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> INDENT <span class="op">-&gt;</span> <span class="cf">switch</span> <span class="op">(</span>indentArrays<span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-19"><a href="#cb20-19" aria-hidden="true" tabindex="-1"></a>                <span class="cf">case</span> INDENT <span class="op">-&gt;</span> <span class="kw">...</span></span>
<span id="cb20-20"><a href="#cb20-20" aria-hidden="true" tabindex="-1"></a>                <span class="cf">case</span> DO_NOT_INDENT <span class="op">-&gt;</span> <span class="kw">...</span></span>
<span id="cb20-21"><a href="#cb20-21" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb20-22"><a href="#cb20-22" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> DO_NOT_INDENT <span class="op">-&gt;</span> <span class="kw">...</span></span>
<span id="cb20-23"><a href="#cb20-23" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb20-24"><a href="#cb20-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-25"><a href="#cb20-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb21"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> Indentation<span class="op">.</span><span class="fu">INDENT</span><span class="op">,</span> Indentation<span class="op">.</span><span class="fu">INDENT</span><span class="op">);</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> Indentation<span class="op">.</span><span class="fu">INDENT</span><span class="op">,</span> Indentation<span class="op">.</span><span class="fu">DO_NOT_INDENT</span><span class="op">);</span></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> Indentation<span class="op">.</span><span class="fu">DO_NOT_INDENT</span><span class="op">,</span> Indentation<span class="op">.</span><span class="fu">INDENT</span><span class="op">);</span></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>        out<span class="op">,</span> </span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>        json<span class="op">,</span> </span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a>        Indentation<span class="op">.</span><span class="fu">DO_NOT_INDENT</span><span class="op">,</span> </span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a>        Indentation<span class="op">.</span><span class="fu">DO_NOT_INDENT</span></span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span></code></pre></div>
<h2 id="option-9-take-options-as-bit-flags">Option 9. Take options as bit flags</h2>
<p>It's an old school solution and maybe a bit too clever, but you are feeling old school and clever.</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> Indentation <span class="op">{</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">final</span> <span class="dt">int</span> NO_INDENTATION <span class="op">=</span> <span class="bn">0b00</span><span class="op">;</span></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">final</span> <span class="dt">int</span> INDENT_OBJECTS <span class="op">=</span> <span class="bn">0b01</span><span class="op">;</span></span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">final</span> <span class="dt">int</span> INDENT_ARRAYS <span class="op">=</span> <span class="bn">0b10</span><span class="op">;</span></span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Indentation</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> JsonWriter <span class="op">{</span></span>
<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">JsonWriter</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb22-13"><a href="#cb22-13" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb22-14"><a href="#cb22-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb22-15"><a href="#cb22-15" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb22-16"><a href="#cb22-16" aria-hidden="true" tabindex="-1"></a>            Json json<span class="op">,</span></span>
<span id="cb22-17"><a href="#cb22-17" aria-hidden="true" tabindex="-1"></a>            <span class="dt">int</span> indentation</span>
<span id="cb22-18"><a href="#cb22-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb22-19"><a href="#cb22-19" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">((</span>indentation <span class="op">&amp;</span> Indentation<span class="op">.</span><span class="fu">INDENT_OBJECTS</span><span class="op">)</span> <span class="op">!=</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb22-20"><a href="#cb22-20" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">((</span>indentation <span class="op">&amp;</span> Indentation<span class="op">.</span><span class="fu">INDENT_ARRAYS</span><span class="op">)</span> <span class="op">!=</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb22-21"><a href="#cb22-21" aria-hidden="true" tabindex="-1"></a>                <span class="kw">...</span></span>
<span id="cb22-22"><a href="#cb22-22" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb22-23"><a href="#cb22-23" aria-hidden="true" tabindex="-1"></a>            <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb22-24"><a href="#cb22-24" aria-hidden="true" tabindex="-1"></a>                <span class="kw">...</span></span>
<span id="cb22-25"><a href="#cb22-25" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb22-26"><a href="#cb22-26" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb22-27"><a href="#cb22-27" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb22-28"><a href="#cb22-28" aria-hidden="true" tabindex="-1"></a>            <span class="kw">...</span></span>
<span id="cb22-29"><a href="#cb22-29" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb22-30"><a href="#cb22-30" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb22-31"><a href="#cb22-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<pre><code>writeJson(
        out, 
        json, 
        Indentation.INDENT_OBJECTS | Indentation.INDENT_ARRAYS, 
);
writeJson(out, json, Indentation.INDENT_OBJECTS);
writeJson(out, json, Indentation.INDENT_ARRAYS);
writeJson(out, json, Indentation.NO_INDENTATION);</code></pre>
<h2 id="option-10-take-an-enumset">Option 10. Take an EnumSet</h2>
<p>Rather than waste a parameter on each flag, explicitly take the set of behaviors they want to enable.</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">enum</span> Indent <span class="op">{</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>    OBJECTS<span class="op">,</span></span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>    ARRAYS</span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> JsonWriter <span class="op">{</span></span>
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">JsonWriter</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-11"><a href="#cb24-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb24-12"><a href="#cb24-12" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb24-13"><a href="#cb24-13" aria-hidden="true" tabindex="-1"></a>            Json json<span class="op">,</span></span>
<span id="cb24-14"><a href="#cb24-14" aria-hidden="true" tabindex="-1"></a>            <span class="bu">EnumSet</span><span class="op">&lt;</span>Indent<span class="op">&gt;</span> indent</span>
<span id="cb24-15"><a href="#cb24-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb24-16"><a href="#cb24-16" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>indent<span class="op">.</span><span class="fu">contains</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">OBJECTS</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb24-17"><a href="#cb24-17" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>indent<span class="op">.</span><span class="fu">contains</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">ARRAYS</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb24-18"><a href="#cb24-18" aria-hidden="true" tabindex="-1"></a>                <span class="kw">...</span></span>
<span id="cb24-19"><a href="#cb24-19" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb24-20"><a href="#cb24-20" aria-hidden="true" tabindex="-1"></a>            <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb24-21"><a href="#cb24-21" aria-hidden="true" tabindex="-1"></a>                <span class="kw">...</span></span>
<span id="cb24-22"><a href="#cb24-22" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb24-23"><a href="#cb24-23" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb24-24"><a href="#cb24-24" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb24-25"><a href="#cb24-25" aria-hidden="true" tabindex="-1"></a>            <span class="kw">...</span></span>
<span id="cb24-26"><a href="#cb24-26" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb24-27"><a href="#cb24-27" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb24-28"><a href="#cb24-28" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<pre><code>writeJson(out, json, EnumSet.of(Indent.OBJECTS, Indent.ARRAYS));
writeJson(out, json, EnumSet.of(Indent.OBJECTS));
writeJson(out, json, EnumSet.of(Indent.ARRAYS));
writeJson(out, json, EnumSet.noneOf(Indent.class));</code></pre>
<h2 id="option-11-take-a-transparent-config-object">Option 11. Take a transparent config object</h2>
<p>Similar to just taking two booleans, but putting them in an object means you can refer to a set of options as a concrete "thing". This could help you keep the most common usages terse.</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Options</span><span class="op">(</span><span class="dt">boolean</span> indentObjects<span class="op">,</span> <span class="dt">boolean</span> indentArrays<span class="op">)</span> <span class="op">{</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">final</span> Options INDENT_EVERYTHING <span class="op">=</span></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="fu">Options</span><span class="op">(</span><span class="kw">true</span><span class="op">,</span> <span class="kw">true</span><span class="op">);</span></span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">final</span> Options NO_INDENT <span class="op">=</span></span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="fu">Options</span><span class="op">(</span><span class="kw">false</span><span class="op">,</span> <span class="kw">false</span><span class="op">);</span></span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-8"><a href="#cb26-8" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb26-9"><a href="#cb26-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-10"><a href="#cb26-10" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> JsonWriter <span class="op">{</span></span>
<span id="cb26-11"><a href="#cb26-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">JsonWriter</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb26-12"><a href="#cb26-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-13"><a href="#cb26-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb26-14"><a href="#cb26-14" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb26-15"><a href="#cb26-15" aria-hidden="true" tabindex="-1"></a>            Json json<span class="op">,</span></span>
<span id="cb26-16"><a href="#cb26-16" aria-hidden="true" tabindex="-1"></a>            Options options</span>
<span id="cb26-17"><a href="#cb26-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb26-18"><a href="#cb26-18" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>options<span class="op">.</span><span class="fu">indentObjects</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb26-19"><a href="#cb26-19" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>options<span class="op">.</span><span class="fu">indentArrays</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb26-20"><a href="#cb26-20" aria-hidden="true" tabindex="-1"></a>                <span class="kw">...</span></span>
<span id="cb26-21"><a href="#cb26-21" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb26-22"><a href="#cb26-22" aria-hidden="true" tabindex="-1"></a>            <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb26-23"><a href="#cb26-23" aria-hidden="true" tabindex="-1"></a>                <span class="kw">...</span></span>
<span id="cb26-24"><a href="#cb26-24" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb26-25"><a href="#cb26-25" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb26-26"><a href="#cb26-26" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb26-27"><a href="#cb26-27" aria-hidden="true" tabindex="-1"></a>            <span class="kw">...</span></span>
<span id="cb26-28"><a href="#cb26-28" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb26-29"><a href="#cb26-29" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb26-30"><a href="#cb26-30" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<pre><code>writeJson(out, json, Options.INDENT_EVERYTHING);
writeJson(out, json, new Options(true, false));
writeJson(out, json, new Options(false, true));
writeJson(out, json, Options.NO_INDENT);</code></pre>
<h2 id="option-12-take-an-opaque-config-object">Option 12. Take an opaque config object</h2>
<p>Maybe you want to give your api some extra wiggle room to grow. Maybe you just like how the usage of an opaque object made from a builder looks.</p>
<p>With this approach you can choose to internally represent things as booleans, enums, an enum set, bit flags, or whatever other evil lies within the hearts of mankind.</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> Options <span class="op">{</span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="dt">boolean</span> indentObjects<span class="op">;</span></span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="dt">boolean</span> indentArrays<span class="op">;</span></span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Options</span><span class="op">(</span>Builder builder<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">indentArrays</span> <span class="op">=</span> builder<span class="op">.</span><span class="fu">indentArrays</span><span class="op">;</span></span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">indentObjects</span> <span class="op">=</span> builder<span class="op">.</span><span class="fu">indentObjects</span><span class="op">;</span></span>
<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">boolean</span> <span class="fu">indentArrays</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb28-11"><a href="#cb28-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">indentArrays</span><span class="op">;</span></span>
<span id="cb28-12"><a href="#cb28-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-13"><a href="#cb28-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-14"><a href="#cb28-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">boolean</span> <span class="fu">indentObjects</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb28-15"><a href="#cb28-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">indentObjects</span><span class="op">;</span></span>
<span id="cb28-16"><a href="#cb28-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-17"><a href="#cb28-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-18"><a href="#cb28-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> Options <span class="fu">standard</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb28-19"><a href="#cb28-19" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fu">builder</span><span class="op">().</span><span class="fu">build</span><span class="op">();</span></span>
<span id="cb28-20"><a href="#cb28-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-21"><a href="#cb28-21" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb28-22"><a href="#cb28-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> Builder <span class="fu">builder</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb28-23"><a href="#cb28-23" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Builder</span><span class="op">();</span></span>
<span id="cb28-24"><a href="#cb28-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-25"><a href="#cb28-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-26"><a href="#cb28-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> Builder <span class="op">{</span></span>
<span id="cb28-27"><a href="#cb28-27" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">boolean</span> indentObjects<span class="op">;</span></span>
<span id="cb28-28"><a href="#cb28-28" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">boolean</span> indentArrays<span class="op">;</span></span>
<span id="cb28-29"><a href="#cb28-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-30"><a href="#cb28-30" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="fu">Builder</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb28-31"><a href="#cb28-31" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">indentObjects</span> <span class="op">=</span> <span class="kw">false</span><span class="op">;</span></span>
<span id="cb28-32"><a href="#cb28-32" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">indentArrays</span> <span class="op">=</span> <span class="kw">false</span><span class="op">;</span></span>
<span id="cb28-33"><a href="#cb28-33" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb28-34"><a href="#cb28-34" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb28-35"><a href="#cb28-35" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Builder <span class="fu">indentObjects</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb28-36"><a href="#cb28-36" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">indentObjects</span> <span class="op">=</span> <span class="kw">true</span><span class="op">;</span></span>
<span id="cb28-37"><a href="#cb28-37" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb28-38"><a href="#cb28-38" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb28-39"><a href="#cb28-39" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb28-40"><a href="#cb28-40" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Builder <span class="fu">indentArrays</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb28-41"><a href="#cb28-41" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">indentArrays</span> <span class="op">=</span> <span class="kw">true</span><span class="op">;</span></span>
<span id="cb28-42"><a href="#cb28-42" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb28-43"><a href="#cb28-43" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb28-44"><a href="#cb28-44" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb28-45"><a href="#cb28-45" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Options <span class="fu">build</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb28-46"><a href="#cb28-46" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Options</span><span class="op">(</span><span class="kw">this</span><span class="op">);</span></span>
<span id="cb28-47"><a href="#cb28-47" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb28-48"><a href="#cb28-48" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-49"><a href="#cb28-49" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb28-50"><a href="#cb28-50" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-51"><a href="#cb28-51" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb28-52"><a href="#cb28-52" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-53"><a href="#cb28-53" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> JsonWriter <span class="op">{</span></span>
<span id="cb28-54"><a href="#cb28-54" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">JsonWriter</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb28-55"><a href="#cb28-55" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-56"><a href="#cb28-56" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb28-57"><a href="#cb28-57" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb28-58"><a href="#cb28-58" aria-hidden="true" tabindex="-1"></a>            Json json<span class="op">,</span></span>
<span id="cb28-59"><a href="#cb28-59" aria-hidden="true" tabindex="-1"></a>            Options options</span>
<span id="cb28-60"><a href="#cb28-60" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-61"><a href="#cb28-61" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>options<span class="op">.</span><span class="fu">indentObjects</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb28-62"><a href="#cb28-62" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>options<span class="op">.</span><span class="fu">indentArrays</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb28-63"><a href="#cb28-63" aria-hidden="true" tabindex="-1"></a>                <span class="kw">...</span></span>
<span id="cb28-64"><a href="#cb28-64" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb28-65"><a href="#cb28-65" aria-hidden="true" tabindex="-1"></a>            <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb28-66"><a href="#cb28-66" aria-hidden="true" tabindex="-1"></a>                <span class="kw">...</span></span>
<span id="cb28-67"><a href="#cb28-67" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb28-68"><a href="#cb28-68" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb28-69"><a href="#cb28-69" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb28-70"><a href="#cb28-70" aria-hidden="true" tabindex="-1"></a>            <span class="kw">...</span></span>
<span id="cb28-71"><a href="#cb28-71" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb28-72"><a href="#cb28-72" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-73"><a href="#cb28-73" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<pre><code>writeJson(
    out, 
    json, 
    Options.builder()
        .indentObjects()
        .indentArrays()
        .build()
);
writeJson(
    out, 
    json, 
    Options.builder()
        .indentObjects()
        .build()
);
writeJson(
    out, 
    json, 
    Options.builder()
        .indentArrays()
        .build()
);
writeJson(out, json, Options.standard());</code></pre>
<hr />
<h1 id="hypothetical-3">Hypothetical 3.</h1>
<p>🚑 Weewoo Weewoo 🚑</p>
<p>Its legal! Your apis are great and all, but when you send data to external clients we would really like to include an explicit statement of copyright. That copyright message might change depending on your contract with the client and also we shouldn't send it internally.</p>
<p>Good luck, legal out.</p>
<h3 id="with-indentation-without-copyright">With Indentation, Without copyright</h3>
<div class="sourceCode" id="cb30"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="ot">[</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>    <span class="fu">{</span></span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a>        <span class="dt">&quot;name&quot;</span><span class="fu">:</span> <span class="st">&quot;joe&quot;</span><span class="fu">,</span></span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a>        <span class="dt">&quot;age&quot;</span><span class="fu">:</span> <span class="dv">35</span></span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a>    <span class="fu">}</span></span>
<span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a><span class="ot">]</span></span></code></pre></div>
<h3 id="with-indentation-with-copyright">With indentation, With copyright</h3>
<div class="sourceCode" id="cb31"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span> </span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">&quot;copyright&quot;</span><span class="fu">:</span> <span class="st">&quot;(c) 2022 Inc.&quot;</span><span class="fu">,</span></span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">&quot;data&quot;</span><span class="fu">:</span> <span class="ot">[</span></span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a>        <span class="fu">{</span></span>
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a>            <span class="dt">&quot;name&quot;</span><span class="fu">:</span><span class="st">&quot;joe&quot;</span><span class="fu">,</span></span>
<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a>            <span class="dt">&quot;age&quot;</span><span class="fu">:</span><span class="dv">35</span></span>
<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a>        <span class="fu">}</span></span>
<span id="cb31-8"><a href="#cb31-8" aria-hidden="true" tabindex="-1"></a>    <span class="ot">]</span></span>
<span id="cb31-9"><a href="#cb31-9" aria-hidden="true" tabindex="-1"></a><span class="fu">}</span></span></code></pre></div>
<h2 id="option-13-add-4-more-methods-to-hit-the-new-combinations">Option 13. Add 4 more methods to hit the new combinations</h2>
<div class="sourceCode" id="cb32"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> JsonWriter <span class="op">{</span></span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">JsonWriter</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a>            Json json</span>
<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb32-8"><a href="#cb32-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb32-9"><a href="#cb32-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb32-10"><a href="#cb32-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-11"><a href="#cb32-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJsonIndentObjects</span><span class="op">(</span></span>
<span id="cb32-12"><a href="#cb32-12" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb32-13"><a href="#cb32-13" aria-hidden="true" tabindex="-1"></a>            Json json</span>
<span id="cb32-14"><a href="#cb32-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb32-15"><a href="#cb32-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb32-16"><a href="#cb32-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb32-17"><a href="#cb32-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-18"><a href="#cb32-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJsonIndentArrays</span><span class="op">(</span></span>
<span id="cb32-19"><a href="#cb32-19" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb32-20"><a href="#cb32-20" aria-hidden="true" tabindex="-1"></a>            Json json</span>
<span id="cb32-21"><a href="#cb32-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb32-22"><a href="#cb32-22" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb32-23"><a href="#cb32-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb32-24"><a href="#cb32-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-25"><a href="#cb32-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJsonIndentEverything</span><span class="op">(</span></span>
<span id="cb32-26"><a href="#cb32-26" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb32-27"><a href="#cb32-27" aria-hidden="true" tabindex="-1"></a>            Json json</span>
<span id="cb32-28"><a href="#cb32-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb32-29"><a href="#cb32-29" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb32-30"><a href="#cb32-30" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb32-31"><a href="#cb32-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-32"><a href="#cb32-32" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJsonWithCopyright</span><span class="op">(</span></span>
<span id="cb32-33"><a href="#cb32-33" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb32-34"><a href="#cb32-34" aria-hidden="true" tabindex="-1"></a>            Json json<span class="op">,</span></span>
<span id="cb32-35"><a href="#cb32-35" aria-hidden="true" tabindex="-1"></a>            <span class="bu">String</span> copyright</span>
<span id="cb32-36"><a href="#cb32-36" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb32-37"><a href="#cb32-37" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb32-38"><a href="#cb32-38" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb32-39"><a href="#cb32-39" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-40"><a href="#cb32-40" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJsonIndentObjectsWithCopyright</span><span class="op">(</span></span>
<span id="cb32-41"><a href="#cb32-41" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb32-42"><a href="#cb32-42" aria-hidden="true" tabindex="-1"></a>            Json json<span class="op">,</span></span>
<span id="cb32-43"><a href="#cb32-43" aria-hidden="true" tabindex="-1"></a>            <span class="bu">String</span> copyright</span>
<span id="cb32-44"><a href="#cb32-44" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb32-45"><a href="#cb32-45" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb32-46"><a href="#cb32-46" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb32-47"><a href="#cb32-47" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-48"><a href="#cb32-48" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJsonIndentArraysWithCopyright</span><span class="op">(</span></span>
<span id="cb32-49"><a href="#cb32-49" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb32-50"><a href="#cb32-50" aria-hidden="true" tabindex="-1"></a>            Json json<span class="op">,</span></span>
<span id="cb32-51"><a href="#cb32-51" aria-hidden="true" tabindex="-1"></a>            <span class="bu">String</span> copyright</span>
<span id="cb32-52"><a href="#cb32-52" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb32-53"><a href="#cb32-53" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb32-54"><a href="#cb32-54" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb32-55"><a href="#cb32-55" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-56"><a href="#cb32-56" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJsonIndentEverythingWithCopyright</span><span class="op">(</span></span>
<span id="cb32-57"><a href="#cb32-57" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb32-58"><a href="#cb32-58" aria-hidden="true" tabindex="-1"></a>            Json json<span class="op">,</span></span>
<span id="cb32-59"><a href="#cb32-59" aria-hidden="true" tabindex="-1"></a>            <span class="bu">String</span> copyright</span>
<span id="cb32-60"><a href="#cb32-60" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb32-61"><a href="#cb32-61" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb32-62"><a href="#cb32-62" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb32-63"><a href="#cb32-63" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb33"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">);</span></span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJsonIndentObjects</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">);</span></span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJsonIndentArrays</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">);</span></span>
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJsonIndentEverything</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">);</span></span>
<span id="cb33-5"><a href="#cb33-5" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJsonWithCopyright</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> <span class="st">&quot;(c) 2022&quot;</span><span class="op">);</span></span>
<span id="cb33-6"><a href="#cb33-6" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJsonIndentObjectsWithCopyright</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> <span class="st">&quot;(c) 2022&quot;</span><span class="op">);</span></span>
<span id="cb33-7"><a href="#cb33-7" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJsonIndentArraysWithCopyright</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> <span class="st">&quot;(c) 2022&quot;</span><span class="op">);</span></span>
<span id="cb33-8"><a href="#cb33-8" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJsonIndentEverythingWithCopyright</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> <span class="st">&quot;(c) 2022&quot;</span><span class="op">);</span></span></code></pre></div>
<h2 id="options-14-add-a-single-new-method">Options 14. Add a single new method</h2>
<p>If your boolean-like options only took up a single overload, you can get away with just adding a single new method to the list.</p>
<p>This will look different depending on whether you used booleans, enums, an <code>EnumSet</code>, or bit flags.</p>
<div class="sourceCode" id="cb34"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">enum</span> Indent <span class="op">{</span></span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>    OBJECTS<span class="op">,</span></span>
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a>    ARRAYS</span>
<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb34-5"><a href="#cb34-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb34-6"><a href="#cb34-6" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb34-7"><a href="#cb34-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb34-8"><a href="#cb34-8" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> JsonWriter <span class="op">{</span></span>
<span id="cb34-9"><a href="#cb34-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">JsonWriter</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb34-10"><a href="#cb34-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb34-11"><a href="#cb34-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb34-12"><a href="#cb34-12" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb34-13"><a href="#cb34-13" aria-hidden="true" tabindex="-1"></a>            Json json<span class="op">,</span></span>
<span id="cb34-14"><a href="#cb34-14" aria-hidden="true" tabindex="-1"></a>            <span class="bu">EnumSet</span><span class="op">&lt;</span>Indent<span class="op">&gt;</span> indent</span>
<span id="cb34-15"><a href="#cb34-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb34-16"><a href="#cb34-16" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb34-17"><a href="#cb34-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb34-18"><a href="#cb34-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb34-19"><a href="#cb34-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb34-20"><a href="#cb34-20" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb34-21"><a href="#cb34-21" aria-hidden="true" tabindex="-1"></a>            Json json<span class="op">,</span></span>
<span id="cb34-22"><a href="#cb34-22" aria-hidden="true" tabindex="-1"></a>            <span class="bu">EnumSet</span><span class="op">&lt;</span>Indent<span class="op">&gt;</span> indent<span class="op">,</span></span>
<span id="cb34-23"><a href="#cb34-23" aria-hidden="true" tabindex="-1"></a>            <span class="bu">String</span> copyright</span>
<span id="cb34-24"><a href="#cb34-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb34-25"><a href="#cb34-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb34-26"><a href="#cb34-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb34-27"><a href="#cb34-27" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb35"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">OBJECTS</span><span class="op">,</span> Indent<span class="op">.</span><span class="fu">ARRAYS</span><span class="op">));</span></span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">OBJECTS</span><span class="op">));</span></span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">ARRAYS</span><span class="op">));</span></span>
<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">noneOf</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">class</span><span class="op">));</span></span>
<span id="cb35-5"><a href="#cb35-5" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb35-6"><a href="#cb35-6" aria-hidden="true" tabindex="-1"></a>    out<span class="op">,</span> </span>
<span id="cb35-7"><a href="#cb35-7" aria-hidden="true" tabindex="-1"></a>    json<span class="op">,</span> </span>
<span id="cb35-8"><a href="#cb35-8" aria-hidden="true" tabindex="-1"></a>    <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">OBJECTS</span><span class="op">,</span> Indent<span class="op">.</span><span class="fu">ARRAYS</span><span class="op">),</span></span>
<span id="cb35-9"><a href="#cb35-9" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;(c) 2022&quot;</span></span>
<span id="cb35-10"><a href="#cb35-10" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb35-11"><a href="#cb35-11" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb35-12"><a href="#cb35-12" aria-hidden="true" tabindex="-1"></a>    out<span class="op">,</span> </span>
<span id="cb35-13"><a href="#cb35-13" aria-hidden="true" tabindex="-1"></a>    json<span class="op">,</span> </span>
<span id="cb35-14"><a href="#cb35-14" aria-hidden="true" tabindex="-1"></a>    <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">OBJECTS</span><span class="op">),</span></span>
<span id="cb35-15"><a href="#cb35-15" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;(c) 2022&quot;</span></span>
<span id="cb35-16"><a href="#cb35-16" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb35-17"><a href="#cb35-17" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb35-18"><a href="#cb35-18" aria-hidden="true" tabindex="-1"></a>    out<span class="op">,</span> </span>
<span id="cb35-19"><a href="#cb35-19" aria-hidden="true" tabindex="-1"></a>    json<span class="op">,</span> </span>
<span id="cb35-20"><a href="#cb35-20" aria-hidden="true" tabindex="-1"></a>    <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">ARRAYS</span><span class="op">),</span></span>
<span id="cb35-21"><a href="#cb35-21" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;(c) 2022&quot;</span></span>
<span id="cb35-22"><a href="#cb35-22" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb35-23"><a href="#cb35-23" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb35-24"><a href="#cb35-24" aria-hidden="true" tabindex="-1"></a>    out<span class="op">,</span> </span>
<span id="cb35-25"><a href="#cb35-25" aria-hidden="true" tabindex="-1"></a>    json<span class="op">,</span> </span>
<span id="cb35-26"><a href="#cb35-26" aria-hidden="true" tabindex="-1"></a>    <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">noneOf</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">class</span><span class="op">),</span> </span>
<span id="cb35-27"><a href="#cb35-27" aria-hidden="true" tabindex="-1"></a>    <span class="st">&quot;(c) 2022&quot;</span></span>
<span id="cb35-28"><a href="#cb35-28" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span></code></pre></div>
<h2 id="option-15-add-another-argument-and-accept-null">Option 15. Add another argument and accept null</h2>
<p>If you don't want to add yet another overload, you can always just allow users to pass <code>null</code>.</p>
<div class="sourceCode" id="cb36"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">enum</span> Indent <span class="op">{</span></span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a>    OBJECTS<span class="op">,</span></span>
<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a>    ARRAYS</span>
<span id="cb36-4"><a href="#cb36-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb36-5"><a href="#cb36-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-6"><a href="#cb36-6" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb36-7"><a href="#cb36-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-8"><a href="#cb36-8" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> JsonWriter <span class="op">{</span></span>
<span id="cb36-9"><a href="#cb36-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">JsonWriter</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb36-10"><a href="#cb36-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-11"><a href="#cb36-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb36-12"><a href="#cb36-12" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb36-13"><a href="#cb36-13" aria-hidden="true" tabindex="-1"></a>            Json json<span class="op">,</span></span>
<span id="cb36-14"><a href="#cb36-14" aria-hidden="true" tabindex="-1"></a>            <span class="bu">EnumSet</span><span class="op">&lt;</span>Indent<span class="op">&gt;</span> indent<span class="op">,</span></span>
<span id="cb36-15"><a href="#cb36-15" aria-hidden="true" tabindex="-1"></a>            <span class="bu">String</span> copyright</span>
<span id="cb36-16"><a href="#cb36-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb36-17"><a href="#cb36-17" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>indent<span class="op">.</span><span class="fu">contains</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">OBJECTS</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb36-18"><a href="#cb36-18" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>indent<span class="op">.</span><span class="fu">contains</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">ARRAYS</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb36-19"><a href="#cb36-19" aria-hidden="true" tabindex="-1"></a>                <span class="cf">if</span> <span class="op">(</span>copyright <span class="op">==</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb36-20"><a href="#cb36-20" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">...</span></span>
<span id="cb36-21"><a href="#cb36-21" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb36-22"><a href="#cb36-22" aria-hidden="true" tabindex="-1"></a>                <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb36-23"><a href="#cb36-23" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">...</span> </span>
<span id="cb36-24"><a href="#cb36-24" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb36-25"><a href="#cb36-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-26"><a href="#cb36-26" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb36-27"><a href="#cb36-27" aria-hidden="true" tabindex="-1"></a>            <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb36-28"><a href="#cb36-28" aria-hidden="true" tabindex="-1"></a>                <span class="kw">...</span></span>
<span id="cb36-29"><a href="#cb36-29" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb36-30"><a href="#cb36-30" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb36-31"><a href="#cb36-31" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb36-32"><a href="#cb36-32" aria-hidden="true" tabindex="-1"></a>            <span class="kw">...</span></span>
<span id="cb36-33"><a href="#cb36-33" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb36-34"><a href="#cb36-34" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb36-35"><a href="#cb36-35" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb37"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">OBJECTS</span><span class="op">,</span> Indent<span class="op">.</span><span class="fu">ARRAYS</span><span class="op">),</span> <span class="kw">null</span><span class="op">);</span></span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">OBJECTS</span><span class="op">),</span> <span class="kw">null</span><span class="op">);</span></span>
<span id="cb37-3"><a href="#cb37-3" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">ARRAYS</span><span class="op">),</span> <span class="kw">null</span><span class="op">);</span></span>
<span id="cb37-4"><a href="#cb37-4" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">noneOf</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">class</span><span class="op">),</span> <span class="kw">null</span><span class="op">);</span></span>
<span id="cb37-5"><a href="#cb37-5" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb37-6"><a href="#cb37-6" aria-hidden="true" tabindex="-1"></a>        out<span class="op">,</span></span>
<span id="cb37-7"><a href="#cb37-7" aria-hidden="true" tabindex="-1"></a>        json<span class="op">,</span></span>
<span id="cb37-8"><a href="#cb37-8" aria-hidden="true" tabindex="-1"></a>        <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">OBJECTS</span><span class="op">,</span> Indent<span class="op">.</span><span class="fu">ARRAYS</span><span class="op">),</span> </span>
<span id="cb37-9"><a href="#cb37-9" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;(c) 2022&quot;</span></span>
<span id="cb37-10"><a href="#cb37-10" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb37-11"><a href="#cb37-11" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">OBJECTS</span><span class="op">),</span> <span class="st">&quot;(c) 2022&quot;</span><span class="op">);</span></span>
<span id="cb37-12"><a href="#cb37-12" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">ARRAYS</span><span class="op">),</span> <span class="st">&quot;(c) 2022&quot;</span><span class="op">);</span></span>
<span id="cb37-13"><a href="#cb37-13" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">noneOf</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">class</span><span class="op">),</span> <span class="st">&quot;(c) 2022&quot;</span><span class="op">);</span></span></code></pre></div>
<h2 id="option-16-add-another-argument-and-make-it-be-an-optional">Option 16. Add another argument and make it be an <code>Optional</code></h2>
<p>It's time to paint a bike shed. You can do this with <code>java.util.Optional</code> or your own sealed type.</p>
<div class="sourceCode" id="cb38"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">enum</span> Indent <span class="op">{</span></span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a>    OBJECTS<span class="op">,</span></span>
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a>    ARRAYS</span>
<span id="cb38-4"><a href="#cb38-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb38-5"><a href="#cb38-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-6"><a href="#cb38-6" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb38-7"><a href="#cb38-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-8"><a href="#cb38-8" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> JsonWriter <span class="op">{</span></span>
<span id="cb38-9"><a href="#cb38-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">JsonWriter</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb38-10"><a href="#cb38-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-11"><a href="#cb38-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb38-12"><a href="#cb38-12" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb38-13"><a href="#cb38-13" aria-hidden="true" tabindex="-1"></a>            Json json<span class="op">,</span></span>
<span id="cb38-14"><a href="#cb38-14" aria-hidden="true" tabindex="-1"></a>            <span class="bu">EnumSet</span><span class="op">&lt;</span>Indent<span class="op">&gt;</span> indent<span class="op">,</span></span>
<span id="cb38-15"><a href="#cb38-15" aria-hidden="true" tabindex="-1"></a>            Optional<span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> copyright</span>
<span id="cb38-16"><a href="#cb38-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb38-17"><a href="#cb38-17" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>indent<span class="op">.</span><span class="fu">contains</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">OBJECTS</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb38-18"><a href="#cb38-18" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>indent<span class="op">.</span><span class="fu">contains</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">ARRAYS</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb38-19"><a href="#cb38-19" aria-hidden="true" tabindex="-1"></a>                <span class="cf">if</span> <span class="op">(</span>copyright<span class="op">.</span><span class="fu">isPresent</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb38-20"><a href="#cb38-20" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">...</span> copyright<span class="op">.</span><span class="fu">orElseThrow</span><span class="op">()</span> <span class="kw">...</span></span>
<span id="cb38-21"><a href="#cb38-21" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb38-22"><a href="#cb38-22" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">...</span></span>
<span id="cb38-23"><a href="#cb38-23" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb38-24"><a href="#cb38-24" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb38-25"><a href="#cb38-25" aria-hidden="true" tabindex="-1"></a>                <span class="kw">...</span></span>
<span id="cb38-26"><a href="#cb38-26" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb38-27"><a href="#cb38-27" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb38-28"><a href="#cb38-28" aria-hidden="true" tabindex="-1"></a>            <span class="kw">...</span></span>
<span id="cb38-29"><a href="#cb38-29" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb38-30"><a href="#cb38-30" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb38-31"><a href="#cb38-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb39"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a>    out<span class="op">,</span> </span>
<span id="cb39-3"><a href="#cb39-3" aria-hidden="true" tabindex="-1"></a>    json<span class="op">,</span> </span>
<span id="cb39-4"><a href="#cb39-4" aria-hidden="true" tabindex="-1"></a>    <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">OBJECTS</span><span class="op">,</span> Indent<span class="op">.</span><span class="fu">ARRAYS</span><span class="op">),</span> </span>
<span id="cb39-5"><a href="#cb39-5" aria-hidden="true" tabindex="-1"></a>    Optional<span class="op">.</span><span class="fu">empty</span><span class="op">()</span></span>
<span id="cb39-6"><a href="#cb39-6" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb39-7"><a href="#cb39-7" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb39-8"><a href="#cb39-8" aria-hidden="true" tabindex="-1"></a>    out<span class="op">,</span></span>
<span id="cb39-9"><a href="#cb39-9" aria-hidden="true" tabindex="-1"></a>    json<span class="op">,</span> </span>
<span id="cb39-10"><a href="#cb39-10" aria-hidden="true" tabindex="-1"></a>    <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">OBJECTS</span><span class="op">),</span></span>
<span id="cb39-11"><a href="#cb39-11" aria-hidden="true" tabindex="-1"></a>    Optional<span class="op">.</span><span class="fu">empty</span><span class="op">()</span></span>
<span id="cb39-12"><a href="#cb39-12" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb39-13"><a href="#cb39-13" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb39-14"><a href="#cb39-14" aria-hidden="true" tabindex="-1"></a>    out<span class="op">,</span> </span>
<span id="cb39-15"><a href="#cb39-15" aria-hidden="true" tabindex="-1"></a>    json<span class="op">,</span> </span>
<span id="cb39-16"><a href="#cb39-16" aria-hidden="true" tabindex="-1"></a>    <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">ARRAYS</span><span class="op">),</span></span>
<span id="cb39-17"><a href="#cb39-17" aria-hidden="true" tabindex="-1"></a>    Optional<span class="op">.</span><span class="fu">empty</span><span class="op">()</span></span>
<span id="cb39-18"><a href="#cb39-18" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb39-19"><a href="#cb39-19" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb39-20"><a href="#cb39-20" aria-hidden="true" tabindex="-1"></a>    out<span class="op">,</span> </span>
<span id="cb39-21"><a href="#cb39-21" aria-hidden="true" tabindex="-1"></a>    json<span class="op">,</span> </span>
<span id="cb39-22"><a href="#cb39-22" aria-hidden="true" tabindex="-1"></a>    <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">noneOf</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">class</span><span class="op">),</span> </span>
<span id="cb39-23"><a href="#cb39-23" aria-hidden="true" tabindex="-1"></a>    Optional<span class="op">.</span><span class="fu">empty</span><span class="op">()</span></span>
<span id="cb39-24"><a href="#cb39-24" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb39-25"><a href="#cb39-25" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb39-26"><a href="#cb39-26" aria-hidden="true" tabindex="-1"></a>    out<span class="op">,</span> </span>
<span id="cb39-27"><a href="#cb39-27" aria-hidden="true" tabindex="-1"></a>    json<span class="op">,</span> </span>
<span id="cb39-28"><a href="#cb39-28" aria-hidden="true" tabindex="-1"></a>    <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">OBJECTS</span><span class="op">,</span> Indent<span class="op">.</span><span class="fu">ARRAYS</span><span class="op">),</span> </span>
<span id="cb39-29"><a href="#cb39-29" aria-hidden="true" tabindex="-1"></a>    Optional<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;(c) 2022&quot;</span><span class="op">)</span></span>
<span id="cb39-30"><a href="#cb39-30" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb39-31"><a href="#cb39-31" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb39-32"><a href="#cb39-32" aria-hidden="true" tabindex="-1"></a>    out<span class="op">,</span> </span>
<span id="cb39-33"><a href="#cb39-33" aria-hidden="true" tabindex="-1"></a>    json<span class="op">,</span> </span>
<span id="cb39-34"><a href="#cb39-34" aria-hidden="true" tabindex="-1"></a>    <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">OBJECTS</span><span class="op">),</span> </span>
<span id="cb39-35"><a href="#cb39-35" aria-hidden="true" tabindex="-1"></a>    Optional<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;(c) 2022&quot;</span><span class="op">)</span></span>
<span id="cb39-36"><a href="#cb39-36" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb39-37"><a href="#cb39-37" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb39-38"><a href="#cb39-38" aria-hidden="true" tabindex="-1"></a>    out<span class="op">,</span> </span>
<span id="cb39-39"><a href="#cb39-39" aria-hidden="true" tabindex="-1"></a>    json<span class="op">,</span> </span>
<span id="cb39-40"><a href="#cb39-40" aria-hidden="true" tabindex="-1"></a>    <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">ARRAYS</span><span class="op">),</span> </span>
<span id="cb39-41"><a href="#cb39-41" aria-hidden="true" tabindex="-1"></a>    Optional<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;(c) 2022&quot;</span><span class="op">)</span></span>
<span id="cb39-42"><a href="#cb39-42" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb39-43"><a href="#cb39-43" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb39-44"><a href="#cb39-44" aria-hidden="true" tabindex="-1"></a>    out<span class="op">,</span> </span>
<span id="cb39-45"><a href="#cb39-45" aria-hidden="true" tabindex="-1"></a>    json<span class="op">,</span> </span>
<span id="cb39-46"><a href="#cb39-46" aria-hidden="true" tabindex="-1"></a>    <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">noneOf</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">class</span><span class="op">),</span> </span>
<span id="cb39-47"><a href="#cb39-47" aria-hidden="true" tabindex="-1"></a>    Optional<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;(c) 2022&quot;</span><span class="op">)</span></span>
<span id="cb39-48"><a href="#cb39-48" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span></code></pre></div>
<h2 id="option-17-add-a-nullable-property-to-a-transparent-config-object">Option 17. Add a nullable property to a transparent config object</h2>
<div class="sourceCode" id="cb40"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Options</span><span class="op">(</span></span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a>        <span class="dt">boolean</span> indentObjects<span class="op">,</span> </span>
<span id="cb40-3"><a href="#cb40-3" aria-hidden="true" tabindex="-1"></a>        <span class="dt">boolean</span> indentArrays<span class="op">,</span></span>
<span id="cb40-4"><a href="#cb40-4" aria-hidden="true" tabindex="-1"></a>        <span class="bu">String</span> copyright<span class="op">)</span> <span class="op">{</span></span>
<span id="cb40-5"><a href="#cb40-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">final</span> Options INDENT_EVERYTHING <span class="op">=</span></span>
<span id="cb40-6"><a href="#cb40-6" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="fu">Options</span><span class="op">(</span><span class="kw">true</span><span class="op">,</span> <span class="kw">true</span><span class="op">,</span> <span class="kw">null</span><span class="op">);</span></span>
<span id="cb40-7"><a href="#cb40-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">final</span> Options NO_INDENT <span class="op">=</span></span>
<span id="cb40-8"><a href="#cb40-8" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="fu">Options</span><span class="op">(</span><span class="kw">false</span><span class="op">,</span> <span class="kw">false</span><span class="op">,</span> <span class="kw">null</span><span class="op">);</span></span>
<span id="cb40-9"><a href="#cb40-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb40-10"><a href="#cb40-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-11"><a href="#cb40-11" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb40-12"><a href="#cb40-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-13"><a href="#cb40-13" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> JsonWriter <span class="op">{</span></span>
<span id="cb40-14"><a href="#cb40-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">JsonWriter</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb40-15"><a href="#cb40-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-16"><a href="#cb40-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb40-17"><a href="#cb40-17" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb40-18"><a href="#cb40-18" aria-hidden="true" tabindex="-1"></a>            Json json<span class="op">,</span></span>
<span id="cb40-19"><a href="#cb40-19" aria-hidden="true" tabindex="-1"></a>            Options options</span>
<span id="cb40-20"><a href="#cb40-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb40-21"><a href="#cb40-21" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>options<span class="op">.</span><span class="fu">indentObjects</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb40-22"><a href="#cb40-22" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>options<span class="op">.</span><span class="fu">indentArrays</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb40-23"><a href="#cb40-23" aria-hidden="true" tabindex="-1"></a>                <span class="cf">if</span> <span class="op">(</span>options<span class="op">.</span><span class="fu">copyright</span><span class="op">()</span> <span class="op">==</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb40-24"><a href="#cb40-24" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">...</span></span>
<span id="cb40-25"><a href="#cb40-25" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb40-26"><a href="#cb40-26" aria-hidden="true" tabindex="-1"></a>                <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb40-27"><a href="#cb40-27" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">...</span>   </span>
<span id="cb40-28"><a href="#cb40-28" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb40-29"><a href="#cb40-29" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb40-30"><a href="#cb40-30" aria-hidden="true" tabindex="-1"></a>            <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb40-31"><a href="#cb40-31" aria-hidden="true" tabindex="-1"></a>                <span class="kw">...</span> </span>
<span id="cb40-32"><a href="#cb40-32" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb40-33"><a href="#cb40-33" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb40-34"><a href="#cb40-34" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span> </span>
<span id="cb40-35"><a href="#cb40-35" aria-hidden="true" tabindex="-1"></a>            <span class="kw">...</span> </span>
<span id="cb40-36"><a href="#cb40-36" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb40-37"><a href="#cb40-37" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb40-38"><a href="#cb40-38" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="option-18-add-an-optional-property-to-a-transparent-config-object">Option 18. Add an <code>Optional</code> property to a transparent config object</h2>
<p>Same as above, but if you like to explicitly have the property be optional you can, but if you are using records as your transparent data carriers then you need to take an <code>Optional</code> in your constructor.</p>
<div class="sourceCode" id="cb41"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Options</span><span class="op">(</span></span>
<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a>        <span class="dt">boolean</span> indentObjects<span class="op">,</span></span>
<span id="cb41-3"><a href="#cb41-3" aria-hidden="true" tabindex="-1"></a>        <span class="dt">boolean</span> indentArrays<span class="op">,</span></span>
<span id="cb41-4"><a href="#cb41-4" aria-hidden="true" tabindex="-1"></a>        Optional<span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> copyright</span>
<span id="cb41-5"><a href="#cb41-5" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb41-6"><a href="#cb41-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">final</span> Options INDENT_EVERYTHING <span class="op">=</span></span>
<span id="cb41-7"><a href="#cb41-7" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="fu">Options</span><span class="op">(</span><span class="kw">true</span><span class="op">,</span> <span class="kw">true</span><span class="op">,</span> Optional<span class="op">.</span><span class="fu">empty</span><span class="op">());</span></span>
<span id="cb41-8"><a href="#cb41-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">final</span> Options NO_INDENT <span class="op">=</span></span>
<span id="cb41-9"><a href="#cb41-9" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="fu">Options</span><span class="op">(</span><span class="kw">false</span><span class="op">,</span> <span class="kw">false</span><span class="op">,</span> Optional<span class="op">.</span><span class="fu">empty</span><span class="op">());</span></span>
<span id="cb41-10"><a href="#cb41-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="option-19-add-another-property-to-an-opaque-config-object">Option 19. Add another property to an opaque config object</h2>
<div class="sourceCode" id="cb42"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb42-1"><a href="#cb42-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> Options <span class="op">{</span></span>
<span id="cb42-2"><a href="#cb42-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="dt">boolean</span> indentObjects<span class="op">;</span></span>
<span id="cb42-3"><a href="#cb42-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="dt">boolean</span> indentArrays<span class="op">;</span></span>
<span id="cb42-4"><a href="#cb42-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="bu">String</span> copyright<span class="op">;</span></span>
<span id="cb42-5"><a href="#cb42-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-6"><a href="#cb42-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Options</span><span class="op">(</span>Builder builder<span class="op">)</span> <span class="op">{</span></span>
<span id="cb42-7"><a href="#cb42-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">indentArrays</span> <span class="op">=</span> builder<span class="op">.</span><span class="fu">indentArrays</span><span class="op">;</span></span>
<span id="cb42-8"><a href="#cb42-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">indentObjects</span> <span class="op">=</span> builder<span class="op">.</span><span class="fu">indentObjects</span><span class="op">;</span></span>
<span id="cb42-9"><a href="#cb42-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">copyright</span> <span class="op">=</span> builder<span class="op">.</span><span class="fu">copyright</span><span class="op">;</span></span>
<span id="cb42-10"><a href="#cb42-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb42-11"><a href="#cb42-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-12"><a href="#cb42-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">boolean</span> <span class="fu">indentArrays</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb42-13"><a href="#cb42-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">indentArrays</span><span class="op">;</span></span>
<span id="cb42-14"><a href="#cb42-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb42-15"><a href="#cb42-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-16"><a href="#cb42-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">boolean</span> <span class="fu">indentObjects</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb42-17"><a href="#cb42-17" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">indentObjects</span><span class="op">;</span></span>
<span id="cb42-18"><a href="#cb42-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb42-19"><a href="#cb42-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-20"><a href="#cb42-20" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> Optional<span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> <span class="fu">copyright</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb42-21"><a href="#cb42-21" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> Optional<span class="op">.</span><span class="fu">ofNullable</span><span class="op">(</span><span class="kw">this</span><span class="op">.</span><span class="fu">copyright</span><span class="op">);</span></span>
<span id="cb42-22"><a href="#cb42-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb42-23"><a href="#cb42-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-24"><a href="#cb42-24" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> Options <span class="fu">standard</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb42-25"><a href="#cb42-25" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fu">builder</span><span class="op">().</span><span class="fu">build</span><span class="op">();</span></span>
<span id="cb42-26"><a href="#cb42-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb42-27"><a href="#cb42-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-28"><a href="#cb42-28" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> Builder <span class="fu">builder</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb42-29"><a href="#cb42-29" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Builder</span><span class="op">();</span></span>
<span id="cb42-30"><a href="#cb42-30" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb42-31"><a href="#cb42-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-32"><a href="#cb42-32" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> Builder <span class="op">{</span></span>
<span id="cb42-33"><a href="#cb42-33" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">boolean</span> indentObjects<span class="op">;</span></span>
<span id="cb42-34"><a href="#cb42-34" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">boolean</span> indentArrays<span class="op">;</span></span>
<span id="cb42-35"><a href="#cb42-35" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="bu">String</span> copyright<span class="op">;</span></span>
<span id="cb42-36"><a href="#cb42-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-37"><a href="#cb42-37" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="fu">Builder</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb42-38"><a href="#cb42-38" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">indentObjects</span> <span class="op">=</span> <span class="kw">false</span><span class="op">;</span></span>
<span id="cb42-39"><a href="#cb42-39" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">indentArrays</span> <span class="op">=</span> <span class="kw">false</span><span class="op">;</span></span>
<span id="cb42-40"><a href="#cb42-40" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">copyright</span> <span class="op">=</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb42-41"><a href="#cb42-41" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb42-42"><a href="#cb42-42" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-43"><a href="#cb42-43" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Builder <span class="fu">indentObjects</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb42-44"><a href="#cb42-44" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">indentObjects</span> <span class="op">=</span> <span class="kw">true</span><span class="op">;</span></span>
<span id="cb42-45"><a href="#cb42-45" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb42-46"><a href="#cb42-46" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb42-47"><a href="#cb42-47" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-48"><a href="#cb42-48" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Builder <span class="fu">indentArrays</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb42-49"><a href="#cb42-49" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">indentArrays</span> <span class="op">=</span> <span class="kw">true</span><span class="op">;</span></span>
<span id="cb42-50"><a href="#cb42-50" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb42-51"><a href="#cb42-51" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb42-52"><a href="#cb42-52" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-53"><a href="#cb42-53" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Builder <span class="fu">copyright</span><span class="op">(</span><span class="bu">String</span> copyright<span class="op">)</span> <span class="op">{</span></span>
<span id="cb42-54"><a href="#cb42-54" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">copyright</span> <span class="op">=</span> copyright<span class="op">;</span></span>
<span id="cb42-55"><a href="#cb42-55" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb42-56"><a href="#cb42-56" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb42-57"><a href="#cb42-57" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb42-58"><a href="#cb42-58" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Options <span class="fu">build</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb42-59"><a href="#cb42-59" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Options</span><span class="op">(</span><span class="kw">this</span><span class="op">);</span></span>
<span id="cb42-60"><a href="#cb42-60" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb42-61"><a href="#cb42-61" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb42-62"><a href="#cb42-62" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb43"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb43-1"><a href="#cb43-1" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb43-2"><a href="#cb43-2" aria-hidden="true" tabindex="-1"></a>    out<span class="op">,</span> </span>
<span id="cb43-3"><a href="#cb43-3" aria-hidden="true" tabindex="-1"></a>    json<span class="op">,</span> </span>
<span id="cb43-4"><a href="#cb43-4" aria-hidden="true" tabindex="-1"></a>    Options<span class="op">.</span><span class="fu">builder</span><span class="op">()</span></span>
<span id="cb43-5"><a href="#cb43-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">indentObjects</span><span class="op">()</span></span>
<span id="cb43-6"><a href="#cb43-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">indentArrays</span><span class="op">()</span></span>
<span id="cb43-7"><a href="#cb43-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">build</span><span class="op">()</span></span>
<span id="cb43-8"><a href="#cb43-8" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb43-9"><a href="#cb43-9" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb43-10"><a href="#cb43-10" aria-hidden="true" tabindex="-1"></a>    out<span class="op">,</span> </span>
<span id="cb43-11"><a href="#cb43-11" aria-hidden="true" tabindex="-1"></a>    json<span class="op">,</span> </span>
<span id="cb43-12"><a href="#cb43-12" aria-hidden="true" tabindex="-1"></a>    Options<span class="op">.</span><span class="fu">builder</span><span class="op">()</span></span>
<span id="cb43-13"><a href="#cb43-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">indentObjects</span><span class="op">()</span></span>
<span id="cb43-14"><a href="#cb43-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">build</span><span class="op">()</span></span>
<span id="cb43-15"><a href="#cb43-15" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb43-16"><a href="#cb43-16" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb43-17"><a href="#cb43-17" aria-hidden="true" tabindex="-1"></a>    out<span class="op">,</span> </span>
<span id="cb43-18"><a href="#cb43-18" aria-hidden="true" tabindex="-1"></a>    json<span class="op">,</span> </span>
<span id="cb43-19"><a href="#cb43-19" aria-hidden="true" tabindex="-1"></a>    Options<span class="op">.</span><span class="fu">builder</span><span class="op">()</span></span>
<span id="cb43-20"><a href="#cb43-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">indentArrays</span><span class="op">()</span></span>
<span id="cb43-21"><a href="#cb43-21" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">build</span><span class="op">()</span></span>
<span id="cb43-22"><a href="#cb43-22" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb43-23"><a href="#cb43-23" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span>out<span class="op">,</span> json<span class="op">,</span> Options<span class="op">.</span><span class="fu">standard</span><span class="op">());</span></span>
<span id="cb43-24"><a href="#cb43-24" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb43-25"><a href="#cb43-25" aria-hidden="true" tabindex="-1"></a>    out<span class="op">,</span> </span>
<span id="cb43-26"><a href="#cb43-26" aria-hidden="true" tabindex="-1"></a>    json<span class="op">,</span> </span>
<span id="cb43-27"><a href="#cb43-27" aria-hidden="true" tabindex="-1"></a>    Options<span class="op">.</span><span class="fu">builder</span><span class="op">()</span></span>
<span id="cb43-28"><a href="#cb43-28" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">indentObjects</span><span class="op">()</span></span>
<span id="cb43-29"><a href="#cb43-29" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">indentArrays</span><span class="op">()</span></span>
<span id="cb43-30"><a href="#cb43-30" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">copyright</span><span class="op">(</span><span class="st">&quot;(c) 2022&quot;</span><span class="op">)</span></span>
<span id="cb43-31"><a href="#cb43-31" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">build</span><span class="op">()</span></span>
<span id="cb43-32"><a href="#cb43-32" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb43-33"><a href="#cb43-33" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb43-34"><a href="#cb43-34" aria-hidden="true" tabindex="-1"></a>    out<span class="op">,</span> </span>
<span id="cb43-35"><a href="#cb43-35" aria-hidden="true" tabindex="-1"></a>    json<span class="op">,</span> </span>
<span id="cb43-36"><a href="#cb43-36" aria-hidden="true" tabindex="-1"></a>    Options<span class="op">.</span><span class="fu">builder</span><span class="op">()</span></span>
<span id="cb43-37"><a href="#cb43-37" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">indentObjects</span><span class="op">()</span></span>
<span id="cb43-38"><a href="#cb43-38" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">copyright</span><span class="op">(</span><span class="st">&quot;(c) 2022&quot;</span><span class="op">)</span></span>
<span id="cb43-39"><a href="#cb43-39" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">build</span><span class="op">()</span></span>
<span id="cb43-40"><a href="#cb43-40" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb43-41"><a href="#cb43-41" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb43-42"><a href="#cb43-42" aria-hidden="true" tabindex="-1"></a>    out<span class="op">,</span> </span>
<span id="cb43-43"><a href="#cb43-43" aria-hidden="true" tabindex="-1"></a>    json<span class="op">,</span> </span>
<span id="cb43-44"><a href="#cb43-44" aria-hidden="true" tabindex="-1"></a>    Options<span class="op">.</span><span class="fu">builder</span><span class="op">()</span></span>
<span id="cb43-45"><a href="#cb43-45" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">indentArrays</span><span class="op">()</span></span>
<span id="cb43-46"><a href="#cb43-46" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">copyright</span><span class="op">(</span><span class="st">&quot;(c) 2022&quot;</span><span class="op">)</span></span>
<span id="cb43-47"><a href="#cb43-47" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">build</span><span class="op">()</span></span>
<span id="cb43-48"><a href="#cb43-48" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb43-49"><a href="#cb43-49" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb43-50"><a href="#cb43-50" aria-hidden="true" tabindex="-1"></a>    out<span class="op">,</span> </span>
<span id="cb43-51"><a href="#cb43-51" aria-hidden="true" tabindex="-1"></a>    json<span class="op">,</span> </span>
<span id="cb43-52"><a href="#cb43-52" aria-hidden="true" tabindex="-1"></a>    Options<span class="op">.</span><span class="fu">builder</span><span class="op">()</span></span>
<span id="cb43-53"><a href="#cb43-53" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">copyright</span><span class="op">(</span><span class="st">&quot;(c) 2022&quot;</span><span class="op">)</span></span>
<span id="cb43-54"><a href="#cb43-54" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">build</span><span class="op">()</span></span>
<span id="cb43-55"><a href="#cb43-55" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span></code></pre></div>
<hr />
<h1 id="hypothetical-4">Hypothetical 4.</h1>
<p>It would be a lot more efficient if you started sending your JSON in a binary format like MessagePack. It has the same data model as JSON, so it should work out.</p>
<p>Also, when sending in that binary format there is a choice between "Little Endian" and "Big Endian".</p>
<p>Problem is, there really isn't a meaning to indentation in a binary format or to endianness in a text one.</p>
<h2 id="option-20-make-separate-methods">Option 20. Make separate methods</h2>
<p>For a split as fundamental as this, it might make sense to start to make an entirely separate API for the new JSON-like format.</p>
<div class="sourceCode" id="cb44"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb44-1"><a href="#cb44-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">enum</span> Indent <span class="op">{</span></span>
<span id="cb44-2"><a href="#cb44-2" aria-hidden="true" tabindex="-1"></a>    OBJECTS<span class="op">,</span></span>
<span id="cb44-3"><a href="#cb44-3" aria-hidden="true" tabindex="-1"></a>    ARRAYS</span>
<span id="cb44-4"><a href="#cb44-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb44-5"><a href="#cb44-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb44-6"><a href="#cb44-6" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb44-7"><a href="#cb44-7" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb44-8"><a href="#cb44-8" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> Endianness <span class="op">{</span></span>
<span id="cb44-9"><a href="#cb44-9" aria-hidden="true" tabindex="-1"></a>    BIG_ENDIAN<span class="op">,</span></span>
<span id="cb44-10"><a href="#cb44-10" aria-hidden="true" tabindex="-1"></a>    LITTLE_ENDIAN</span>
<span id="cb44-11"><a href="#cb44-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb44-12"><a href="#cb44-12" aria-hidden="true" tabindex="-1"></a>  </span>
<span id="cb44-13"><a href="#cb44-13" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb44-14"><a href="#cb44-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb44-15"><a href="#cb44-15" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> JsonWriter <span class="op">{</span></span>
<span id="cb44-16"><a href="#cb44-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">JsonWriter</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb44-17"><a href="#cb44-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb44-18"><a href="#cb44-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb44-19"><a href="#cb44-19" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb44-20"><a href="#cb44-20" aria-hidden="true" tabindex="-1"></a>            Json json<span class="op">,</span></span>
<span id="cb44-21"><a href="#cb44-21" aria-hidden="true" tabindex="-1"></a>            <span class="bu">EnumSet</span><span class="op">&lt;</span>Indent<span class="op">&gt;</span> indent<span class="op">,</span></span>
<span id="cb44-22"><a href="#cb44-22" aria-hidden="true" tabindex="-1"></a>            Optional<span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> copyright</span>
<span id="cb44-23"><a href="#cb44-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb44-24"><a href="#cb44-24" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb44-25"><a href="#cb44-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb44-26"><a href="#cb44-26" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb44-27"><a href="#cb44-27" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeMessagePack</span><span class="op">(</span></span>
<span id="cb44-28"><a href="#cb44-28" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb44-29"><a href="#cb44-29" aria-hidden="true" tabindex="-1"></a>            Json json<span class="op">,</span></span>
<span id="cb44-30"><a href="#cb44-30" aria-hidden="true" tabindex="-1"></a>            Endianness endianness<span class="op">,</span></span>
<span id="cb44-31"><a href="#cb44-31" aria-hidden="true" tabindex="-1"></a>            Optional<span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> copyright</span>
<span id="cb44-32"><a href="#cb44-32" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb44-33"><a href="#cb44-33" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb44-34"><a href="#cb44-34" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb44-35"><a href="#cb44-35" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb45"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb45-1"><a href="#cb45-1" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb45-2"><a href="#cb45-2" aria-hidden="true" tabindex="-1"></a>        out<span class="op">,</span> </span>
<span id="cb45-3"><a href="#cb45-3" aria-hidden="true" tabindex="-1"></a>        json<span class="op">,</span></span>
<span id="cb45-4"><a href="#cb45-4" aria-hidden="true" tabindex="-1"></a>        <span class="bu">EnumSet</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>Indent<span class="op">.</span><span class="fu">OBJECTS</span><span class="op">),</span></span>
<span id="cb45-5"><a href="#cb45-5" aria-hidden="true" tabindex="-1"></a>        Optional<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;(c) 2022&quot;</span><span class="op">)</span></span>
<span id="cb45-6"><a href="#cb45-6" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb45-7"><a href="#cb45-7" aria-hidden="true" tabindex="-1"></a><span class="fu">writeMessagePack</span><span class="op">(</span></span>
<span id="cb45-8"><a href="#cb45-8" aria-hidden="true" tabindex="-1"></a>        out<span class="op">,</span></span>
<span id="cb45-9"><a href="#cb45-9" aria-hidden="true" tabindex="-1"></a>        json<span class="op">,</span></span>
<span id="cb45-10"><a href="#cb45-10" aria-hidden="true" tabindex="-1"></a>        Endianness<span class="op">.</span><span class="fu">BIG_ENDIAN</span><span class="op">,</span></span>
<span id="cb45-11"><a href="#cb45-11" aria-hidden="true" tabindex="-1"></a>        Optional<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;(c) 2022&quot;</span><span class="op">)</span></span>
<span id="cb45-12"><a href="#cb45-12" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span></code></pre></div>
<h2 id="option-21-make-an-interface-and-use-dispatch">Option 21. Make an interface and use dispatch</h2>
<p>You were surprised you didn't think of this first. Dynamic dispatch is some classic Java stylings.</p>
<div class="sourceCode" id="cb46"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb46-1"><a href="#cb46-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">interface</span> JsonWriter <span class="op">{</span></span>
<span id="cb46-2"><a href="#cb46-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">write</span><span class="op">(</span><span class="bu">Appendable</span> out<span class="op">,</span> JSON json<span class="op">);</span></span>
<span id="cb46-3"><a href="#cb46-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb46-4"><a href="#cb46-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-5"><a href="#cb46-5" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb46-6"><a href="#cb46-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-7"><a href="#cb46-7" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> TextJsonWriter <span class="kw">implements</span> JsonWriter <span class="op">{</span></span>
<span id="cb46-8"><a href="#cb46-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="dt">boolean</span> indentObjects<span class="op">;</span></span>
<span id="cb46-9"><a href="#cb46-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="dt">boolean</span> indentArrays<span class="op">;</span></span>
<span id="cb46-10"><a href="#cb46-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="bu">String</span> copyright<span class="op">;</span></span>
<span id="cb46-11"><a href="#cb46-11" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb46-12"><a href="#cb46-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">TextJsonWriter</span><span class="op">(</span></span>
<span id="cb46-13"><a href="#cb46-13" aria-hidden="true" tabindex="-1"></a>            <span class="dt">boolean</span> indentObjects<span class="op">,</span> </span>
<span id="cb46-14"><a href="#cb46-14" aria-hidden="true" tabindex="-1"></a>            <span class="dt">boolean</span> indentArrays<span class="op">,</span></span>
<span id="cb46-15"><a href="#cb46-15" aria-hidden="true" tabindex="-1"></a>            <span class="bu">String</span> copyright</span>
<span id="cb46-16"><a href="#cb46-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{}</span></span>
<span id="cb46-17"><a href="#cb46-17" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb46-18"><a href="#cb46-18" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb46-19"><a href="#cb46-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">write</span><span class="op">(</span><span class="bu">Appendable</span> out<span class="op">,</span> JSON json<span class="op">)</span> <span class="op">{</span></span>
<span id="cb46-20"><a href="#cb46-20" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb46-21"><a href="#cb46-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb46-22"><a href="#cb46-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb46-23"><a href="#cb46-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-24"><a href="#cb46-24" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb46-25"><a href="#cb46-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-26"><a href="#cb46-26" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> Endianness <span class="op">{</span></span>
<span id="cb46-27"><a href="#cb46-27" aria-hidden="true" tabindex="-1"></a>    BIG_ENDIAN<span class="op">,</span></span>
<span id="cb46-28"><a href="#cb46-28" aria-hidden="true" tabindex="-1"></a>    LITTLE_ENDIAN</span>
<span id="cb46-29"><a href="#cb46-29" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb46-30"><a href="#cb46-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-31"><a href="#cb46-31" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb46-32"><a href="#cb46-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-33"><a href="#cb46-33" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> BinaryJsonWriter <span class="kw">implements</span> JsonWriter <span class="op">{</span></span>
<span id="cb46-34"><a href="#cb46-34" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> Endianness endianness<span class="op">;</span></span>
<span id="cb46-35"><a href="#cb46-35" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="bu">String</span> copyright<span class="op">;</span></span>
<span id="cb46-36"><a href="#cb46-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-37"><a href="#cb46-37" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">BinaryJsonWriter</span><span class="op">(</span></span>
<span id="cb46-38"><a href="#cb46-38" aria-hidden="true" tabindex="-1"></a>            Endianness endianness<span class="op">,</span></span>
<span id="cb46-39"><a href="#cb46-39" aria-hidden="true" tabindex="-1"></a>            <span class="bu">String</span> copyright</span>
<span id="cb46-40"><a href="#cb46-40" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{}</span></span>
<span id="cb46-41"><a href="#cb46-41" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb46-42"><a href="#cb46-42" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb46-43"><a href="#cb46-43" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">write</span><span class="op">(</span><span class="bu">Appendable</span> out<span class="op">,</span> JSON json<span class="op">)</span> <span class="op">{</span></span>
<span id="cb46-44"><a href="#cb46-44" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb46-45"><a href="#cb46-45" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb46-46"><a href="#cb46-46" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<pre class="jshelllanguage"><code>new BinaryJsonWriter(
        Endianness.BIG_ENDIAN,
        &quot;(c) 2022&quot;
).writeJson(out, json);

new TextJsonWriter(
        true,
        false,
        &quot;(c) 2022&quot;
).writeJson(out, json);</code></pre>
<h2 id="option-22-take-everything-as-an-object-and-figure-it-out-at-runtime">Option 22. Take everything as an object and figure it out at runtime.</h2>
<p>You need to choose whether you silently ignore bad combinations of objects and what behaviors get preference, but there is a simplicity to just throwing it all into a record or opaque object and figuring it out from there.</p>
<div class="sourceCode" id="cb48"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb48-1"><a href="#cb48-1" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> Endianness <span class="op">{</span></span>
<span id="cb48-2"><a href="#cb48-2" aria-hidden="true" tabindex="-1"></a>    BIG_ENDIAN<span class="op">,</span></span>
<span id="cb48-3"><a href="#cb48-3" aria-hidden="true" tabindex="-1"></a>    LITTLE_ENDIAN</span>
<span id="cb48-4"><a href="#cb48-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb48-5"><a href="#cb48-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb48-6"><a href="#cb48-6" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Options</span><span class="op">(</span></span>
<span id="cb48-7"><a href="#cb48-7" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Boolean</span> indentObjects<span class="op">,</span> </span>
<span id="cb48-8"><a href="#cb48-8" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Boolean</span> indentArrays<span class="op">,</span></span>
<span id="cb48-9"><a href="#cb48-9" aria-hidden="true" tabindex="-1"></a>        <span class="bu">String</span> copyright<span class="op">,</span></span>
<span id="cb48-10"><a href="#cb48-10" aria-hidden="true" tabindex="-1"></a>        <span class="dt">boolean</span> useBinary<span class="op">,</span></span>
<span id="cb48-11"><a href="#cb48-11" aria-hidden="true" tabindex="-1"></a>        Endianness endianness</span>
<span id="cb48-12"><a href="#cb48-12" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb48-13"><a href="#cb48-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">final</span> Options INDENT_EVERYTHING <span class="op">=</span></span>
<span id="cb48-14"><a href="#cb48-14" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="fu">Options</span><span class="op">(</span></span>
<span id="cb48-15"><a href="#cb48-15" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">true</span><span class="op">,</span> </span>
<span id="cb48-16"><a href="#cb48-16" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">true</span><span class="op">,</span> </span>
<span id="cb48-17"><a href="#cb48-17" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">null</span><span class="op">,</span> </span>
<span id="cb48-18"><a href="#cb48-18" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">false</span><span class="op">,</span> </span>
<span id="cb48-19"><a href="#cb48-19" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">null</span></span>
<span id="cb48-20"><a href="#cb48-20" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb48-21"><a href="#cb48-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">final</span> Options NO_INDENT <span class="op">=</span></span>
<span id="cb48-22"><a href="#cb48-22" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="fu">Options</span><span class="op">(</span></span>
<span id="cb48-23"><a href="#cb48-23" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">false</span><span class="op">,</span> </span>
<span id="cb48-24"><a href="#cb48-24" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">false</span><span class="op">,</span> </span>
<span id="cb48-25"><a href="#cb48-25" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">null</span><span class="op">,</span> </span>
<span id="cb48-26"><a href="#cb48-26" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">false</span><span class="op">,</span> </span>
<span id="cb48-27"><a href="#cb48-27" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">null</span></span>
<span id="cb48-28"><a href="#cb48-28" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb48-29"><a href="#cb48-29" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">final</span> Options BINARY_LE <span class="op">=</span> </span>
<span id="cb48-30"><a href="#cb48-30" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="fu">Options</span><span class="op">(</span></span>
<span id="cb48-31"><a href="#cb48-31" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">null</span><span class="op">,</span></span>
<span id="cb48-32"><a href="#cb48-32" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">null</span><span class="op">,</span> </span>
<span id="cb48-33"><a href="#cb48-33" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">null</span><span class="op">,</span> </span>
<span id="cb48-34"><a href="#cb48-34" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">true</span><span class="op">,</span> </span>
<span id="cb48-35"><a href="#cb48-35" aria-hidden="true" tabindex="-1"></a>                    Endianness<span class="op">.</span><span class="fu">LITTLE_ENDIAN</span></span>
<span id="cb48-36"><a href="#cb48-36" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb48-37"><a href="#cb48-37" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb48-38"><a href="#cb48-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb48-39"><a href="#cb48-39" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb48-40"><a href="#cb48-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb48-41"><a href="#cb48-41" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> JsonWriter <span class="op">{</span></span>
<span id="cb48-42"><a href="#cb48-42" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">JsonWriter</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb48-43"><a href="#cb48-43" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb48-44"><a href="#cb48-44" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb48-45"><a href="#cb48-45" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb48-46"><a href="#cb48-46" aria-hidden="true" tabindex="-1"></a>            Json json<span class="op">,</span></span>
<span id="cb48-47"><a href="#cb48-47" aria-hidden="true" tabindex="-1"></a>            Options options</span>
<span id="cb48-48"><a href="#cb48-48" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb48-49"><a href="#cb48-49" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>options<span class="op">.</span><span class="fu">useBinary</span><span class="op">()</span> <span class="op">&amp;&amp;</span></span>
<span id="cb48-50"><a href="#cb48-50" aria-hidden="true" tabindex="-1"></a>                <span class="op">(</span>options<span class="op">.</span><span class="fu">indentArrays</span><span class="op">()</span> <span class="op">!=</span> <span class="kw">null</span> </span>
<span id="cb48-51"><a href="#cb48-51" aria-hidden="true" tabindex="-1"></a>                        <span class="op">||</span> options<span class="op">.</span><span class="fu">indentObjects</span><span class="op">()</span> <span class="op">!=</span> <span class="kw">null</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb48-52"><a href="#cb48-52" aria-hidden="true" tabindex="-1"></a>            <span class="co">// ignore or throw</span></span>
<span id="cb48-53"><a href="#cb48-53" aria-hidden="true" tabindex="-1"></a>            <span class="kw">...</span></span>
<span id="cb48-54"><a href="#cb48-54" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb48-55"><a href="#cb48-55" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="cf">if</span> <span class="op">(!</span>options<span class="op">.</span><span class="fu">useBinary</span><span class="op">()</span> <span class="op">&amp;&amp;</span></span>
<span id="cb48-56"><a href="#cb48-56" aria-hidden="true" tabindex="-1"></a>                    options<span class="op">.</span><span class="fu">endianness</span><span class="op">()</span> <span class="op">!=</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb48-57"><a href="#cb48-57" aria-hidden="true" tabindex="-1"></a>            <span class="kw">...</span></span>
<span id="cb48-58"><a href="#cb48-58" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb48-59"><a href="#cb48-59" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb48-60"><a href="#cb48-60" aria-hidden="true" tabindex="-1"></a>            <span class="kw">...</span></span>
<span id="cb48-61"><a href="#cb48-61" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb48-62"><a href="#cb48-62" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb48-63"><a href="#cb48-63" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb49"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb49-1"><a href="#cb49-1" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb49-2"><a href="#cb49-2" aria-hidden="true" tabindex="-1"></a>        out<span class="op">,</span> </span>
<span id="cb49-3"><a href="#cb49-3" aria-hidden="true" tabindex="-1"></a>        json<span class="op">,</span> </span>
<span id="cb49-4"><a href="#cb49-4" aria-hidden="true" tabindex="-1"></a>        Options<span class="op">.</span><span class="fu">INDENT_EVERYTHING</span></span>
<span id="cb49-5"><a href="#cb49-5" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb49-6"><a href="#cb49-6" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb49-7"><a href="#cb49-7" aria-hidden="true" tabindex="-1"></a>        out<span class="op">,</span></span>
<span id="cb49-8"><a href="#cb49-8" aria-hidden="true" tabindex="-1"></a>        json<span class="op">,</span></span>
<span id="cb49-9"><a href="#cb49-9" aria-hidden="true" tabindex="-1"></a>        Options<span class="op">.</span><span class="fu">BINARY_LE</span></span>
<span id="cb49-10"><a href="#cb49-10" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb49-11"><a href="#cb49-11" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb49-12"><a href="#cb49-12" aria-hidden="true" tabindex="-1"></a>        out<span class="op">,</span></span>
<span id="cb49-13"><a href="#cb49-13" aria-hidden="true" tabindex="-1"></a>        json<span class="op">,</span></span>
<span id="cb49-14"><a href="#cb49-14" aria-hidden="true" tabindex="-1"></a>        <span class="kw">new</span> <span class="fu">Options</span><span class="op">(</span></span>
<span id="cb49-15"><a href="#cb49-15" aria-hidden="true" tabindex="-1"></a>            <span class="kw">null</span><span class="op">,</span></span>
<span id="cb49-16"><a href="#cb49-16" aria-hidden="true" tabindex="-1"></a>            <span class="kw">null</span><span class="op">,</span> </span>
<span id="cb49-17"><a href="#cb49-17" aria-hidden="true" tabindex="-1"></a>            <span class="kw">null</span><span class="op">,</span></span>
<span id="cb49-18"><a href="#cb49-18" aria-hidden="true" tabindex="-1"></a>            <span class="kw">true</span><span class="op">,</span> </span>
<span id="cb49-19"><a href="#cb49-19" aria-hidden="true" tabindex="-1"></a>            Endianness<span class="op">.</span><span class="fu">BIG_ENDIAN</span></span>
<span id="cb49-20"><a href="#cb49-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span></span>
<span id="cb49-21"><a href="#cb49-21" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span></code></pre></div>
<h2 id="option-23-model-valid-choices-in-the-type-hierarchy">Option 23. Model valid choices in the type hierarchy.</h2>
<p>With a bit of restructuring, you can actually make an <code>Options</code> object that will correctly handle having that disjoint set of options.</p>
<p>Maybe not what you would choose with 100 settings or more complicated legality restrictions, but for this case it all seems to work out.</p>
<div class="sourceCode" id="cb50"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb50-1"><a href="#cb50-1" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> Endianness <span class="op">{</span></span>
<span id="cb50-2"><a href="#cb50-2" aria-hidden="true" tabindex="-1"></a>    BIG_ENDIAN<span class="op">,</span></span>
<span id="cb50-3"><a href="#cb50-3" aria-hidden="true" tabindex="-1"></a>    LITTLE_ENDIAN</span>
<span id="cb50-4"><a href="#cb50-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb50-5"><a href="#cb50-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb50-6"><a href="#cb50-6" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Options permits BinaryOptions<span class="op">,</span> TextOptions <span class="op">{</span></span>
<span id="cb50-7"><a href="#cb50-7" aria-hidden="true" tabindex="-1"></a>    Optional<span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> <span class="fu">copyright</span><span class="op">();</span></span>
<span id="cb50-8"><a href="#cb50-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb50-9"><a href="#cb50-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb50-10"><a href="#cb50-10" aria-hidden="true" tabindex="-1"></a>record <span class="fu">TextOptions</span><span class="op">(</span></span>
<span id="cb50-11"><a href="#cb50-11" aria-hidden="true" tabindex="-1"></a>        <span class="at">@Override</span> Optional<span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> copyright<span class="op">,</span></span>
<span id="cb50-12"><a href="#cb50-12" aria-hidden="true" tabindex="-1"></a>        <span class="dt">boolean</span> indentObjects<span class="op">,</span></span>
<span id="cb50-13"><a href="#cb50-13" aria-hidden="true" tabindex="-1"></a>        <span class="dt">boolean</span> indentArrays</span>
<span id="cb50-14"><a href="#cb50-14" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="kw">implements</span> Options <span class="op">{}</span></span>
<span id="cb50-15"><a href="#cb50-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb50-16"><a href="#cb50-16" aria-hidden="true" tabindex="-1"></a>record <span class="fu">BinaryOptions</span><span class="op">(</span></span>
<span id="cb50-17"><a href="#cb50-17" aria-hidden="true" tabindex="-1"></a>        <span class="at">@Override</span> Optional<span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> copyright<span class="op">,</span></span>
<span id="cb50-18"><a href="#cb50-18" aria-hidden="true" tabindex="-1"></a>        Endianness endianness</span>
<span id="cb50-19"><a href="#cb50-19" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="kw">implements</span> Options <span class="op">{}</span></span>
<span id="cb50-20"><a href="#cb50-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb50-21"><a href="#cb50-21" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb50-22"><a href="#cb50-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb50-23"><a href="#cb50-23" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> JsonWriter <span class="op">{</span></span>
<span id="cb50-24"><a href="#cb50-24" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">JsonWriter</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb50-25"><a href="#cb50-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb50-26"><a href="#cb50-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb50-27"><a href="#cb50-27" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb50-28"><a href="#cb50-28" aria-hidden="true" tabindex="-1"></a>            Json json<span class="op">,</span></span>
<span id="cb50-29"><a href="#cb50-29" aria-hidden="true" tabindex="-1"></a>            Options options</span>
<span id="cb50-30"><a href="#cb50-30" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb50-31"><a href="#cb50-31" aria-hidden="true" tabindex="-1"></a>        <span class="cf">switch</span> <span class="op">(</span>options<span class="op">)</span> <span class="op">{</span></span>
<span id="cb50-32"><a href="#cb50-32" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> TextOptions textOptions <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb50-33"><a href="#cb50-33" aria-hidden="true" tabindex="-1"></a>                <span class="kw">...</span></span>
<span id="cb50-34"><a href="#cb50-34" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb50-35"><a href="#cb50-35" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> BinaryOptions binaryOptions <span class="op">-&gt;</span></span>
<span id="cb50-36"><a href="#cb50-36" aria-hidden="true" tabindex="-1"></a>                <span class="cf">switch</span> <span class="op">(</span>binaryOptions<span class="op">.</span><span class="fu">endianness</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb50-37"><a href="#cb50-37" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">case</span> BIG_ENDIAN <span class="op">-&gt;</span> <span class="kw">...</span></span>
<span id="cb50-38"><a href="#cb50-38" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">case</span> LITTLE_ENDIAN <span class="op">-&gt;</span> <span class="kw">...</span></span>
<span id="cb50-39"><a href="#cb50-39" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb50-40"><a href="#cb50-40" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb50-41"><a href="#cb50-41" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb50-42"><a href="#cb50-42" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb51"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb51-1"><a href="#cb51-1" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb51-2"><a href="#cb51-2" aria-hidden="true" tabindex="-1"></a>        out<span class="op">,</span> </span>
<span id="cb51-3"><a href="#cb51-3" aria-hidden="true" tabindex="-1"></a>        json<span class="op">,</span> </span>
<span id="cb51-4"><a href="#cb51-4" aria-hidden="true" tabindex="-1"></a>        <span class="kw">new</span> <span class="fu">TextOptions</span><span class="op">(</span>Optional<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;(c) 2022&quot;</span><span class="op">),</span> <span class="kw">true</span><span class="op">,</span> <span class="kw">false</span><span class="op">)</span></span>
<span id="cb51-5"><a href="#cb51-5" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb51-6"><a href="#cb51-6" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb51-7"><a href="#cb51-7" aria-hidden="true" tabindex="-1"></a>        out<span class="op">,</span></span>
<span id="cb51-8"><a href="#cb51-8" aria-hidden="true" tabindex="-1"></a>        json<span class="op">,</span></span>
<span id="cb51-9"><a href="#cb51-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">new</span> <span class="fu">BinaryOptions</span><span class="op">(</span>Optional<span class="op">.</span><span class="fu">empty</span><span class="op">(),</span> Endianness<span class="op">.</span><span class="fu">BIG_ENDIAN</span><span class="op">)</span></span>
<span id="cb51-10"><a href="#cb51-10" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span></code></pre></div>
<h2 id="option-24-give-up-on-typing-it-just-pass-a-map">Option 24. Give up on typing it, just pass a map</h2>
<p>This was always an option. It works just as well here as it does in a dynamic language, it's just a tad more verbose and unsafe.</p>
<div class="sourceCode" id="cb52"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb52-1"><a href="#cb52-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> JsonWriter <span class="op">{</span></span>
<span id="cb52-2"><a href="#cb52-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">JsonWriter</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb52-3"><a href="#cb52-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb52-4"><a href="#cb52-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb52-5"><a href="#cb52-5" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Appendable</span> out<span class="op">,</span></span>
<span id="cb52-6"><a href="#cb52-6" aria-hidden="true" tabindex="-1"></a>            Json json<span class="op">,</span></span>
<span id="cb52-7"><a href="#cb52-7" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Map</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">,</span> <span class="bu">Object</span><span class="op">&gt;</span> options</span>
<span id="cb52-8"><a href="#cb52-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb52-9"><a href="#cb52-9" aria-hidden="true" tabindex="-1"></a>        var copyright <span class="op">=</span> options<span class="op">.</span><span class="fu">get</span><span class="op">(</span><span class="st">&quot;copyright&quot;</span><span class="op">);</span></span>
<span id="cb52-10"><a href="#cb52-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>copyright <span class="op">==</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb52-11"><a href="#cb52-11" aria-hidden="true" tabindex="-1"></a>            <span class="kw">...</span></span>
<span id="cb52-12"><a href="#cb52-12" aria-hidden="true" tabindex="-1"></a>            var endianness <span class="op">=</span> options<span class="op">.</span><span class="fu">get</span><span class="op">(</span><span class="st">&quot;binary&quot;</span><span class="op">);</span></span>
<span id="cb52-13"><a href="#cb52-13" aria-hidden="true" tabindex="-1"></a>            <span class="kw">...</span></span>
<span id="cb52-14"><a href="#cb52-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb52-15"><a href="#cb52-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>copyright <span class="kw">instanceof</span> <span class="bu">String</span> copyrightString<span class="op">)</span> <span class="op">{</span></span>
<span id="cb52-16"><a href="#cb52-16" aria-hidden="true" tabindex="-1"></a>            <span class="kw">...</span></span>
<span id="cb52-17"><a href="#cb52-17" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb52-18"><a href="#cb52-18" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb52-19"><a href="#cb52-19" aria-hidden="true" tabindex="-1"></a>            <span class="cf">throw</span> <span class="kw">new</span> <span class="bu">IllegalArgumentException</span><span class="op">(</span><span class="kw">...</span><span class="op">);</span></span>
<span id="cb52-20"><a href="#cb52-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb52-21"><a href="#cb52-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb52-22"><a href="#cb52-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb53"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb53-1"><a href="#cb53-1" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb53-2"><a href="#cb53-2" aria-hidden="true" tabindex="-1"></a>        out<span class="op">,</span> </span>
<span id="cb53-3"><a href="#cb53-3" aria-hidden="true" tabindex="-1"></a>        json<span class="op">,</span></span>
<span id="cb53-4"><a href="#cb53-4" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Map</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb53-5"><a href="#cb53-5" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;indentObjects&quot;</span><span class="op">,</span> <span class="kw">true</span><span class="op">,</span></span>
<span id="cb53-6"><a href="#cb53-6" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;copyright&quot;</span><span class="op">,</span> <span class="st">&quot;(c) 2022&quot;</span></span>
<span id="cb53-7"><a href="#cb53-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span></span>
<span id="cb53-8"><a href="#cb53-8" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span>
<span id="cb53-9"><a href="#cb53-9" aria-hidden="true" tabindex="-1"></a><span class="fu">writeJson</span><span class="op">(</span></span>
<span id="cb53-10"><a href="#cb53-10" aria-hidden="true" tabindex="-1"></a>        out<span class="op">,</span> </span>
<span id="cb53-11"><a href="#cb53-11" aria-hidden="true" tabindex="-1"></a>        json<span class="op">,</span></span>
<span id="cb53-12"><a href="#cb53-12" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Map</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb53-13"><a href="#cb53-13" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;binary&quot;</span><span class="op">,</span> <span class="kw">true</span><span class="op">,</span></span>
<span id="cb53-14"><a href="#cb53-14" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;endianness&quot;</span><span class="op">,</span> Endianness<span class="op">.</span><span class="fu">BIG_ENDIAN</span></span>
<span id="cb53-15"><a href="#cb53-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">)</span></span>
<span id="cb53-16"><a href="#cb53-16" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span></code></pre></div>
<hr />
<h1 id="hypothetical-5">Hypothetical 5.</h1>
<p>You've taken the mouse to the movies. People don't need all the configuration options you've provided and don't like using the API that has them. They want a simpler API.</p>
<p>Maybe you should have gone with option 1.</p>
<hr />
<p>Exercise for the reader. Make a spreadsheet of all these options versus all the criteria you use to evaluate software and fill in the grid with smiley faces, frowny faces, and meh faces. Feel free to fill in some options I missed, like reading from environment variables, system properties, or more inheritance schemes.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Why Java didn't add flow typing</title><link>https://mccue.dev/pages/1-25-22-method-overload-with-new-switch</link><description></description><pubDate>Tue, 25 Jan 0022 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Why Java didn't add flow typing</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Why Java didn't add flow typing</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
Java's method priority rules are part of the reason why pattern matching works the way it does.

<p>Say you had code that you wrote in the past 30 years that looks like this</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Example<span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">){</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Number</span> i <span class="op">=</span> <span class="dv">3</span><span class="op">;</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>i <span class="kw">instanceof</span> <span class="bu">Integer</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>            <span class="fu">doTask</span><span class="op">(</span>i<span class="op">);</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">doTask</span><span class="op">(</span><span class="bu">Integer</span> i<span class="op">){</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;integer&quot;</span><span class="op">);</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">doTask</span><span class="op">(</span><span class="bu">Number</span> i<span class="op">){</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;number&quot;</span><span class="op">);</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This will output <code>number</code> even though <code>i</code> is an <code>Integer</code> because the stated type of <code>i</code> is <code>Number</code>.</p>
<p>In other languages like kotlin, if you check if <code>i</code> is an <code>Integer</code>, within the block of that if it will be considered an integer by the compiler.</p>
<p>Since java has legacy code that might have done something like this, you have to explicitly name a variable that will be considered an <code>Integer</code> after the check</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="bu">Number</span> number <span class="op">=</span> <span class="dv">3</span><span class="op">;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>number <span class="kw">instanceof</span> <span class="bu">Integer</span> integer<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    <span class="fu">doTask</span><span class="op">(</span>integer<span class="op">);</span> <span class="co">// will select the integer overload</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="fu">doTask</span><span class="op">(</span>number<span class="op">);</span> <span class="co">// will select the number overload</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">// integer and number both refer to the same object</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>    <span class="co">// so this will output true</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>integer <span class="op">==</span> number<span class="op">);</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>While this might feel like a nuisance, structuring the language feature like this enables more generic "pattern matching" syntax that you can read about here (coming in the next few years) <a href="https://openjdk.java.net/jeps/405">https://openjdk.java.net/jeps/405</a></p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>The switch that only I like</title><link>https://mccue.dev/pages/1-24-22-silly-switch</link><description></description><pubDate>Mon, 24 Jan 0022 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>The switch that only I like</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">The switch that only I like</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
One thing that I think is really cool, but no one else cares about, is that if you make a sealed interface which only has one implementor (say, if you are enriching a class via generated code) then there is actually a way for you to make a "type safe cast" between the two things.

<p>What i mean by this is, consider a normal cast</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="bu">Integer</span> i <span class="op">=</span> <span class="dv">3</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="bu">Object</span> o <span class="op">=</span> i<span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="bu">String</span> s <span class="op">=</span> <span class="op">(</span><span class="bu">String</span><span class="op">)</span> o<span class="op">;</span> <span class="co">// boom, ClassCastException</span></span></code></pre></div>
<p>Normal casts are allowed by the language to fail. If you did not properly track the types of things and you try to cast to a type you are not compatible with your code will still compile, but it will crash at runtime.</p>
<p>Even if you write an interface that has a single implementor, the language can't guarantee that later on there won't be another one added.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">interface</span> Thing <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">exist</span><span class="op">();</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> OnlyThingImpl <span class="kw">implements</span> Thing <span class="op">{</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> specialThing <span class="op">=</span> <span class="dv">8</span><span class="op">;</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">exist</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a><span class="co">// This code works perfectly well</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>Thing thing <span class="op">=</span> <span class="kw">...</span><span class="op">;</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>OnlyThingImpl thingImpl <span class="op">=</span> <span class="op">(</span>OnlyThingImpl<span class="op">)</span> thing<span class="op">;</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a><span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>thingImpl<span class="op">.</span><span class="fu">specialThing</span><span class="op">);</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a><span class="co">// but if an intern adds another implementation, java won&#39;t warn you about</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a><span class="co">// the old usage and it will crash at runtime if you happen to call that code</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a><span class="co">// with the wrong implementation.</span></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> OtherThingImpl <span class="kw">implements</span> Thing <span class="op">{</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">exist</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;party&quot;</span><span class="op">);</span></span>
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-29"><a href="#cb2-29" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Even making the interface sealed doesn't solve this, since Java won't force you to handle other possibilities in your casts if another case is added to the sealed class</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> Thing permits OnlyThingImpl <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">exist</span><span class="op">();</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="co">// This still has the same problem - you might forget about this code</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>OnlyThingImpl thingImpl <span class="op">=</span> <span class="op">(</span>OnlyThingImpl<span class="op">)</span> thing<span class="op">;</span></span></code></pre></div>
<p>What can solve this is a "safe cast" done via a pattern matching switch.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>OnlyThingImpl thingImpl <span class="op">=</span> <span class="cf">switch</span> <span class="op">(</span>thing<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> OnlyThingImpl __ <span class="op">-&gt;</span> __<span class="op">;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Why you should care about Sealed Types</title><link>https://mccue.dev/pages/1-24-22-sealed-types</link><description></description><pubDate>Mon, 24 Jan 0022 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Why you should care about Sealed Types</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Why you should care about Sealed Types</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
As of Java 17 (with --enable-preview) you can combine two features - pattern matching and sealed types - to represent and deal with cases where two things have different sets of data.

<p>Say you want to represent three different kinds of items you can check out from a library.</p>
<p>A book, which has a title and author</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>record <span class="bu">Book</span><span class="op">(</span><span class="bu">String</span> title<span class="op">,</span> <span class="bu">String</span> author<span class="op">)</span> <span class="op">{}</span></span></code></pre></div>
<p>A CD, which has a runtime and genre</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>record <span class="fu">CD</span><span class="op">(</span><span class="dt">double</span> runtime<span class="op">,</span> <span class="bu">String</span> genre<span class="op">)</span> <span class="op">{}</span></span></code></pre></div>
<p>And a VHS tape, which contains precious memories</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>record <span class="fu">VHSTape</span><span class="op">(</span><span class="bu">List</span><span class="op">&lt;</span>Memory<span class="op">&gt;</span> preciousMemories<span class="op">)</span> <span class="op">{}</span></span></code></pre></div>
<p>What you can do to have a method which might return any one of these cases, or to have a list of any item in the library, is make a common interface that all three of them share</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">interface</span> LibraryItem <span class="op">{}</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>record <span class="bu">Book</span><span class="op">(</span><span class="bu">String</span> title<span class="op">,</span> <span class="bu">String</span> author<span class="op">)</span> <span class="kw">implements</span> LibraryItem <span class="op">{}</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>record <span class="fu">CD</span><span class="op">(</span><span class="dt">double</span> runtime<span class="op">,</span> <span class="bu">String</span> genre<span class="op">)</span> <span class="kw">implements</span> LibraryItem <span class="op">{}</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>record <span class="fu">VHSTape</span><span class="op">(</span><span class="bu">List</span><span class="op">&lt;</span>Memory<span class="op">&gt;</span> preciousMemories<span class="op">)</span> <span class="kw">implements</span> LibraryItem <span class="op">{}</span></span></code></pre></div>
<p>The problem is that if you have a LibraryItem object, there isn't much you can actually do with it since the three cases of library items have different kinds of data and thus you cant access everything from the interface</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>LibraryItem item <span class="op">=</span> <span class="kw">...</span><span class="op">;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>item<span class="op">.</span><span class="fu">title</span><span class="op">();</span> <span class="co">// nope</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>item<span class="op">.</span><span class="fu">runtime</span><span class="op">();</span> <span class="co">// also nope</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>item<span class="op">.</span><span class="fu">preciousMemories</span><span class="op">();</span> <span class="co">// you&#39;ll never get them back</span></span></code></pre></div>
<p>To remedy this, you can make the interface sealed. This guarantees to the language that Book, CD, and VHSTape are the only classes which implement LibraryItem</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> LibraryItem permits <span class="bu">Book</span><span class="op">,</span> CD<span class="op">,</span> VHSTape <span class="op">{}</span></span></code></pre></div>
<p>Now if you have an instance of library item, you can use it with a "pattern switch expression" to safely recover the actual type of the item</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>LibraryItem item <span class="op">=</span> <span class="kw">...</span><span class="op">;</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="cf">switch</span> <span class="op">(</span>item<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> <span class="bu">Book</span> book <span class="op">-&gt;</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>         <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>book<span class="op">.</span><span class="fu">title</span><span class="op">());</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> CD cd <span class="op">-&gt;</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>         <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>cd<span class="op">.</span><span class="fu">genre</span><span class="op">());</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> VHSTape tape <span class="op">-&gt;</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>         <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>tape<span class="op">.</span><span class="fu">preciousMemories</span><span class="op">());</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Code generation with annotation processors</title><link>https://mccue.dev/pages/1-23-22-code-generation</link><description></description><pubDate>Sun, 23 Jan 0022 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Code generation with annotation processors</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Code generation with annotation processors</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
Java does not allow annotation processors to affect the source or bytecode of classes you have written, only generate new classes.

<p>In Java 17, there is a clever way around this restriction though.</p>
<p>Lets say you want to make an annotation processor that adds a <code>toJson</code> method to a class based on some automated set of rules.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="at">@AutoToJson</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> record <span class="fu">BasicThing</span><span class="op">(</span><span class="bu">String</span> color<span class="op">,</span> <span class="bu">String</span> size<span class="op">)</span> <span class="op">{}</span></span></code></pre></div>
<p>What you can do is generate an interface with a predictable name</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">interface</span> BasicThingToJson <span class="op">{}</span></span></code></pre></div>
<p>Make it "sealed", so that only the class you want to can implement it</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> BasicThingToJson permits BasicThing <span class="op">{}</span></span></code></pre></div>
<p>And then inside of the interface you can add a default method, in which it is safe to assume that the only possible class that implements the interface is the class you want to</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> BasicThingToJson permits BasicThing <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">default</span> JSON <span class="fu">toJson</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>        <span class="co">// totally safe</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>        var self <span class="op">=</span> <span class="op">(</span>BasicThing<span class="op">)</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>        var jsonObject <span class="op">=</span> <span class="kw">new</span> <span class="fu">JsonObject</span><span class="op">();</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>        jsonObject<span class="op">.</span><span class="fu">set</span><span class="op">(</span><span class="st">&quot;color&quot;</span><span class="op">,</span> self<span class="op">.</span><span class="fu">color</span><span class="op">());</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>        jsonObject<span class="op">.</span><span class="fu">set</span><span class="op">(</span><span class="st">&quot;size&quot;</span><span class="op">,</span> self<span class="op">.</span><span class="fu">size</span><span class="op">());</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> jsonObject<span class="op">;</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And then all your user has to do is</p>
<ol type="1">
<li>Annotate their class</li>
<li>Implement the interface that will be generated (its kinda circular, but it works out)</li>
</ol>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="at">@AutoToJson</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> record <span class="fu">BasicThing</span><span class="op">(</span><span class="bu">String</span> color<span class="op">,</span> <span class="bu">String</span> size<span class="op">)</span> <span class="kw">implements</span> BasicThingToJson <span class="op">{}</span></span></code></pre></div>
<p>And then boom, their class has been "enriched" in whatever way you want.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>var basicThing <span class="op">=</span> <span class="kw">new</span> <span class="fu">BasicThing</span><span class="op">(</span><span class="st">&quot;red&quot;</span><span class="op">,</span> <span class="st">&quot;small&quot;</span><span class="op">);</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>var json <span class="op">=</span> basicThing<span class="op">.</span><span class="fu">toJson</span><span class="op">();</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Basics of Annotation Processors</title><link>https://mccue.dev/pages/1-23-22-annotation-processor</link><description></description><pubDate>Sun, 23 Jan 0022 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Basics of Annotation Processors</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Basics of Annotation Processors</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
If you register an implementation of `javax.annotation.processing.Processor` with the ServiceLoader mechanism then you can make what is called an "Annotation Processor".

<p>Annotations are just metadata that can be put onto classes, fields, etc.</p>
<p>You can declare your own annotation like this</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span><span class="im"> some</span><span class="op">.</span><span class="im">pack</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="at">@Target</span><span class="op">({</span><span class="bu">ElementType</span><span class="op">.</span><span class="fu">TYPE</span><span class="op">})</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="at">@Retention</span><span class="op">(</span><span class="bu">RetentionPolicy</span><span class="op">.</span><span class="fu">SOURCE</span><span class="op">)</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="at">@interface</span> YourAnnotation <span class="op">{</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>In this example the annotation can only be used on "types" like classes or interfaces and the metadata is only available on the source code.</p>
<p>So we can use that example annotation to mark a class of ours</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="at">@YourAnnotation</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> SomeClass <span class="op">{}</span></span></code></pre></div>
<p>And any annotation processors that the ServiceLoader can find at compile time can do stuff like generate brand new code, or add new compile time checks.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="at">@SupportedAnnotationTypes</span><span class="op">(</span><span class="st">&quot;some.pack.MagicBean&quot;</span><span class="op">)</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="at">@SupportedSourceVersion</span><span class="op">(</span><span class="bu">SourceVersion</span><span class="op">.</span><span class="fu">RELEASE_17</span><span class="op">)</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> AnnotationProcessor <span class="kw">extends</span> <span class="bu">AbstractProcessor</span> <span class="op">{</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">boolean</span> <span class="fu">process</span><span class="op">(</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Set</span><span class="op">&lt;?</span> <span class="kw">extends</span> <span class="bu">TypeElement</span><span class="op">&gt;</span> annotations<span class="op">,</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>            <span class="bu">RoundEnvironment</span> roundEnv</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>        var filer <span class="op">=</span> <span class="kw">this</span><span class="op">.</span><span class="fu">processingEnv</span><span class="op">.</span><span class="fu">getFiler</span><span class="op">();</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>        var elements <span class="op">=</span> roundEnv<span class="op">.</span><span class="fu">getElementsAnnotatedWith</span><span class="op">(</span>YourAnnotation<span class="op">.</span><span class="fu">class</span><span class="op">);</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>            var file <span class="op">=</span> filer<span class="op">.</span><span class="fu">createSourceFile</span><span class="op">(</span><span class="st">&quot;brand.new.Code&quot;</span><span class="op">);</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>            <span class="cf">try</span> <span class="op">(</span>var writer <span class="op">=</span> file<span class="op">.</span><span class="fu">openWriter</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>                <span class="co">// there are libraries like javapoet which make doing this easier</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>                writer<span class="op">.</span><span class="fu">append</span><span class="op">(</span><span class="st">&quot;&quot;&quot;</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>                <span class="kw">package</span><span class="im"> brand</span><span class="op">.</span><span class="im">new</span><span class="op">;</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a>                <span class="kw">class</span> Code <span class="op">{</span></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">final</span> <span class="dt">int</span> NUMBER_OF_INSTANCES <span class="op">=</span> <span class="op">%</span>s<span class="op">;</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;&quot;&quot;.formatted(elements.size()));</span></span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true" tabindex="-1"></a>            <span class="cf">catch</span> <span class="op">(</span><span class="bu">IOException</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a>                <span class="cf">throw</span> <span class="kw">new</span> <span class="bu">RuntimeException</span><span class="op">(</span>e<span class="op">);</span></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> </span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">true</span><span class="op">;</span></span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Which in this case we generate a new class which has the number of annotated classes as a constant.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>The Service Loader Mechanism</title><link>https://mccue.dev/pages/1-20-22-service-provider-interface</link><description></description><pubDate>Thu, 20 Jan 0022 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>The Service Loader Mechanism</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">The Service Loader Mechanism</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
If you have an interface or abstract class defined in some jar

<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span><span class="im"> whatever</span><span class="op">.</span><span class="im">project</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">interface</span> DoesThing <span class="op">{</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>   <span class="dt">void</span> <span class="fu">doThing</span><span class="op">();</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And in another jar you have one or more implementations of that interface which has a zero argument constructor</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span><span class="im"> something</span><span class="op">.</span><span class="im">other</span><span class="op">;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> DoesThingImpl <span class="kw">implements</span> DoesThing <span class="op">{</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">doThing</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;I implemented this in a certain way&quot;</span><span class="op">);</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>as well as a file in that jar with the interface name under <code>META-INF/services</code></p>
<pre><code>META-INF/services/whatever.project,DoesThing</code></pre>
<p>which has a line that has the name of the implementing class</p>
<pre><code>something.other.DoesThingImpl</code></pre>
<p>Then you can obtain an implementation of that interface via the service loader mechanism</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>var loader <span class="op">=</span> <span class="bu">ServiceLoader</span><span class="op">.</span><span class="fu">load</span><span class="op">(</span>DoesThing<span class="op">.</span><span class="fu">class</span><span class="op">);</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> <span class="op">(</span>var thingDoer <span class="op">:</span> loader<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    thingDoer<span class="op">.</span><span class="fu">doThing</span><span class="op">();</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This is some really core magic and is how most of the projects that want you to just add dependencies to get functionality - like slf4j, jdbc, twelvemonkeys, etc - use to do their thing</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Factories in FP</title><link>https://mccue.dev/pages/1-17-22-factories-in-fp</link><description></description><pubDate>Mon, 17 Jan 0022 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Factories in FP</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Factories in FP</h1>
</header>
<h2 id="question-from-muhammad-hamza-chippa">Question from Muhammad Hamza Chippa</h2>
<blockquote>
<p>How would you replace Factory design patterns in functional programming?</p>
</blockquote>
<p>Before someone else says it - with a function</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">interface</span> ThingFactory <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    Thing <span class="fu">makeThing</span><span class="op">();</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">work</span><span class="op">(</span>ThingFactory factory<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    var thing <span class="op">=</span> factory<span class="op">.</span><span class="fu">makeThing</span><span class="op">();</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    thing<span class="op">.</span><span class="fu">whatever</span><span class="op">();</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb2"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> work </span>[factory]</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  (<span class="kw">let</span> [thing (factory)]</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    (.whatever thing)))</span></code></pre></div>
<p>You can also use the exact pattern as is (where the producer method gets a special name) with traits/typeclasses/protocols depending on your FP language</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Aliasing core functions in Clojure</title><link>https://mccue.dev/pages/1-1-22-aliasing-core-functions</link><description></description><pubDate>Sat, 01 Jan 0022 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Aliasing core functions in Clojure</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Aliasing core functions in Clojure</h1>
</header>
<h2 id="question-from-rmxm">Question from rmxm</h2>
<blockquote>
<p>Funny question, how do you cover for "get" word being a function name, say you have namespace 'computer, surely it would be intuitive to have "get" function obtaining "computer". Just wondering how do you overcome this linguitically 🙂 or do you just place get at the bottom</p>
</blockquote>
<p>You are allowed to have a function named get - you just need to put <code>(:refer-clojure :exclude [get])</code> in your namespace declaration to avoid warnings.</p>
<p>And then you refer to the core <code>get</code> as <code>clojure.core/get</code> within that file.</p>
<p>so</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">ns</span> <span class="kw">some</span>.computer</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  (<span class="at">:refer-clojure</span> <span class="at">:exclude</span> [<span class="kw">get</span>]))</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> get </span>[o]</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  (clojure.core/get o <span class="at">:thing</span>))</span></code></pre></div>
<p>or</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode clojure"><code class="sourceCode clojure"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">ns</span> <span class="kw">some</span>.computer</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  (<span class="at">:require</span> [clojure.core <span class="at">:as</span> core])</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  (<span class="at">:refer-clojure</span> <span class="at">:exclude</span> [<span class="kw">get</span>]))</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>(<span class="bu">defn</span><span class="fu"> get </span>[o]</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>  (core/get o <span class="at">:thing</span>))</span></code></pre></div>
<blockquote>
<p>sure, sure its not a technical question more of, do you use a different function name, or do you choose another word etc.</p>
</blockquote>
<p>I do this with <code>update</code> in some contexts.</p>
<p>No I just use get if I want to - but you have to be more specific about the use case for me to give a better name.</p>
<p>You can usually call it <code>get-thing</code> or <code>thing</code></p>
<blockquote>
<p>If you mention both get and update in this case I will assume this is ok practice</p>
</blockquote>
<p>its fine, depends on your domain</p>
<blockquote>
<p>sure, sure, thanks 🙂</p>
<p>I could also <code>get*</code> or something like that for, "c/grud" stuff, <code>get*, update*, delete*, create*</code> seems, ok I think</p>
</blockquote>
<p>if the intended usage of the namespace is <code>:require [a.b.thing :as thing], thing/func</code> and the ns is small and focused (enough that you wont forget you shadowed a core fn) then don’t worry about it</p>
<blockquote>
<p>thanks, going the get* route, this less bother down the road i think</p>
</blockquote>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How can you write this productSum algorithm written in JS in Java?</title><link>https://mccue.dev/pages/10-15-21-product-sum-algorithm</link><description></description><pubDate>Fri, 15 Oct 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How can you write this productSum algorithm written in JS in Java?</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How can you write this productSum algorithm written in JS in Java?</h1>
</header>
<h2 id="question-from-uwarrior242">Question from u/warrior242</h2>
<blockquote>
<p>I want to write this algorithm from JS to Java and I am having some problem doing it because Java does not support parameter defaults and does not do dynamic inputs. I know this must be somehow possible and even better written in a typed language but I dont know how. Please help Java Gods.</p>
<p>The algorithm is supposed to go through the array, and add it up and multiply each part by the depth that its at.</p>
<p>So something like <code>[1, 2]</code></p>
<p>would be something like</p>
<p><code>(1 * 1) + (2 * 1)</code>.</p>
<p>Something at depth <code>[1, 2, [3, 4] ]</code></p>
<p>would be:</p>
<p>(1 * 1) + (2 * 1). + (( 3 + 4) *2)</p>
<p>As far as I understand anyways</p>
<p>Link for JS version of algorithm:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> ProductSum{</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="fu">constructor</span>() {</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    }</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    <span class="fu">solution</span>(array<span class="op">,</span> multiplier <span class="op">=</span> <span class="dv">1</span>) {</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> sum <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> (<span class="kw">let</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> array<span class="op">.</span><span class="at">length</span><span class="op">;</span> i<span class="op">++</span>) {</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> (array[i] <span class="kw">instanceof</span> <span class="bu">Array</span>) {</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>                sum <span class="op">+=</span> <span class="kw">this</span><span class="op">.</span><span class="fu">solution</span> (array[i]<span class="op">,</span> multiplier <span class="op">+</span> <span class="dv">1</span>)</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>            }</span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>            <span class="cf">else</span> {</span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>                sum <span class="op">=</span> sum <span class="op">+</span> array[i]<span class="op">;</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>            }</span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>        }</span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> sum <span class="op">*</span> multiplier<span class="op">;</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>    }</span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>}</span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> myArray <span class="op">=</span> [<span class="dv">5</span><span class="op">,</span> <span class="dv">2</span><span class="op">,</span> [<span class="dv">7</span><span class="op">,</span> <span class="op">-</span><span class="dv">1</span>]<span class="op">,</span> <span class="dv">3</span><span class="op">,</span> [<span class="dv">6</span><span class="op">,</span> [<span class="op">-</span><span class="dv">13</span><span class="op">,</span> <span class="dv">8</span>]<span class="op">,</span> <span class="dv">4</span>]]<span class="op">;</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> mySolution <span class="op">=</span> <span class="kw">new</span> <span class="fu">ProductSum</span>()<span class="op">;</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> result <span class="op">=</span> mySolution<span class="op">.</span><span class="fu">solution</span>(myArray)<span class="op">;</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a><span class="bu">console</span><span class="op">.</span><span class="fu">log</span>(result)<span class="op">;</span></span></code></pre></div>
</blockquote>
<p>So for java, first you need to represent this "type" of data in some way. You have a List of either single numbers or other Lists containing the same.</p>
<p>You can represent this like so</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> NestedNumberList <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">SingleNumber</span><span class="op">(</span><span class="dt">int</span> x<span class="op">)</span> </span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>            <span class="kw">implements</span> NestedNumberList <span class="op">{}</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">MultipleNumbers</span><span class="op">(</span><span class="bu">List</span><span class="op">&lt;</span>NestedNumberList<span class="op">&gt;</span> numbers<span class="op">)</span> </span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>            <span class="kw">implements</span> NestedNumberList <span class="op">{}</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Which you should read as a <code>NestedNumberList</code> is one of <code>SingleNumber</code> or <code>MultipleNumbers</code>.</p>
<p>which makes your example data look like this</p>
<pre><code>[5, 2, [7, -1], 3, [6, [-13, 8], 4]]</code></pre>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>var myArray <span class="op">=</span> <span class="kw">new</span> <span class="fu">MultipleNumbers</span><span class="op">(</span><span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">new</span> <span class="fu">SingleNumber</span><span class="op">(</span><span class="dv">5</span><span class="op">),</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">new</span> <span class="fu">SingleNumber</span><span class="op">(</span><span class="dv">2</span><span class="op">),</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">new</span> <span class="fu">MultipleNumbers</span><span class="op">(</span><span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">new</span> <span class="fu">SingleNumber</span><span class="op">(</span><span class="dv">7</span><span class="op">),</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>        <span class="kw">new</span> <span class="fu">SingleNumber</span><span class="op">(-</span><span class="dv">1</span><span class="op">)</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">)),</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">new</span> <span class="fu">SingleNumber</span><span class="op">(</span><span class="dv">3</span><span class="op">),</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">new</span> <span class="fu">MultipleNumbers</span><span class="op">(</span><span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">new</span> <span class="fu">SingleNumber</span><span class="op">(</span><span class="dv">6</span><span class="op">),</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>        <span class="kw">new</span> <span class="fu">MultipleNumbers</span><span class="op">(</span><span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="fu">SingleNumber</span><span class="op">(-</span><span class="dv">13</span><span class="op">),</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="fu">SingleNumber</span><span class="op">(</span><span class="dv">8</span><span class="op">)</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">)),</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">new</span> <span class="fu">SingleNumber</span><span class="op">(</span><span class="dv">4</span><span class="op">);</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">));</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a><span class="op">));</span></span></code></pre></div>
<p>Which yes, is way more verbose, but lets not dwell on that. This is a bit of a pathological case.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> ProductSum <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">solution</span><span class="op">(</span>MultipleNumbers array<span class="op">,</span> <span class="dt">int</span> multiplier<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> sum <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span>var num <span class="op">:</span> array<span class="op">.</span><span class="fu">numbers</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>            <span class="cf">switch</span> <span class="op">(</span>num<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>              <span class="cf">case</span> SingleNumber single <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>                  sum <span class="op">=</span> sum <span class="op">+</span> single<span class="op">.</span><span class="fu">x</span><span class="op">();</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>              <span class="op">}</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>              <span class="cf">case</span> MultipleNumbers multiple <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>                  sum <span class="op">+=</span> <span class="kw">this</span><span class="op">.</span><span class="fu">solutionHelper</span><span class="op">(</span>multiple<span class="op">,</span> multiplier <span class="op">+</span> <span class="dv">1</span><span class="op">);</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>              <span class="op">}</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> sum <span class="op">*</span> multiplier<span class="op">;</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="fu">solution</span><span class="op">(</span>MultipleNumbers array<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">solution</span><span class="op">(</span>array<span class="op">,</span> <span class="dv">1</span><span class="op">);</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="kw">new</span> <span class="fu">ProductSum</span><span class="op">().</span><span class="fu">solution</span><span class="op">(</span>myArray<span class="op">));</span></span></code></pre></div>
<p>So thats roughly conceptually equivalent. (for Java 17 with preview features). For the default multiplier value, in this case we emulate that with method overloading.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Smuggling Checked Exceptions with Sealed Interfaces</title><link>https://mccue.dev/pages/11-1-21-smuggling-checked-exceptions</link><description></description><pubDate>Fri, 01 Oct 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Smuggling Checked Exceptions with Sealed Interfaces</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Smuggling Checked Exceptions with Sealed Interfaces</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
# Vanilla Code

<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">Connection</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">SQLException</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">ArrayList</span><span class="op">;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">List</span><span class="op">;</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">Optional</span><span class="op">;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>record <span class="fu">User</span><span class="op">(</span><span class="bu">String</span> name<span class="op">)</span> <span class="op">{}</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> VanillaCode <span class="op">{</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> Optional<span class="op">&lt;</span>User<span class="op">&gt;</span> <span class="fu">lookupUser</span><span class="op">(</span><span class="bu">Connection</span> db<span class="op">,</span> <span class="dt">int</span> id<span class="op">)</span> <span class="kw">throws</span> <span class="bu">SQLException</span>  <span class="op">{</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>        var statement <span class="op">=</span> db<span class="op">.</span><span class="fu">prepareStatement</span><span class="op">(</span><span class="st">&quot;SELECT name FROM USER where id = ?&quot;</span><span class="op">);</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>        statement<span class="op">.</span><span class="fu">setInt</span><span class="op">(</span><span class="dv">1</span><span class="op">,</span> id<span class="op">);</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>        var resultSet <span class="op">=</span> statement<span class="op">.</span><span class="fu">executeQuery</span><span class="op">();</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>resultSet<span class="op">.</span><span class="fu">next</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> Optional<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="kw">new</span> <span class="fu">User</span><span class="op">(</span>resultSet<span class="op">.</span><span class="fu">getString</span><span class="op">(</span><span class="dv">1</span><span class="op">)));</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> Optional<span class="op">.</span><span class="fu">empty</span><span class="op">();</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="bu">List</span><span class="op">&lt;</span>Optional<span class="op">&lt;</span>User<span class="op">&gt;&gt;</span> <span class="fu">lookupMultipleUsers</span><span class="op">(</span><span class="bu">Connection</span> db<span class="op">,</span> <span class="bu">List</span><span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;</span> ids<span class="op">)</span> <span class="kw">throws</span> <span class="bu">SQLException</span> <span class="op">{</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>        <span class="bu">List</span><span class="op">&lt;</span>Optional<span class="op">&lt;</span>User<span class="op">&gt;&gt;</span> users <span class="op">=</span> <span class="kw">new</span> <span class="bu">ArrayList</span><span class="op">&lt;&gt;();</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> id <span class="op">:</span> ids<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>            users<span class="op">.</span><span class="fu">add</span><span class="op">(</span><span class="fu">lookupUser</span><span class="op">(</span>db<span class="op">,</span> id<span class="op">));</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> users<span class="op">;</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">exampleUsage</span><span class="op">(</span><span class="bu">Connection</span> db<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a>            <span class="fu">lookupUser</span><span class="op">(</span>db<span class="op">,</span> <span class="dv">123</span><span class="op">).</span><span class="fu">ifPresentOrElse</span><span class="op">(</span></span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a>                    user <span class="op">-&gt;</span> <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;FOUND USER: &quot;</span> <span class="op">+</span> user<span class="op">),</span></span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a>                    <span class="op">()</span> <span class="op">-&gt;</span> <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;NO SUCH USER&quot;</span><span class="op">)</span></span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a>            <span class="op">);</span></span>
<span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span><span class="bu">SQLException</span> sqlException<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-37"><a href="#cb1-37" aria-hidden="true" tabindex="-1"></a>            <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;ERROR RUNNING QUERY: &quot;</span> <span class="op">+</span> sqlException<span class="op">);</span></span>
<span id="cb1-38"><a href="#cb1-38" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-39"><a href="#cb1-39" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-40"><a href="#cb1-40" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h1 id="sealed-types">Sealed Types</h1>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">Connection</span><span class="op">;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">sql</span><span class="op">.</span><span class="im">SQLException</span><span class="op">;</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">List</span><span class="op">;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>record <span class="fu">User</span><span class="op">(</span><span class="bu">String</span> name<span class="op">)</span> <span class="op">{}</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>sealed <span class="kw">interface</span> UserLookupResult <span class="op">{</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">FoundUser</span><span class="op">(</span>User user<span class="op">)</span> <span class="kw">implements</span> UserLookupResult <span class="op">{}</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">NoSuchUser</span><span class="op">()</span> <span class="kw">implements</span> UserLookupResult <span class="op">{}</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">ErrorRunningQuery</span><span class="op">(</span><span class="bu">SQLException</span> sqlException<span class="op">)</span> <span class="kw">implements</span> UserLookupResult <span class="op">{}</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> SealedTypes <span class="op">{</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> UserLookupResult <span class="fu">lookupUser</span><span class="op">(</span><span class="bu">Connection</span> db<span class="op">,</span> <span class="dt">int</span> id<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>            var statement <span class="op">=</span> db<span class="op">.</span><span class="fu">prepareStatement</span><span class="op">(</span><span class="st">&quot;SELECT name FROM USER where id = ?&quot;</span><span class="op">);</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>            statement<span class="op">.</span><span class="fu">setInt</span><span class="op">(</span><span class="dv">1</span><span class="op">,</span> id<span class="op">);</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a>            var resultSet <span class="op">=</span> statement<span class="op">.</span><span class="fu">executeQuery</span><span class="op">();</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>resultSet<span class="op">.</span><span class="fu">next</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="kw">new</span> UserLookupResult<span class="op">.</span><span class="fu">FoundUser</span><span class="op">(</span><span class="kw">new</span> <span class="fu">User</span><span class="op">(</span>resultSet<span class="op">.</span><span class="fu">getString</span><span class="op">(</span><span class="dv">1</span><span class="op">)));</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a>            <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="kw">new</span> UserLookupResult<span class="op">.</span><span class="fu">NoSuchUser</span><span class="op">();</span></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a>        <span class="cf">catch</span> <span class="op">(</span><span class="bu">SQLException</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">new</span> UserLookupResult<span class="op">.</span><span class="fu">ErrorRunningQuery</span><span class="op">(</span>e<span class="op">);</span></span>
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb2-29"><a href="#cb2-29" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-30"><a href="#cb2-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-31"><a href="#cb2-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="bu">List</span><span class="op">&lt;</span>UserLookupResult<span class="op">&gt;</span> <span class="fu">lookupMultipleUsers</span><span class="op">(</span><span class="bu">Connection</span> db<span class="op">,</span> <span class="bu">List</span><span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;</span> ids<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-32"><a href="#cb2-32" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> ids</span>
<span id="cb2-33"><a href="#cb2-33" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">stream</span><span class="op">()</span></span>
<span id="cb2-34"><a href="#cb2-34" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">map</span><span class="op">(</span>id <span class="op">-&gt;</span> <span class="fu">lookupUser</span><span class="op">(</span>db<span class="op">,</span> id<span class="op">))</span></span>
<span id="cb2-35"><a href="#cb2-35" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span><span class="fu">toList</span><span class="op">();</span></span>
<span id="cb2-36"><a href="#cb2-36" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-37"><a href="#cb2-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-38"><a href="#cb2-38" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">exampleUsage</span><span class="op">(</span><span class="bu">Connection</span> db<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-39"><a href="#cb2-39" aria-hidden="true" tabindex="-1"></a>        <span class="cf">switch</span> <span class="op">(</span><span class="fu">lookupUser</span><span class="op">(</span>db<span class="op">,</span> <span class="dv">123</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb2-40"><a href="#cb2-40" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> UserLookupResult<span class="op">.</span><span class="fu">FoundUser</span> foundUser <span class="op">-&gt;</span></span>
<span id="cb2-41"><a href="#cb2-41" aria-hidden="true" tabindex="-1"></a>                <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;FOUND USER: &quot;</span> <span class="op">+</span> foundUser<span class="op">.</span><span class="fu">user</span><span class="op">());</span></span>
<span id="cb2-42"><a href="#cb2-42" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> UserLookupResult<span class="op">.</span><span class="fu">NoSuchUser</span> __ <span class="op">-&gt;</span></span>
<span id="cb2-43"><a href="#cb2-43" aria-hidden="true" tabindex="-1"></a>                <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;NO SUCH USER&quot;</span><span class="op">);</span></span>
<span id="cb2-44"><a href="#cb2-44" aria-hidden="true" tabindex="-1"></a>            <span class="cf">case</span> UserLookupResult<span class="op">.</span><span class="fu">ErrorRunningQuery</span> errorRunningQuery <span class="op">-&gt;</span></span>
<span id="cb2-45"><a href="#cb2-45" aria-hidden="true" tabindex="-1"></a>                <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;ERROR RUNNING QUERY: &quot;</span> <span class="op">+</span> errorRunningQuery<span class="op">.</span><span class="fu">sqlException</span><span class="op">());</span></span>
<span id="cb2-46"><a href="#cb2-46" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb2-47"><a href="#cb2-47" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-48"><a href="#cb2-48" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<p>Sealed interfaces let you properly represent "sum types". This thing is either "A" or "B".</p>
<p>In this case we have a <code>Stream&lt;Integer&gt;</code> that we want to turn into a <code>Stream&lt;User&gt;</code>, but our method that takes <code>Integer -&gt; User</code> throws a <code>SQLException</code>.</p>
<p>Your options before sealed interfaces were to</p>
<ol type="1">
<li>Make it a <code>Stream&lt;User&gt;</code> by re-throwing any <code>SQLException</code> as a <code>RuntimeException</code>. As other comments have mentioned, this can be an issue depending on your type of stream. Also it requires that you fail the whole procedure if getting any one <code>User</code> fails</li>
<li>Make it a <code>Stream&lt;Object&gt;</code> by returning any <code>SQLException</code> as a value, then cast it back at the end with <code>instanceof</code> checks.</li>
<li>Make it a <code>Stream&lt;Try&lt;User&gt;&gt;</code> like with <code>vavr</code>. This works if you don't care about the exception and just care that it failed in some way, but you won't be able to call methods particular to <code>SQLException</code> like <code>getSQLState</code> without casting. Also you lose documentation of why something can fail.</li>
<li>Do this same technique, but without a sealed interface. Doing this without needing to have <code>default -&gt; ... error ...</code> branches on all your switches would require using the visitor pattern.</li>
</ol>
<p>The new option is what you see, you can properly represent a function from <code>Integer</code> -&gt; <code>User | SQLException</code> by wrapping each of the values in a sealed hierarchy.</p>
<pre><code>sealed interface UserLookupResult {
    record FoundUser(User user) implements UserLookupResult {}
    record ErrorRunningQuery(SQLException sqlException) implements UserLookupResult {}
}</code></pre>
<p>So it becomes <code>Stream&lt;Integer&gt;</code> -&gt; <code>Stream&lt;UserLookupResult&gt;</code>, which is effectively <code>Stream&lt;FoundUser | ErrorRunningQuery&gt;</code>. This gives you the most flexibility in how to interpret the result of the Stream without any casting or assumptions in usage.</p>
<p>Also if you had another possibility like <code>UserIsBanned</code>, you can add it to the sealed hierarchy and all our switches would force you to fix them.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Static Dependency Injection with Intersection Types</title><link>https://mccue.dev/pages/9-6-21-static-dependency-injection</link><description></description><pubDate>Mon, 06 Sep 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Static Dependency Injection with Intersection Types</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Static Dependency Injection with Intersection Types</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
One of the patterns I am personally partial to that I haven't really seen get traction or attention in Java is to do DI manually.

<p>Imagine a hypothetical web framework.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">interface</span> <span class="bu">Handler</span><span class="op">&lt;</span><span class="bu">Context</span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Response</span> <span class="fu">handle</span><span class="op">(</span><span class="bu">Context</span> context<span class="op">,</span> <span class="bu">Request</span> request<span class="op">)</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="dt">final</span> <span class="kw">class</span> Router<span class="op">&lt;</span><span class="bu">Context</span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">...</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>    <span class="fu">Router</span><span class="op">(</span><span class="bu">Context</span> context<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">addHandler</span><span class="op">(</span><span class="bu">String</span> route<span class="op">,</span> <span class="bu">Handler</span><span class="op">&lt;</span><span class="bu">Context</span><span class="op">&gt;</span> handler<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>We can make a router that carries through some context to the different handlers</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="bu">List</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> ips <span class="op">=</span> <span class="bu">Collections</span><span class="op">.</span><span class="fu">synchronizedList</span><span class="op">(</span><span class="kw">new</span> <span class="bu">ArrayList</span><span class="op">&lt;&gt;());</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>Router<span class="op">&lt;</span><span class="bu">List</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;&gt;</span> router <span class="op">=</span> <span class="kw">new</span> Router<span class="op">&lt;&gt;(</span>ips<span class="op">);</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>router<span class="op">.</span><span class="fu">addHandler</span><span class="op">(</span><span class="st">&quot;/hello&quot;</span><span class="op">,</span> <span class="op">(</span>ips<span class="op">,</span> req<span class="op">)</span> <span class="op">-&gt;</span> <span class="op">{</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    ips<span class="op">.</span><span class="fu">add</span><span class="op">(</span>req<span class="op">.</span><span class="fu">ip</span><span class="op">());</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="bu">Response</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>ips<span class="op">.</span><span class="fu">toString</span><span class="op">());</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="op">});</span></span></code></pre></div>
<p>And then all our route handlers will get the context. Then the trick is to make an interface for each stateful "thing" a handler might want access to, like a database connection or a redis connection.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">interface</span> HasDB <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    DB <span class="fu">db</span><span class="op">();</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="kw">interface</span> HasRedis <span class="op">{</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    Redis <span class="fu">redis</span><span class="op">();</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And similarly for anything that you might have that is "derivative" of those root stateful components</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">interface</span> UserService <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    User <span class="fu">findById</span><span class="op">(</span><span class="dt">int</span> id<span class="op">);</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="dt">final</span> <span class="kw">class</span> UserServiceImpl <span class="kw">implements</span> UserService <span class="op">{</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">...</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>    <span class="fu">UserServiceImpl</span><span class="op">(</span>DB db<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>    User <span class="fu">findById</span><span class="op">(</span><span class="dt">int</span> id<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>        <span class="kw">...</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a><span class="kw">interface</span> HasUserService <span class="op">{</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>    UserService <span class="fu">userService</span><span class="op">();</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And make the "Context" be a type that implements all of those interfaces</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>record <span class="bu">System</span><span class="op">(</span>DB db<span class="op">,</span> Redis redis<span class="op">)</span> <span class="kw">implements</span> HasDB<span class="op">,</span> HasRedis<span class="op">,</span> HasUserService <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> UserService <span class="fu">userService</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">UserServiceImpl</span><span class="op">(</span>db<span class="op">);</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Then a handler just needs to "declare its dependencies" by saying which stateful components it wants to use. For example if we have a handler that just wants to lookup a user and write things into redis</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">static</span> <span class="op">&lt;</span>Components <span class="kw">extends</span> HasRedis <span class="op">&amp;</span> HasUserService<span class="op">&gt;</span> <span class="fu">handleRequest</span><span class="op">(</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    Components components<span class="op">,</span> <span class="bu">Request</span> request</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>   var redis <span class="op">=</span> components<span class="op">.</span><span class="fu">redis</span><span class="op">();</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>   var userService <span class="op">=</span> components<span class="op">.</span><span class="fu">userService</span><span class="op">();</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>   <span class="kw">...</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a><span class="bu">System</span> system <span class="op">=</span> <span class="kw">new</span> <span class="bu">System</span><span class="op">(</span><span class="kw">...</span><span class="op">);</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>Router<span class="op">&lt;</span><span class="bu">System</span><span class="op">&gt;</span> router <span class="op">=</span> <span class="kw">new</span> Router<span class="op">&lt;&gt;(</span>system<span class="op">);</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a>router<span class="op">.</span><span class="fu">addHandler</span><span class="op">(</span><span class="st">&quot;/hello&quot;</span><span class="op">,</span> Handlers<span class="op">::</span>handleRequest<span class="op">);</span></span></code></pre></div>
<p>And by virtue of <code>System</code> being <code>HasDB</code>, <code>HasRedis</code> and a <code>HasUserService</code> it will fulfill <code>HasRedis &amp; HasUserService</code>.</p>
<p>Replace "route handler" with whatever other entry points your app has and boom, dependency injection without reflection or magics.</p>
<p>There are downsides - <code>System</code> might get fairly large depending on your preferences, it doesn't solve the problem of starting everything in the right order, and there is a decent amount of boilerplate - but I just wish more people knew about this "System pattern."</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Basic C++ value class</title><link>https://mccue.dev/pages/8-18-21-basic-cpp-value-class</link><description></description><pubDate>Wed, 18 Aug 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Basic C++ value class</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Basic C++ value class</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
A class in C++ is the same thing as a struct, just the `clas`s keyword makes the fields private by default
instead of public by default with struct.

<p>Here is a complete example of a simple "money" class</p>
<pre class="cplusplus"><code>#pragma once

#include &lt;cstdint&gt;
#include &lt;functional&gt;
#include &lt;ostream&gt;
#include &lt;optional&gt;

namespace shopping {
    class Money final {
    private:
        constexpr explicit Money(std::uint32_t cents) noexcept: cents(cents) {};
        const std::uint32_t cents;

    public:
        constexpr static Money fromCents(std::uint32_t cents) noexcept {
            return Money(cents);
        };

        constexpr bool operator==(const Money&amp; other) const noexcept {
            return this-&gt;cents == other.cents;
        };

        [[nodiscard]] constexpr std::uint32_t getCents() const noexcept {
            return this-&gt;cents;
        };

        friend std::ostream&amp; operator&lt;&lt;(std::ostream &amp;os, const Money &amp;money) {
            os &lt;&lt; &quot;Money{cents=&quot; &lt;&lt; money.cents &lt;&lt; &quot;}&quot;;
            return os;
        };

        constexpr Money operator+(const Money&amp; other) const noexcept {
            return Money::fromCents(this-&gt;getCents() + other.getCents());
        };

        constexpr std::optional&lt;Money&gt; operator-(const Money&amp; other) const noexcept {
            if (other.getCents() &gt; this-&gt;getCents()) {
                return std::nullopt;
            }
            else {
                return Money::fromCents(this-&gt;getCents() - other.getCents());
            }
        };
    };
}

namespace std {
    template &lt;&gt; struct hash&lt;shopping::Money&gt; {
        size_t operator()(const shopping::Money&amp; money) const noexcept {
            return hash&lt;uint32_t&gt;{}(money.getCents());
        }
    };
}</code></pre>
<p>This is the same as this rust</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>derive<span class="at">(</span><span class="bu">Debug</span><span class="op">,</span> <span class="bu">Eq</span><span class="op">,</span> <span class="bu">PartialEq</span><span class="op">,</span> <span class="bu">Hash</span><span class="at">)]</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Money(cents<span class="op">:</span> <span class="dt">u32</span>)<span class="op">;</span></span></code></pre></div>
<p>Now maybe stop learning c++.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Handling numbers too big for base data types</title><link>https://mccue.dev/pages/8-18-21-how-to-handle-big-numbers</link><description></description><pubDate>Wed, 18 Aug 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Handling numbers too big for base data types</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Handling numbers too big for base data types</h1>
</header>
<h2 id="question-from-skip4185">Question from Skip#4185</h2>
<blockquote>
<p>How do you handle numbers that are too big to fit into the largest available data types?</p>
<p>Would you define a struct containing multiple large data types and somehow split up the number?</p>
<p>I'm not trying to do something like that, but i'm just curious if anyone knows what the right course of action would be in such a case</p>
</blockquote>
<p>End of day you should use a bigint library, but you can also "build" it yourself if you are so inclined</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdlib.h&gt;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> bigint_kind <span class="op">{</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    _64_BIT<span class="op">,</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    _MORE_THAN_64_BIT</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="kw">union</span> bigint_value <span class="op">{</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">long</span> u64<span class="op">;</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> <span class="op">{</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>        <span class="dt">long</span><span class="op">*</span> blocks_of_64_bit<span class="op">;</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>        <span class="dt">size_t</span> length<span class="op">;</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> bigger_than_u64<span class="op">;</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> bigint <span class="op">{</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">enum</span> bigint_kind _kind<span class="op">;</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">union</span> bigint_value _value<span class="op">;</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> bigint<span class="op">*</span> bigint_from_long<span class="op">(</span><span class="dt">long</span> value<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> bigint<span class="op">*</span> i <span class="op">=</span> calloc<span class="op">(</span><span class="dv">0</span><span class="op">,</span> <span class="kw">sizeof</span><span class="op">(</span><span class="kw">struct</span> bigint<span class="op">));</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>    i<span class="op">-&gt;</span>_kind <span class="op">=</span> _64_BIT<span class="op">;</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">union</span> bigint_value value_<span class="op">;</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>    value_<span class="op">.</span>u64 <span class="op">=</span> value<span class="op">;</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>    i<span class="op">-&gt;</span>_value <span class="op">=</span> value_<span class="op">;</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> i<span class="op">;</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> bigint_free<span class="op">(</span><span class="kw">struct</span> bigint<span class="op">*</span> i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>i<span class="op">-&gt;</span>_kind <span class="op">==</span> _MORE_THAN_64_BIT<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a>        free<span class="op">(</span>i<span class="op">-&gt;</span>_value<span class="op">.</span>bigger_than_u64<span class="op">.</span>blocks_of_64_bit<span class="op">);</span></span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a>    free<span class="op">(</span>i<span class="op">)</span></span>
<span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>If you are using rote C it can be a bit of a nightmare to track memory now for darn numbers since any of them can now contain a heap allocated array and in C you don't have "move semantics" like c++ so you end up doing unneeded heap allocations to track stuff and also there is some pointer indirection here which is annoying.</p>
<p>TL;DR; use a library for it</p>
<p>python, java, etc it should "just work". python's numerics auto promote and java has BigInteger. But the only languages on your profile are C and python. so if you are asking the question...</p>
<p>Exercise for the reader</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> bigint<span class="op">*</span> bigint_add<span class="op">(</span><span class="kw">struct</span> bigint<span class="op">*</span> a<span class="op">,</span> <span class="kw">struct</span> bigint<span class="op">*</span> b<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>a<span class="op">-&gt;</span>_kind <span class="op">==</span> _64_BIT<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>b<span class="op">-&gt;</span>_kind <span class="op">==</span> _64_BIT<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>            </span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>            </span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How to build C++ from a git repo</title><link>https://mccue.dev/pages/8-17-21-makefile-for-cc-files-from-git-repo</link><description></description><pubDate>Tue, 17 Aug 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How to build C++ from a git repo</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How to build C++ from a git repo</h1>
</header>
<h2 id="question-from-csstudentbruh5797">Question from csstudentbruh#5797</h2>
<blockquote>
<p>How do I make a makefile in order to compile a .cc file that uses libraries from a git repo</p>
</blockquote>
<p>Okay so there are basically 2 questions there</p>
<ol type="1">
<li>what are the commands to run to compile the git repo and include it in your code</li>
<li>how to use a makefile to do it</li>
</ol>
<p>In general using a makefile is just copy pasting the commands you would have run by hand so lets focus on question 1.</p>
<p><a href="https://github.com/hzeller/rpi-rgb-led-matrix">https://github.com/hzeller/rpi-rgb-led-matrix</a></p>
<p>Looking at the library, it looks like they have a make file which can build it.</p>
<p>So in broad strokes - build that library with something like <code>make all</code>, then build your code which references the header files in the library then link all the code together.</p>
<p>c++ is a nightmare, I'm truly sorry. It has the worst "build story" of any modern language.</p>
<p><img src="./8-17-21-img.jpeg"></img></p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Type Classes in Elm</title><link>https://mccue.dev/pages/8-10-21-typeclasses-in-elm</link><description></description><pubDate>Tue, 10 Aug 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Type Classes in Elm</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Type Classes in Elm</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
## Conversation with somebody#0002
>
> elm doesn't even have typeclasses apparently

<p>Yeah, but you can do the pattern the same way scala does, just manually</p>
<blockquote>
<p>so how does show work in elm</p>
</blockquote>
<div class="sourceCode" id="cb1"><pre class="sourceCode elm"><code class="sourceCode elm"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="kw">alias</span> <span class="dt">ShowOps</span> <span class="fu">a</span> <span class="op">=</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    { <span class="fu">show</span> : <span class="fu">a</span> <span class="op">-&gt;</span> <span class="dt">String</span> }</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="fu">show</span> : <span class="dt">ShowOps</span> <span class="fu">a</span> <span class="op">-&gt;</span> <span class="fu">a</span> <span class="op">-&gt;</span> <span class="dt">String</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="fu">show</span> <span class="fu">ops</span> <span class="fu">a</span> <span class="op">=</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    <span class="fu">ops</span><span class="op">.</span><span class="fu">show</span> <span class="fu">a</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="fu">stringShowOps</span> : <span class="dt">ShowOps</span> <span class="dt">String</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="fu">stringShowOps</span> <span class="op">=</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>    { <span class="fu">show</span> <span class="op">=</span> <span class="fu">identity</span> }</span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="fu">intShowOps</span> : <span class="dt">ShowOps</span> <span class="dt">Int</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a><span class="fu">intShowOps</span> <span class="op">=</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>    { <span class="fu">show</span> <span class="op">=</span> <span class="dt">String</span><span class="op">.</span><span class="fu">fromInt</span> }</span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a><span class="fu">listShowOps</span> : <span class="dt">ShowOps</span> <span class="fu">a</span> <span class="op">-&gt;</span> <span class="dt">ShowOps</span> (<span class="dt">List</span> <span class="fu">a</span>)</span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a><span class="fu">listShowOps</span> <span class="fu">elementShowOps</span> <span class="op">=</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>    { <span class="fu">show</span> <span class="op">=</span> \<span class="fu">l</span> <span class="op">-&gt;</span> <span class="st">&quot;[ &quot;</span> <span class="op">++</span> <span class="dt">String</span><span class="op">.</span><span class="fu">join</span> <span class="st">&quot;, &quot;</span> (<span class="dt">List</span><span class="op">.</span><span class="fu">map</span> (<span class="fu">show</span> <span class="fu">elementShowOps</span>) <span class="fu">l</span>) <span class="op">++</span> <span class="st">&quot; ]&quot;</span> }</span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a><span class="fu">x</span> : <span class="dt">String</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a><span class="fu">x</span> <span class="op">=</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>    <span class="fu">show</span> (<span class="fu">listShowOps</span> <span class="fu">intShowOps</span>) [ <span class="dv">1</span><span class="op">,</span> <span class="dv">2</span><span class="op">,</span> <span class="dv">3</span> ]</span></code></pre></div>
<p>Like this.</p>
<p>It's literally the same as scala except there are no implicit parameters - at which point you start to realize that maybe its not that special a pattern.</p>
<blockquote>
<p>well</p>
<p>obviously.</p>
<p>it's the implicit parameters that is the special part</p>
</blockquote>
<p>sure, but the point is if i want to take a parameter that is <code>Show</code>, I just need access to the functions</p>
<blockquote>
<p>well... yes that's kinda how vtables work too?</p>
</blockquote>
<p>Yep, it's all connected. You want "dynamic dispatch" in a strongly typed system with no interface polymorphism? Make a vtable, pass it around.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Celsius to Fahrenheit in Java</title><link>https://mccue.dev/pages/8-8-21-c-to-f-in-java</link><description></description><pubDate>Sun, 08 Aug 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Celsius to Fahrenheit in Java</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Celsius to Fahrenheit in Java</h1>
</header>
<h2 id="question-from-sahil8151">Question from Sahil#8151</h2>
<blockquote>
<p>i want to convert celsius to farenhiet and vice versa i have got the conversion part down but i want to be able to do with only the letter so that if someone types F at the end it converst to C and if someone types C at the end of any number it converst to farenheit without asking the user to what they want it converted to</p>
</blockquote>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> Temperature <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="dt">double</span> c<span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Temperature</span><span class="op">(</span><span class="dt">double</span> c<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">c</span> <span class="op">=</span> c<span class="op">;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> Temperature <span class="fu">fromCelcius</span><span class="op">(</span><span class="dt">double</span> c<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Temperature</span><span class="op">(</span>c<span class="op">);</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> Temperature <span class="fu">fromFarenheight</span><span class="op">(</span><span class="dt">double</span> f<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">(</span>f <span class="op">-</span> <span class="dv">32</span><span class="op">)</span> <span class="op">*</span> <span class="op">(</span><span class="fl">5.0</span> <span class="op">/</span> <span class="fl">9.0</span><span class="op">);</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">double</span> <span class="fu">celcius</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">c</span><span class="op">;</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">double</span> <span class="fu">farenheight</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">(</span><span class="kw">this</span><span class="op">.</span><span class="fu">c</span> <span class="op">*</span> <span class="op">(</span><span class="fl">9.0</span> <span class="op">/</span> <span class="fl">5.0</span><span class="op">))</span> <span class="op">+</span> <span class="dv">32</span><span class="op">;</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Obviously you know how to do the math, but one technique is to just always store one temperature type, one internal representation, and do conversions as needed but directly, at the boundaries.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How to remove items using a stream</title><link>https://mccue.dev/pages/8-4-21-remove-items-with-stream</link><description></description><pubDate>Wed, 04 Aug 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How to remove items using a stream</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How to remove items using a stream</h1>
</header>
<h2 id="question-from-kevin1322">Question from Kevin#1322</h2>
<blockquote>
<p>When you iterate over a map.keySet(), map.values() or map.entrySet() and you call the iterator.remove() method. How does it work that the key-value of the map is removed?</p>
</blockquote>
<p>It depends on the exact collection. Sometimes remove won't be implemented, so for most purposes a stream and a filter would be "cleaner" and less prone to running into potentially unsupported methods.</p>
<blockquote>
<p>i see</p>
<p>how do you remove items while using a stream?</p>
</blockquote>
<p>Like this</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="bu">List</span><span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;</span> xs <span class="op">=</span> <span class="bu">List</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="dv">1</span><span class="op">,</span> <span class="dv">2</span><span class="op">,</span> <span class="dv">3</span><span class="op">,</span> <span class="dv">4</span><span class="op">);</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="bu">List</span><span class="op">&lt;</span><span class="bu">Integer</span><span class="op">&gt;</span> evens <span class="op">=</span> xs<span class="op">.</span><span class="fu">stream</span><span class="op">().</span><span class="fu">filter</span><span class="op">(</span>x <span class="op">-&gt;</span> x <span class="op">%</span> <span class="dv">2</span> <span class="op">==</span> <span class="dv">0</span><span class="op">).</span><span class="fu">collect</span><span class="op">(</span>Collectors<span class="op">.</span><span class="fu">toList</span><span class="op">());</span></span></code></pre></div>
<p>And for a map you would use Collectors.toMap if you need a map at the end. So "filter" is the answer</p>
<blockquote>
<p>I see instead of removing you just create a new collection</p>
</blockquote>
<p>Yeah, because a bunch of iterators don't support remove (like <code>ArrayList</code>'s would, but not what you get from <code>List.of(..)</code>) if you are programming to the <code>List</code> or <code>Map</code> interface instead of a particular implementation it's safer to do a filter.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How to wait for the value from onSuccess</title><link>https://mccue.dev/pages/8-4-21-waiting-for-future-to-finish</link><description></description><pubDate>Wed, 04 Aug 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How to wait for the value from onSuccess</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How to wait for the value from onSuccess</h1>
</header>
<h2 id="question-from-stefanlnd2296">Question from Stefan.lnd#2296</h2>
<blockquote>
<p>How do I make sure that java waits for the value from the onSucces method: <a href="https://pastebin.com/TR6ea2QZ">https://pastebin.com/TR6ea2QZ</a> ? (I cut out the irrelevant stuff)</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">float</span> <span class="fu">getMoney</span><span class="op">(</span>Player player<span class="op">){</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>      <span class="bu">Float</span><span class="op">[]</span> money <span class="op">=</span> <span class="kw">new</span> <span class="bu">Float</span><span class="op">[</span><span class="dv">1</span><span class="op">];</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>      <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>          <span class="co">//SOME CODE FOR DB</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>          asyncMySQL<span class="op">.</span><span class="fu">getMoneyAsnyc</span><span class="op">(</span>statement<span class="op">,</span> <span class="kw">new</span> <span class="bu">Callback</span><span class="op">&lt;</span><span class="bu">Float</span><span class="op">&gt;()</span> <span class="op">{</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>             </span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>              <span class="at">@Override</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>              <span class="kw">public</span> <span class="bu">Float</span> <span class="fu">onSucces</span><span class="op">(</span><span class="bu">Float</span> money<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>                  <span class="co">//This value should be returned!!!</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>                  money<span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">=</span> money<span class="op">;</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>              <span class="op">}</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>              <span class="at">@Override</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>              <span class="kw">public</span> <span class="dt">void</span> <span class="fu">onFailure</span><span class="op">(</span><span class="bu">Throwable</span> cause<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>              <span class="op">}</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>          <span class="op">});</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span><span class="bu">SQLException</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>          e<span class="op">.</span><span class="fu">printStackTrace</span><span class="op">();</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> money<span class="op">[</span><span class="dv">0</span><span class="op">];</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span></code></pre></div>
</blockquote>
<p>I want to call out that, long term, it;s going to be a better tech investment to use blocking sql because loom, but yes, you can return a Future<Float></p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> FutureExample <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">interface</span> ExampleAsync <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>        <span class="dt">void</span> <span class="fu">onSuccess</span><span class="op">(</span><span class="dt">float</span> money<span class="op">);</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>        <span class="dt">void</span> <span class="fu">onFailure</span><span class="op">(</span><span class="bu">Throwable</span> throwable<span class="op">);</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">void</span> <span class="fu">someThing</span><span class="op">(</span>ExampleAsync exampleAsync<span class="op">)</span> <span class="op">{}</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">Future</span><span class="op">&lt;</span><span class="bu">Float</span><span class="op">&gt;</span> <span class="fu">getMoney</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>        <span class="dt">final</span> var future <span class="op">=</span> <span class="kw">new</span> CompletableFuture<span class="op">&lt;</span><span class="bu">Float</span><span class="op">&gt;();</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>            <span class="fu">someThing</span><span class="op">(</span><span class="kw">new</span> <span class="fu">ExampleAsync</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>                <span class="at">@Override</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>                <span class="kw">public</span> <span class="dt">void</span> <span class="fu">onSuccess</span><span class="op">(</span><span class="dt">float</span> money<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>                    future<span class="op">.</span><span class="fu">complete</span><span class="op">(</span>money<span class="op">);</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a>                <span class="at">@Override</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>                <span class="kw">public</span> <span class="dt">void</span> <span class="fu">onFailure</span><span class="op">(</span><span class="bu">Throwable</span> throwable<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>                    future<span class="op">.</span><span class="fu">completeExceptionally</span><span class="op">(</span>throwable<span class="op">);</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a>            <span class="op">});</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span><span class="bu">Exception</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a>            future<span class="op">.</span><span class="fu">completeExceptionally</span><span class="op">(</span>e<span class="op">);</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> future<span class="op">;</span></span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>What does this regex mean...??</title><link>https://mccue.dev/pages/8-3-21-what-does-this-regex-group-mean</link><description></description><pubDate>Tue, 03 Aug 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>What does this regex mean...??</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">What does this regex mean...??</h1>
</header>
<h2 id="question-from-sobiter2949">Question from sobiter#2949:</h2>
<blockquote>
<p>What does this regex mean...??</p>
<pre><code>(?!.*\1)</code></pre>
<p>Anything that isn't group 1??</p>
</blockquote>
<p>It means you should go outside</p>
<p>hug a stranger</p>
<p>smell a flower</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How do I send a message to everyone</title><link>https://mccue.dev/pages/8-3-21-sending-a-message-to-everyone</link><description></description><pubDate>Tue, 03 Aug 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How do I send a message to everyone</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How do I send a message to everyone</h1>
</header>
<h2 id="question-from-gummyjon4984">Question from GummyJon#4984:</h2>
<blockquote>
<p>Hey! I'm currently trying to make a custom communication client between me and my friends, and I'm coming across an issue. I have a server running which creates a different thread per person, but I want it to run a block of code along all threads, so everybody gets the same message. How can this be done?</p>
<p>For context, this is the code itself per thread</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">net</span><span class="op">.*;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">io</span><span class="op">.*;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> <span class="bu">Handler</span> <span class="kw">extends</span> <span class="bu">Thread</span><span class="op">{</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">private</span> <span class="bu">Socket</span> socket <span class="op">=</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">public</span> <span class="bu">Handler</span><span class="op">(</span><span class="bu">Socket</span> socket<span class="op">){</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>      <span class="kw">super</span><span class="op">(</span><span class="st">&quot;Handler&quot;</span><span class="op">);</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>      <span class="kw">this</span><span class="op">.</span><span class="fu">socket</span> <span class="op">=</span> socket<span class="op">;</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">public</span> <span class="dt">void</span> <span class="fu">run</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>      <span class="cf">try</span> <span class="op">(</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>               <span class="bu">PrintWriter</span> out <span class="op">=</span> <span class="kw">new</span> <span class="bu">PrintWriter</span><span class="op">(</span>socket<span class="op">.</span><span class="fu">getOutputStream</span><span class="op">(),</span> <span class="kw">true</span><span class="op">);</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>               <span class="bu">BufferedReader</span> in <span class="op">=</span> <span class="kw">new</span> <span class="bu">BufferedReader</span><span class="op">(</span><span class="kw">new</span> <span class="bu">InputStreamReader</span><span class="op">(</span>socket<span class="op">.</span><span class="fu">getInputStream</span><span class="op">()))</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>       <span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>           <span class="bu">String</span> inputLine<span class="op">;</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>           <span class="cf">while</span> <span class="op">((</span>inputLine <span class="op">=</span> in<span class="op">.</span><span class="fu">readLine</span><span class="op">())</span> <span class="op">!=</span> <span class="kw">null</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>               <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>inputLine<span class="op">);</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>               out<span class="op">.</span><span class="fu">println</span><span class="op">(</span>inputLine<span class="op">);</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>           <span class="op">}</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>       <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>               <span class="bu">IOException</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>           <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Exception caught&quot;</span><span class="op">);</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>       <span class="op">}</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>   <span class="op">}</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>Have each thread have a method of communication. In practice this can mean each that each thread as its own queue it reads off of and the "producer" writes the same message to the queue of each "consumer".</p>
<p><a href="https://www.baeldung.com/java-concurrent-queueshttps://www.baeldung.com/java-concurrent-queues">Here</a> is a decent rundown of your options, but ArrayBlockingQueue is probably good enoughhere is a decent rundown of your options, but ArrayBlockingQueue is probably good enough, so:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Message</span><span class="op">(</span><span class="bu">String</span> contents<span class="op">)</span> <span class="op">{}</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">net</span><span class="op">.*;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">io</span><span class="op">.*;</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">ArrayBlockingQueue</span><span class="op">;</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> <span class="bu">Handler</span> <span class="kw">extends</span> <span class="bu">Thread</span><span class="op">{</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="bu">Socket</span> socket <span class="op">=</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="bu">ArrayBlockingQueue</span><span class="op">&lt;</span>Message<span class="op">&gt;</span> queue<span class="op">;</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">Handler</span><span class="op">(</span><span class="bu">ArrayBlockingQueue</span><span class="op">&lt;</span>Message<span class="op">&gt;</span> queue<span class="op">,</span> <span class="bu">Socket</span> socket<span class="op">){</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">(</span><span class="st">&quot;Handler&quot;</span><span class="op">);</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">queue</span> <span class="op">=</span> queue<span class="op">;</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">socket</span> <span class="op">=</span> socket<span class="op">;</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">run</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a>        <span class="cf">while</span> <span class="op">(</span><span class="kw">true</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>            Message msg<span class="op">;</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>            <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a>                msg <span class="op">=</span> <span class="kw">this</span><span class="op">.</span><span class="fu">queue</span><span class="op">.</span><span class="fu">take</span><span class="op">();</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span><span class="bu">InterruptedException</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a>                <span class="cf">throw</span> <span class="kw">new</span> <span class="bu">RuntimeException</span><span class="op">(</span>e<span class="op">);</span></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And then push things into the queue from another thread. Though please don't extend thread, just implement Runnable.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>record <span class="fu">Message</span><span class="op">(</span><span class="bu">String</span> contents<span class="op">)</span> <span class="op">{}</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">net</span><span class="op">.*;</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">io</span><span class="op">.*;</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">ArrayBlockingQueue</span><span class="op">;</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> <span class="bu">Handler</span> <span class="kw">implements</span> <span class="bu">Runnable</span> <span class="op">{</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="bu">Socket</span> socket <span class="op">=</span> <span class="kw">null</span><span class="op">;</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="bu">ArrayBlockingQueue</span><span class="op">&lt;</span>Message<span class="op">&gt;</span> queue<span class="op">;</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">Handler</span><span class="op">(</span><span class="bu">ArrayBlockingQueue</span><span class="op">&lt;</span>Message<span class="op">&gt;</span> queue<span class="op">,</span> <span class="bu">Socket</span> socket<span class="op">){</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">(</span><span class="st">&quot;Handler&quot;</span><span class="op">);</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">queue</span> <span class="op">=</span> queue<span class="op">;</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">socket</span> <span class="op">=</span> socket<span class="op">;</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">run</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a>        <span class="cf">while</span> <span class="op">(</span><span class="kw">true</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a>            Message msg<span class="op">;</span></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a>            <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a>                msg <span class="op">=</span> <span class="kw">this</span><span class="op">.</span><span class="fu">queue</span><span class="op">.</span><span class="fu">take</span><span class="op">();</span></span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span><span class="bu">InterruptedException</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a>                <span class="cf">throw</span> <span class="kw">new</span> <span class="bu">RuntimeException</span><span class="op">(</span>e<span class="op">);</span></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How to read a properties file</title><link>https://mccue.dev/pages/8-2-21-extract-properties</link><description></description><pubDate>Mon, 02 Aug 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How to read a properties file</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How to read a properties file</h1>
</header>
<h2 id="question-from-kiryo9472">Question from Kiryo#9472</h2>
<blockquote>
<p>i need to make that my app shows the specific value in xml file should i use scanner? or there is another way i need to extract</p>
<pre><code># Rate Exp Sp
RateXp = 4.
RateSp = 4.</code></pre>
<p>the value of for example this^</p>
<p>actually not the xml but .properities</p>
</blockquote>
<p>Get your .properties file as an input stream, then</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="dt">final</span> var properties <span class="op">=</span> <span class="kw">new</span> <span class="bu">Properties</span><span class="op">();</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="cf">try</span> <span class="op">(</span><span class="bu">InputStream</span> is <span class="op">=</span> <span class="kw">...</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    properties<span class="op">.</span><span class="fu">load</span><span class="op">(</span>is<span class="op">);</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Easy peasy, then just</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>properties<span class="op">.</span><span class="fu">getProperty</span><span class="op">(</span><span class="st">&quot;RateXp&quot;</span><span class="op">);</span></span></code></pre></div>
<p>Full example:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> record <span class="fu">Config</span><span class="op">(</span><span class="dt">int</span> rateXp<span class="op">,</span> <span class="dt">int</span> rateSp<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> Config <span class="fu">loadFromClasspath</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>        <span class="dt">final</span> var properties <span class="op">=</span> <span class="kw">new</span> <span class="bu">Properties</span><span class="op">();</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>        <span class="cf">try</span> <span class="op">(</span><span class="dt">final</span> var inputStream <span class="op">=</span> <span class="fu">getClass</span><span class="op">().</span><span class="fu">getClassLoader</span><span class="op">().</span><span class="fu">getResourceAsStream</span><span class="op">(</span><span class="st">&quot;config.properties&quot;</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>            properties<span class="op">.</span><span class="fu">load</span><span class="op">(</span>inputStream<span class="op">);</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">catch</span> <span class="op">(</span><span class="bu">IOException</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>            <span class="cf">throw</span> <span class="kw">new</span> <span class="fu">UncheckedIOException</span><span class="op">(</span>e<span class="op">);</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Config</span><span class="op">(</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Integer</span><span class="op">.</span><span class="fu">parseInt</span><span class="op">(</span>properties<span class="op">.</span><span class="fu">getProperty</span><span class="op">(</span><span class="st">&quot;RateXp&quot;</span><span class="op">)),</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>            <span class="bu">Integer</span><span class="op">.</span><span class="fu">parseInt</span><span class="op">(</span>properties<span class="op">.</span><span class="fu">getProperty</span><span class="op">(</span><span class="st">&quot;RateSp&quot;</span><span class="op">))</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">);</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How to do no more than 3 deletes a month</title><link>https://mccue.dev/pages/8-2-21-no-more-than-2-deletes-a-month</link><description></description><pubDate>Mon, 02 Aug 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How to do no more than 3 deletes a month</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How to do no more than 3 deletes a month</h1>
</header>
<h2 id="question-from-ab_al8947">Question from ab_al#8947:</h2>
<blockquote>
<p>I have a method that will check number of times user delete their tasks. Requirement includes no more than 3 deletes in a month. Can someone recommend a library to achieve this task?</p>
</blockquote>
<p>You need to record this information somewhere.</p>
<p>The "simple" solution is to record the deletions in a database and block future ones if they are up to 3 in the last month.</p>
<p>So the db can store the record of deletes and the times and then it's up to you to determine what a "month" is.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How do I extract the time from a Java Date object</title><link>https://mccue.dev/pages/8-1-21-extract-time-from-java-date-object</link><description></description><pubDate>Sun, 01 Aug 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How do I extract the time from a Java Date object</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How do I extract the time from a Java Date object</h1>
</header>
<h2 id="question-from-meeks7478">Question from Meeks#7478:</h2>
<blockquote>
<p>how can i extract the time (i.e HH:mm:ss) from a java date object?</p>
</blockquote>
<p>Take your date</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="bu">Date</span> d <span class="op">=</span> <span class="kw">new</span> <span class="bu">Date</span><span class="op">();</span></span></code></pre></div>
<p>turn it into an Instant</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="bu">Date</span> d <span class="op">=</span> <span class="kw">new</span> <span class="bu">Date</span><span class="op">();</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>Instant instant <span class="op">=</span> d<span class="op">.</span><span class="fu">toInstant</span><span class="op">();</span></span></code></pre></div>
<p>make a date time formatter</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="bu">Date</span> d <span class="op">=</span> <span class="kw">new</span> <span class="bu">Date</span><span class="op">();</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>Instant instant <span class="op">=</span> d<span class="op">.</span><span class="fu">toInstant</span><span class="op">();</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>DateTimeFormatter formatter <span class="op">=</span> DateTimeFormatter<span class="op">.</span><span class="fu">ofPattern</span><span class="op">(</span><span class="st">&quot;HH:mm:ss&quot;</span><span class="op">);</span></span></code></pre></div>
<p>interpret your instant in a time zone</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="bu">Date</span> d <span class="op">=</span> <span class="kw">new</span> <span class="bu">Date</span><span class="op">();</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>Instant instant <span class="op">=</span> d<span class="op">.</span><span class="fu">toInstant</span><span class="op">();</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>DateTimeFormatter formatter <span class="op">=</span> DateTimeFormatter<span class="op">.</span><span class="fu">ofPattern</span><span class="op">(</span><span class="st">&quot;HH:mm:ss&quot;</span><span class="op">);</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>ZonedDateTime time <span class="op">=</span> instant<span class="op">.</span><span class="fu">atZone</span><span class="op">(</span>ZoneId<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;EST&quot;</span><span class="op">));</span></span></code></pre></div>
<p>then format that with the formatter</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="bu">Date</span> d <span class="op">=</span> <span class="kw">new</span> <span class="bu">Date</span><span class="op">();</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>Instant instant <span class="op">=</span> d<span class="op">.</span><span class="fu">toInstant</span><span class="op">();</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>DateTimeFormatter formatter <span class="op">=</span> DateTimeFormatter<span class="op">.</span><span class="fu">ofPattern</span><span class="op">(</span><span class="st">&quot;HH:mm:ss&quot;</span><span class="op">);</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>ZonedDateTime time <span class="op">=</span> instant<span class="op">.</span><span class="fu">atZone</span><span class="op">(</span>ZoneId<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;EST&quot;</span><span class="op">));</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="bu">String</span> dateString <span class="op">=</span> formatter<span class="op">.</span><span class="fu">format</span><span class="op">(</span>time<span class="op">);</span></span></code></pre></div>
<p>and then just don't have a Date anymore</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>Instant instant <span class="op">=</span> Instant<span class="op">.</span><span class="fu">now</span><span class="op">();</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>DateTimeFormatter formatter <span class="op">=</span> DateTimeFormatter<span class="op">.</span><span class="fu">ofPattern</span><span class="op">(</span><span class="st">&quot;HH:mm:ss&quot;</span><span class="op">);</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>ZonedDateTime time <span class="op">=</span> instant<span class="op">.</span><span class="fu">atZone</span><span class="op">(</span>ZoneId<span class="op">.</span><span class="fu">of</span><span class="op">(</span><span class="st">&quot;EST&quot;</span><span class="op">));</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="bu">String</span> dateString <span class="op">=</span> formatter<span class="op">.</span><span class="fu">format</span><span class="op">(</span>time<span class="op">);</span></span></code></pre></div>
<blockquote>
<p>will the time still be considered a date object</p>
<p>cause my sql column is a date time type</p>
</blockquote>
<p>Is it a java.sql.Date or java.sql.TimeStamp?</p>
<p><a href="https://docs.oracle.com/javase/8/docs/api/java/sql/Timestamp.html#toInstant--">https://docs.oracle.com/javase/8/docs/api/java/sql/Timestamp.html#toInstant--</a></p>
<p><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Date.html#toInstant--">https://docs.oracle.com/javase/8/docs/api/java/util/Date.html#toInstant--</a></p>
<p>Both have a <code>toInstant</code> method which is how you can enter the realm of sane date types.</p>
<p>Both also have a <code>from(Instant)</code> (<code>java.sql.Date</code> extends <code>java.util.Date</code>).</p>
<blockquote>
<p>so when im saving to db an instant will be able to be inserted in?</p>
</blockquote>
<p>Depends on your driver, but most likely when you insert you will need to convert <code>Date.from(instant)</code>.</p>
<blockquote>
<p>i see</p>
<p>lemme try</p>
<p>thanks man</p>
</blockquote>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How do I stop a thread</title><link>https://mccue.dev/pages/8-1-21-how-to-stop-a-thread</link><description></description><pubDate>Sun, 01 Aug 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How do I stop a thread</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How do I stop a thread</h1>
</header>
<h2 id="question-from-arbee3030">Question from Arbee#3030:</h2>
<blockquote>
<p>How do i stop a thread?</p>
</blockquote>
<p><img src="/pages/8-1-21-you-dont.png"></img></p>
<blockquote>
<p>And how do I stop my bot then? lol</p>
</blockquote>
<p>You can interrupt the thread, or cancel the task and then it is up to your code to check the Thread.isInterrupted flag.</p>
<p>Some built in methods which throw interrupted exceptions will do that check for you (like those on <code>HttpClient</code>) but without shutting down you cannot force a thread to stop.</p>
<blockquote>
<p>Im kinda lost rn... how do I stop my bot without stopping the thread it is running in?</p>
</blockquote>
<p>well - you can communicate to the bot's thread</p>
<blockquote>
<p>And how do I do that?</p>
</blockquote>
<p>Sharing a reference to an <code>AtomicBoolean</code> would do the trick.</p>
<p>So if your bot has an <code>AtomicBoolean</code> it can check it occasionally to see if the value is true. If it's true, it can clean itself up - and atomic boolean is safe to change from another thread.</p>
<p>But it might be difficult depending on how your bot framework is built</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How to have a HashMap with different types as values</title><link>https://mccue.dev/pages/8-1-21-hashmap-with-different-value-types</link><description></description><pubDate>Sun, 01 Aug 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How to have a HashMap with different types as values</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How to have a HashMap with different types as values</h1>
</header>
<h2 id="question-from-fellowtomato4643">Question from FellowTomato#4643:</h2>
<blockquote>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">static</span> <span class="bu">HashMap</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">,</span> <span class="bu">Integer</span><span class="op">&gt;</span> seats <span class="op">=</span> <span class="kw">new</span> <span class="bu">HashMap</span><span class="op">&lt;&gt;(){{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>       <span class="fu">put</span><span class="op">(</span><span class="st">&quot;total_rows&quot;</span><span class="op">,</span> <span class="dv">9</span><span class="op">);</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>       <span class="fu">put</span><span class="op">(</span><span class="st">&quot;total_columns&quot;</span><span class="op">,</span> <span class="dv">9</span><span class="op">);</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>       <span class="fu">put</span><span class="op">(</span><span class="st">&quot;available_seats&quot;</span><span class="op">,</span> <span class="kw">new</span> <span class="bu">HashMap</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">,</span> <span class="bu">Integer</span><span class="op">&gt;(){{</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>           <span class="fu">put</span><span class="op">(</span><span class="st">&quot;row&quot;</span><span class="op">,</span> <span class="dv">1</span><span class="op">);</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>           <span class="fu">put</span><span class="op">(</span><span class="st">&quot;column&quot;</span><span class="op">,</span> <span class="dv">1</span><span class="op">);</span>   <span class="op">}});</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}};</span></span></code></pre></div>
<p>How should I initialize HashMap to allow several datatypes as values?</p>
<p>I want something like this in result:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;total_rows&quot;</span><span class="fu">:</span><span class="dv">5</span><span class="fu">,</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;total_columns&quot;</span><span class="fu">:</span><span class="dv">6</span><span class="fu">,</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">&quot;available_seats&quot;</span><span class="fu">:</span><span class="ot">[</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>     <span class="fu">{</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>        <span class="dt">&quot;row&quot;</span><span class="fu">:</span><span class="dv">1</span><span class="fu">,</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>        <span class="dt">&quot;column&quot;</span><span class="fu">:</span><span class="dv">1</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>     <span class="fu">}</span><span class="ot">,</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="er">...</span><span class="ot">]</span><span class="er">;</span></span></code></pre></div>
<p>Turns out, I can simply type <code>Object</code>...</p>
</blockquote>
<p>You usually want to make objects for parsing json, not Map&lt;Object,Object&gt;</p>
<blockquote>
<p>Sorry, I'm really new to Java. Can you provide an example?</p>
</blockquote>
<p>Okay so for what you have there</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>      <span class="fu">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>         <span class="dt">&quot;row&quot;</span><span class="fu">:</span><span class="dv">1</span><span class="fu">,</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>         <span class="dt">&quot;column&quot;</span><span class="fu">:</span><span class="dv">1</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>      <span class="fu">}</span><span class="er">,</span></span></code></pre></div>
<p>when we put this into Java we want to map it to a class like so</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> record <span class="fu">SeatPosition</span><span class="op">(</span><span class="dt">int</span> row<span class="op">,</span> <span class="dt">int</span> column<span class="op">)</span> <span class="op">{}</span></span></code></pre></div>
<p>and then for the whole structure</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> record <span class="fu">Theater</span><span class="op">(</span><span class="dt">int</span> totalRows<span class="op">,</span> <span class="dt">int</span> totalColumns<span class="op">,</span> <span class="bu">List</span><span class="op">&lt;</span>SeatPosition<span class="op">&gt;</span> availableSeats<span class="op">)</span> <span class="op">{}</span></span></code></pre></div>
<blockquote>
<p>Ah, you mean make a special class for a second HashMap?</p>
</blockquote>
<p>Only use a hash map if every key maps to the same thing and you don't know the set of keys ahead of time.</p>
<p>If you know the set of things <code>"total_rows"</code>, <code>"available_seats"</code> - that is your clue you should be representing things as classes.</p>
<p>records are a good default for this kind of thing. They are just a shorthand way of making a class that contains data and has methods for accessing it.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Are Functions called Methods in Java</title><link>https://mccue.dev/pages/7-31-21-are-java-methods-functions</link><description></description><pubDate>Sat, 31 Jul 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Are Functions called Methods in Java</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Are Functions called Methods in Java</h1>
</header>
<h2 id="question-from-em0694">Question from Em.#0694</h2>
<blockquote>
<p>Hi</p>
<p>Are functions called methods in Java?</p>
</blockquote>
<p>Yes, but the caveat is that you don't have true "free standing" functions.</p>
<p>so in python</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> f(x, y):</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> x <span class="op">+</span> y</span></code></pre></div>
<p>This is a function, it is its own thing. In Java "methods" have to "belong" to something either instances of a class or to the class itself.</p>
<blockquote>
<p>Oh</p>
<p>yeah</p>
<p>that makes sense</p>
</blockquote>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Thing <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="dt">int</span> <span class="fu">f</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x <span class="op">+</span> y<span class="op">;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>so this <code>f</code> function in python, translated to java has to "belong" to some class as a "static method".</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>What would define FP in Java?</title><link>https://mccue.dev/pages/7-28-21-what-would-define-fp-in-java</link><description></description><pubDate>Wed, 28 Jul 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>What would define FP in Java?</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">What would define FP in Java?</h1>
</header>
<h2 id="question-from-fast-q2816">Question from Fast Q#2816</h2>
<blockquote>
<p>What would define FP in java? I usually hear it thrown around when talking about streams/ functional interfaces</p>
</blockquote>
<p>Let me write out some examples let me write out some examples</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> BankAccount <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">int</span> balance<span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">BankAccount</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">balance</span> <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">deposit</span><span class="op">(</span><span class="dt">int</span> amt<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>amt <span class="op">&lt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>            <span class="cf">throw</span> <span class="kw">new</span> <span class="bu">IllegalArgumentException</span><span class="op">(</span><span class="st">&quot;amt must be non-negative&quot;</span><span class="op">);</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">balance</span> <span class="op">+=</span> amt<span class="op">;</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">int</span> <span class="fu">withdraw</span><span class="op">(</span><span class="dt">int</span> amt<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>amt <span class="op">&lt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>            <span class="cf">throw</span> <span class="kw">new</span> <span class="bu">IllegalArgumentException</span><span class="op">(</span><span class="st">&quot;amt must be non-negative&quot;</span><span class="op">);</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span><span class="kw">this</span><span class="op">.</span><span class="fu">balance</span> <span class="op">&lt;</span> amt<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>                <span class="dt">int</span> balance <span class="op">=</span> <span class="kw">this</span><span class="op">.</span><span class="fu">balance</span><span class="op">;</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>                <span class="kw">this</span><span class="op">.</span><span class="fu">balance</span> <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> balance<span class="op">;</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>            <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a>                <span class="kw">this</span><span class="op">.</span><span class="fu">balance</span> <span class="op">-=</span> amt<span class="op">;</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> amt<span class="op">;</span></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">int</span> <span class="fu">getBalance</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">balance</span><span class="op">;</span></span>
<span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-37"><a href="#cb1-37" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Okay real basic class here i just whipped up. Take a moment to read it and show me what an example usage might be.</p>
<p>(this isn't FP, this is normal)</p>
<p>(i'm also sure there is a bug, but ignore it)</p>
<blockquote>
<p>So an example like:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>BankAccount myTaxHaven <span class="op">=</span> <span class="kw">new</span> <span class="fu">BankAccount</span><span class="op">();</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>myTaxHaven<span class="op">.</span><span class="fu">deposit</span><span class="op">(</span><span class="dv">500</span><span class="op">);</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>myTaxHaven<span class="op">.</span><span class="fu">withdraw</span><span class="op">(</span><span class="dv">250</span><span class="op">);</span></span></code></pre></div>
<p>?</p>
</blockquote>
<p>sure.</p>
<p>Mutable bank account - you can take money in and out.</p>
<p>Now here is the challenge. We have a new requirement. We want to know the state of every bank account at every time.</p>
<p>So somewhere in the code there is a map of user id to a map of timestamp to bank account. (does that parse?)</p>
<blockquote>
<p>transaction timestamp?</p>
</blockquote>
<p>yeah</p>
<blockquote>
<p>yep I'm tracking</p>
</blockquote>
<p>But in order to support that use case we can't change bank accounts directly like that.</p>
<p>Or rather, one way to support it is to make the bank account immutable.</p>
<blockquote>
<p>Wait, why can't we change bank accounts directly?</p>
</blockquote>
<p>lets say we had this</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="bu">Map</span><span class="op">&lt;</span>Instant<span class="op">,</span> BankAccount<span class="op">&gt;</span> bankAccountAtTime <span class="op">=</span> <span class="kw">new</span> <span class="bu">HashMap</span><span class="op">&lt;&gt;();</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>BankAccount myTaxHaven <span class="op">=</span> <span class="kw">new</span> <span class="fu">BankAccount</span><span class="op">();</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>bankAccountAtTime<span class="op">.</span><span class="fu">put</span><span class="op">(</span>Instant<span class="op">.</span><span class="fu">now</span><span class="op">(),</span> myTaxHaven<span class="op">);</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>myTaxHaven<span class="op">.</span><span class="fu">deposit</span><span class="op">(</span><span class="dv">400</span><span class="op">);</span> <span class="co">// oh no, our history is messed up</span></span></code></pre></div>
<blockquote>
<p>Why is our history messed up?</p>
<p>so the fact that we mutate our bank account after depositing? That makes me question the original claim that this is a solution</p>
<p>I mean yeah we're mapping to the bank accounts, not a specific balance of the bank account in that time</p>
</blockquote>
<p>My framing here is a bit messed up. I guess I'm saying if they were immutable then this kind of solution would work.</p>
<blockquote>
<p>If they were immutable, deposit wouldn't even do the same thing though</p>
</blockquote>
<p>Thats correct.</p>
<p>So how would we re-write the code such that we support all the same use cases but our contract doesn't have any mutating methods.</p>
<blockquote>
<p>Keep a list of &lt;Instant, Balance&gt; or &lt;Instant, Transaction&gt;(which contains before/after information) Or a map, but some data structure</p>
</blockquote>
<p>I mean just the BankAccount class.</p>
<blockquote>
<p>deposit/withdraw could return a Balance or Transaction object, but then I think our paradigm doesn't even make sense</p>
</blockquote>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> BankAccount <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="dt">int</span> balance<span class="op">;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">BankAccount</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">(</span><span class="dv">0</span><span class="op">);</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">BankAccount</span><span class="op">(</span><span class="dt">int</span> balance<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">balance</span> <span class="op">=</span> balance<span class="op">;</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> BankAccount <span class="fu">deposit</span><span class="op">(</span><span class="dt">int</span> amt<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>amt <span class="op">&lt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>            <span class="cf">throw</span> <span class="kw">new</span> <span class="bu">IllegalArgumentException</span><span class="op">(</span><span class="st">&quot;amt must be non-negative&quot;</span><span class="op">);</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">new</span> <span class="fu">BankAccount</span><span class="op">(</span><span class="kw">this</span><span class="op">.</span><span class="fu">balance</span> <span class="op">-</span> amt<span class="op">);</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a>    record <span class="fu">WithdrawalResult</span><span class="op">(</span>BankAccount account<span class="op">,</span> <span class="dt">int</span> withdrawn<span class="op">)</span> <span class="op">{}</span></span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> WithdrawalResult <span class="fu">withdraw</span><span class="op">(</span><span class="dt">int</span> amt<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>amt <span class="op">&lt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true" tabindex="-1"></a>            <span class="cf">throw</span> <span class="kw">new</span> <span class="bu">IllegalArgumentException</span><span class="op">(</span><span class="st">&quot;amt must be non-negative&quot;</span><span class="op">);</span></span>
<span id="cb4-26"><a href="#cb4-26" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb4-27"><a href="#cb4-27" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb4-28"><a href="#cb4-28" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span><span class="kw">this</span><span class="op">.</span><span class="fu">balance</span> <span class="op">&lt;</span> amt<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-29"><a href="#cb4-29" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="kw">new</span> <span class="fu">WithdrawalResult</span><span class="op">(</span><span class="kw">new</span> <span class="fu">BankAccount</span><span class="op">(</span><span class="dv">0</span><span class="op">),</span> <span class="kw">this</span><span class="op">.</span><span class="fu">balance</span><span class="op">);</span></span>
<span id="cb4-30"><a href="#cb4-30" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb4-31"><a href="#cb4-31" aria-hidden="true" tabindex="-1"></a>            <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb4-32"><a href="#cb4-32" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="kw">new</span> <span class="fu">WithdrawalResult</span><span class="op">(</span><span class="kw">new</span> <span class="fu">BankAccount</span><span class="op">(</span><span class="kw">this</span><span class="op">.</span><span class="fu">balance</span> <span class="op">-</span> amt<span class="op">),</span> amt<span class="op">);</span></span>
<span id="cb4-33"><a href="#cb4-33" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb4-34"><a href="#cb4-34" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb4-35"><a href="#cb4-35" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-36"><a href="#cb4-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-37"><a href="#cb4-37" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">int</span> <span class="fu">getBalance</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb4-38"><a href="#cb4-38" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">balance</span><span class="op">;</span></span>
<span id="cb4-39"><a href="#cb4-39" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-40"><a href="#cb4-40" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>A bank account is a full history - always. There is the current state of it and past states of it, but they are all equally real "accounts".</p>
<blockquote>
<p>right, that's a fine way of viewing it yeah</p>
</blockquote>
<p>It's like numbers. Imagine if this worked</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="bu">Integer</span> i <span class="op">=</span> <span class="dv">5</span><span class="op">;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>i<span class="op">.</span><span class="fu">subtractOne</span><span class="op">();</span> <span class="co">// i is now 4</span></span></code></pre></div>
<p>the <em>value</em> of 5 should be independent from the <em>identity</em> you assign that value. If that isn't the case - for numbers - it feels super wierd</p>
<blockquote>
<p>Is the main point that mutability is inherently dangerous?</p>
</blockquote>
<p>Kinda. there are a lot of downsides to it - it's a lot harder to multithread is a big one.</p>
<p>And you can always <em>get it back</em> if you need to.</p>
<blockquote>
<p>Yeah this makes sense I definitely believe in keeping an immutable history for anything important</p>
</blockquote>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How does this cause deadlock</title><link>https://mccue.dev/pages/7-19-21-how-does-this-cause-deadlock</link><description></description><pubDate>Mon, 19 Jul 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How does this cause deadlock</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How does this cause deadlock</h1>
</header>
<h2 id="question-from-blindspot234418">Question from blindspot23#4418</h2>
<blockquote>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Deadlock <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="kw">class</span> Friend <span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">final</span> <span class="bu">String</span> name<span class="op">;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="fu">Friend</span><span class="op">(</span><span class="bu">String</span> name<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">name</span> <span class="op">=</span> name<span class="op">;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="bu">String</span> <span class="fu">getName</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">name</span><span class="op">;</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="kw">synchronized</span> <span class="dt">void</span> <span class="fu">bow</span><span class="op">(</span>Friend bower<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>            <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">format</span><span class="op">(</span><span class="st">&quot;</span><span class="sc">%s</span><span class="st">: </span><span class="sc">%s</span><span class="st">&quot;</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>                <span class="op">+</span> <span class="st">&quot;  has bowed to me!</span><span class="sc">%n</span><span class="st">&quot;</span><span class="op">,</span> </span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>                <span class="kw">this</span><span class="op">.</span><span class="fu">name</span><span class="op">,</span> bower<span class="op">.</span><span class="fu">getName</span><span class="op">());</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>            bower<span class="op">.</span><span class="fu">bowBack</span><span class="op">(</span><span class="kw">this</span><span class="op">);</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="kw">synchronized</span> <span class="dt">void</span> <span class="fu">bowBack</span><span class="op">(</span>Friend bower<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>            <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">format</span><span class="op">(</span><span class="st">&quot;</span><span class="sc">%s</span><span class="st">: </span><span class="sc">%s</span><span class="st">&quot;</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>                <span class="op">+</span> <span class="st">&quot; has bowed back to me!</span><span class="sc">%n</span><span class="st">&quot;</span><span class="op">,</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>                <span class="kw">this</span><span class="op">.</span><span class="fu">name</span><span class="op">,</span> bower<span class="op">.</span><span class="fu">getName</span><span class="op">());</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>        <span class="dt">final</span> Friend alphonse <span class="op">=</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="fu">Friend</span><span class="op">(</span><span class="st">&quot;Alphonse&quot;</span><span class="op">);</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>        <span class="dt">final</span> Friend gaston <span class="op">=</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>            <span class="kw">new</span> <span class="fu">Friend</span><span class="op">(</span><span class="st">&quot;Gaston&quot;</span><span class="op">);</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a>        <span class="kw">new</span> <span class="bu">Thread</span><span class="op">(</span><span class="kw">new</span> <span class="bu">Runnable</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a>            <span class="kw">public</span> <span class="dt">void</span> <span class="fu">run</span><span class="op">()</span> <span class="op">{</span> alphonse<span class="op">.</span><span class="fu">bow</span><span class="op">(</span>gaston<span class="op">);</span> <span class="op">}</span></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a>        <span class="op">}).</span><span class="fu">start</span><span class="op">();</span></span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a>        <span class="kw">new</span> <span class="bu">Thread</span><span class="op">(</span><span class="kw">new</span> <span class="bu">Runnable</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a>            <span class="kw">public</span> <span class="dt">void</span> <span class="fu">run</span><span class="op">()</span> <span class="op">{</span> gaston<span class="op">.</span><span class="fu">bow</span><span class="op">(</span>alphonse<span class="op">);</span> <span class="op">}</span></span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a>        <span class="op">}).</span><span class="fu">start</span><span class="op">();</span></span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This is the example given for deadlock in java docs. I presume that inside the bow method, the last line causes the deadlock. But how? We access the bowBack method using the object and not the thread. Then why do we get a deadlock.</p>
</blockquote>
<p>Those synchronized blocks basically make this</p>
<pre><code>Thread 1:
  - lock gaston
  - lock alphonse
  - unlock alphonse
  - unlock gaston
Thread 2:
  - lock alphonse
  - lock gaston
  - unlock gaston
  - unlock alphonse</code></pre>
<p>now we can write those out</p>
<pre><code>1. lock gaston
1. lock alphonse
1. unlock alphonse
1. unlock gaston
2. lock alphonse
2. lock gaston
2. unlock gaston
2. unlock alphonse</code></pre>
<p>and intermesh them like so</p>
<p>actually - exercise for you, how can those get ordered in a way that causes deadlock</p>
<blockquote>
<p>Because bowBack method invocation inside bow method tries to get the lock of gaston, while a thread that tries to get the lock on gaston is already blocked and queued?</p>
</blockquote>
<pre><code>1. lock gaston
2. lock alphonse
1. lock alphonse
2. lock gaston
1. unlock alphonse
1. unlock gaston
2. unlock gaston
2. unlock alphonse</code></pre>
<p>Basically this. I think your words are right.</p>
<blockquote>
<p>Alright then, Thank you for the help.</p>
</blockquote>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Array basics</title><link>https://mccue.dev/pages/7-16-21-array-basics</link><description></description><pubDate>Fri, 16 Jul 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Array basics</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Array basics</h1>
</header>
<h2 id="question-from-junk1089">Question from junk#1089</h2>
<blockquote>
<p>the question ask for:</p>
<p>user input a number, n then save into array. after that, display the numbers out according to sequence</p>
</blockquote>
<p>An array is a fixed size container of elements</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span><span class="op">[]</span> numbers <span class="op">=</span> <span class="kw">new</span> <span class="dt">int</span><span class="op">[</span><span class="dv">10</span><span class="op">];</span></span></code></pre></div>
<p>so here I made an array of 10 integers. They will all start at 0, and I can set</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>numbers<span class="op">[</span><span class="dv">5</span><span class="op">]</span> <span class="op">=</span> <span class="dv">123</span><span class="op">;</span></span></code></pre></div>
<p>any number in the array and get</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> i <span class="op">=</span> numbers<span class="op">[</span><span class="dv">2</span><span class="op">];</span></span></code></pre></div>
<p>any number in the array.</p>
<p>But if I try to get a number outside of the bounds of the array (in this case 0-9)</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> j <span class="op">=</span> numbers<span class="op">[</span><span class="dv">10</span><span class="op">];</span></span></code></pre></div>
<p>it will crash. so if a user inputs a number and you want to save that number into an array you need to</p>
<ol type="1">
<li>Know what "place" in the array you are at</li>
<li>Know whether you can expect a certain number of elements because an array, like I said, is fixed size</li>
</ol>
<blockquote>
<p>thank you so much</p>
</blockquote>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Why is my List code crashing</title><link>https://mccue.dev/pages/7-10-21-caveats-with-arrays-as-list</link><description></description><pubDate>Sat, 10 Jul 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Why is my List code crashing</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Why is my List code crashing</h1>
</header>
<h2 id="question-from-los-feliz2763">Question from Los Feliz#2763</h2>
<blockquote>
<p>is there a way to convert List&lt;String&gt; to ArrayList&lt;Object&gt;, and vice versa?</p>
<p>here's the full picture:</p>
<p>I have a String arr[].</p>
<p>I convert it into List&lt;String&gt; so I can show its content on Android app.</p>
<p>But then for performing filter for search purposes, I require an ArrayList of objects.</p>
<p>So I wanna convert my List&lt;String&gt; into an ArrayList&lt;Object&gt;, because my adapter is set to accept ArrayList as its params.</p>
<p>this is how i converted.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="bu">String</span> arr<span class="op">[];</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="bu">List</span><span class="op">&amp;</span>lt<span class="op">;</span><span class="bu">String</span><span class="op">&amp;</span>gt<span class="op">;</span> list1<span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>list1 <span class="op">=</span> <span class="bu">Arrays</span><span class="op">.</span><span class="fu">asList</span><span class="op">(</span><span class="fu">getResources</span><span class="op">().</span><span class="fu">getStringArray</span><span class="op">(</span>R<span class="op">.</span><span class="fu">array</span><span class="op">.</span><span class="fu">string</span><span class="op">-</span>array<span class="er">&#39;</span>s name<span class="op">));</span></span></code></pre></div>
<p>thought i know what i'm doing until i saw the app crash with what i have now.</p>
<pre><code>Unknown bits set in runtime_flags: 0x8000
E/libc: Access denied finding property &amp;quot;ro.serialno&amp;quot;
E/AndroidRuntime: FATAL EXCEPTION: main

at java.util.AbstractList.remove(AbstractList.java:161)
at java.util.AbstractList$Itr.remove(AbstractList.java:374)
at java.util.AbstractList.removeRange(AbstractList.java:571)
at java.util.AbstractList.clear(AbstractList.java:234)
at com.example.cspeaks.MyAdapter$2.publishResults(MyAdapter.java:105)
at android.widget.Filter$ResultsHandler.handleMessage(Filter.java:284)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
```.</code></pre>
</blockquote>
<p>ohhh. wrap your <code>Arrays.asList(...)</code> with <code>new ArrayList&lt;&gt;(Arrays.asList(...))</code> that <em>might</em> help. IDK though that message is horrific.</p>
<blockquote>
<p>OMGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG @emccue YOU ARE THE MAN! JESUS CHRIST! THANK YOUUUUUUUUUUUUUUUUUUUUU</p>
</blockquote>
<p>Okay don't leave yet. I want you to understand why that helped.</p>
<blockquote>
<p><img src="/pages/7-10-21-all-ears.gif"></img></p>
</blockquote>
<p>List is an interface that has methods that read from a list (like <code>.get</code>) and methods that alter a list (like <code>.remove</code>).</p>
<p>An implementation of that interface like <code>ArrayList</code> supports all the methods. You can get elements, add elements, and remove elements.</p>
<p>But there are a bunch of methods in the JDK that return lists that are unmodifiable. <code>Arrays.asList</code> is one of those, because the purpose of it is to be a list "view" onto an array.</p>
<p><img src="/pages/7-10-21-javadoc.png"></img></p>
<blockquote>
<p>ooooooo. So in other words, when we have Arryas.asList, if we want to make changes to the array, we must change it to arraylist</p>
</blockquote>
<p>That doesn't parse for me, Arrays are their own things.</p>
<p>So if you have a <code>String[]</code>, that is a fixed size collection. It does not implement the List interface.</p>
<p><code>Arrays.asList(..)</code> is a way you can take a<code>String[]</code> and get a <code>List&lt;String&gt;</code>, but the <code>List</code> you get doesn't support adding or removing elements.</p>
<p>If you want to add or remove elements from that list you need to copy its contents into a list that supports that.</p>
<blockquote>
<p>OMG. i learned this hard way. Almost 20 hours.</p>
</blockquote>
<p><code>ArrayList</code> is the most common one and a good default. <code>List.of(...)</code> and <code>.toList()</code> on a <code>Stream</code> also give you unmodifiable lists - though those ones don't support setting elements in place either.</p>
<p>Its annoying, but you just need to be aware of it. If you are in doubt, copy it into an <code>ArrayList</code> and you know you can do everything.</p>
<blockquote>
<p>yeah. lesson learned. from now on Im coppying every instance of List&lt;&gt; into an arraylist</p>
</blockquote>
<p>Thats one approach.</p>
<p>In other contexts that can be called "defensive copying" - Its a generally good technique if you are working with mutable structures though overkill if you are the one making and working with all the instances (potentially).</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Why do we throw exceptions?</title><link>https://mccue.dev/pages/7-9-21-why-do-we-throw-an-exception</link><description></description><pubDate>Fri, 09 Jul 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Why do we throw exceptions?</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Why do we throw exceptions?</h1>
</header>
<h2 id="question-from-blindspot234418">Question from blindspot23#4418</h2>
<blockquote>
<p>Why do we throw an exception when try and catch can handle it?</p>
</blockquote>
<p>The use case is for "exceptional conditions". Like if you write a library that asks google for search results that can always fail because it goes over the network and you use try catch to handle it, but sometimes either</p>
<ol type="1">
<li>you can't handle it and you need to crash</li>
<li>you don't want to handle it and prefer to crash</li>
<li>It makes sense to "bubble" the exception up multiple layers</li>
</ol>
<p>Making it more complicated - there are actually 2 "kinds" of exceptions in Java, checked and unchecked ones.</p>
<p>Checked exceptions like <code>IOException</code> you always have to handle either by doing some behavior or rethrowing.</p>
<p>Unchecked exceptions like <code>RuntimeException</code> the language doesn't make you handle so generally those are used for situations where you don't think people will want to try to recover.</p>
<p>It's all also really abstract until you try writing some code that uses or works with them. (and also really frustrating because not even the standard library does exceptions "right" always)</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How do I break correctly</title><link>https://mccue.dev/pages/7-7-21-how-do-i-break-correctly</link><description></description><pubDate>Wed, 07 Jul 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How do I break correctly</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How do I break correctly</h1>
</header>
<h2 id="question-from-quadzilla9639">Question from Quadzilla#9639</h2>
<blockquote>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Pyramid <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> s <span class="op">=</span> <span class="dv">50</span><span class="op">;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">while</span> <span class="op">(</span><span class="kw">true</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>            s <span class="op">+=</span> <span class="dv">50</span><span class="op">;</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>s <span class="op">&gt;</span> <span class="dv">50</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>                <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>s<span class="op">);</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>                s <span class="op">=</span> <span class="dv">200</span><span class="op">;</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>                <span class="cf">break</span><span class="op">;</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>            <span class="cf">while</span> <span class="op">(</span>s <span class="op">&gt;=</span> <span class="dv">200</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>                <span class="cf">break</span><span class="op">;</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>How can I add in a break to prevent the numbers from going to 20,000 in the terminal and beyond. Am I applying break correctly? I adapted the code from a java forum that printed a pyramid &amp; thought today is the day to apply the break statement. s was changed by me to integer rather than string.</p>
</blockquote>
<p>So first</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> s <span class="op">=</span> <span class="dv">50</span><span class="op">;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>        <span class="cf">while</span> <span class="op">(</span><span class="kw">true</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>            s <span class="op">+=</span> <span class="dv">50</span><span class="op">;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>s <span class="op">&gt;</span> <span class="dv">50</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>                <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>s<span class="op">);</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>                s <span class="op">=</span> <span class="dv">200</span><span class="op">;</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>                <span class="cf">break</span><span class="op">;</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>            <span class="cf">while</span> <span class="op">(</span>s <span class="op">&gt;=</span> <span class="dv">200</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>                <span class="cf">break</span><span class="op">;</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span></code></pre></div>
<p>This else block here where you set s to 200 will never run.</p>
<p><code>s</code> starts out at 50, you immediately add 50 to it, So it's always above 50 and you never set it to anything lower.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> s <span class="op">=</span> <span class="dv">50</span><span class="op">;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>        <span class="cf">while</span> <span class="op">(</span><span class="kw">true</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>            s <span class="op">+=</span> <span class="dv">50</span><span class="op">;</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>s <span class="op">&gt;</span> <span class="dv">50</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>                <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>s<span class="op">);</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> </span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>            <span class="cf">while</span> <span class="op">(</span>s <span class="op">&gt;=</span> <span class="dv">200</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>                <span class="cf">break</span><span class="op">;</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span></code></pre></div>
<p>Now for that last while block with the break.</p>
<p><code>break</code> is a "terminal" action. You will exit your loop if you do it. And because you nest that other loop you only break out of the <code>while (s &gt;= 200)</code> loop, not the <code>while (true)</code> loop.</p>
<p>So what you want isn't a <code>while</code>, it's an <code>if</code>.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> s <span class="op">=</span> <span class="dv">50</span><span class="op">;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>        <span class="cf">while</span> <span class="op">(</span><span class="kw">true</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>            s <span class="op">+=</span> <span class="dv">50</span><span class="op">;</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>s <span class="op">&gt;</span> <span class="dv">50</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>                <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>s<span class="op">);</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> </span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>s <span class="op">&gt;=</span> <span class="dv">200</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>                <span class="cf">break</span><span class="op">;</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How do I inject dependencies into Enums</title><link>https://mccue.dev/pages/7-6-21-javax-inject-into-enums</link><description></description><pubDate>Tue, 06 Jul 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How do I inject dependencies into Enums</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How do I inject dependencies into Enums</h1>
</header>
<h2 id="question-from-chem9771">Question from Chem#9771</h2>
<blockquote>
<p>In <code>javax</code>, if you use <code>@Inject</code> into a constructor, but you have instances where you can't pass those parameters, what do you do?</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="at">@ApplicationScoped</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> JavascriptLanguageExecutor <span class="kw">extends</span> LanguageExecutor <span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>   <span class="at">@Inject</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>   <span class="fu">JavascriptLanguageExecutor</span><span class="op">(</span>EngineInstance engine<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>       <span class="kw">super</span><span class="op">(</span>Language<span class="op">.</span><span class="fu">JAVASCRIPT</span><span class="op">,</span> engine<span class="op">.</span><span class="fu">instance</span><span class="op">);</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>   <span class="op">}</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">enum</span> Language <span class="op">{</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>   <span class="fu">JAVASCRIPT</span><span class="op">(</span><span class="st">&quot;js&quot;</span><span class="op">);</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>   <span class="kw">public</span> LanguageExecutor <span class="fu">getExecutor</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>       <span class="cf">return</span> <span class="cf">switch</span> <span class="op">(</span><span class="kw">this</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>           <span class="co">// THIS NEEDS &quot;EngineInstance&quot; BUT I DON&#39;T HAVE ABILITY TO &quot;@Inject&quot; INTO ENUMS</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>           <span class="cf">case</span> JAVASCRIPT <span class="op">-&gt;</span> <span class="kw">new</span> <span class="fu">JavascriptLanguageExecutor</span><span class="op">();</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>       <span class="op">};</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>   <span class="op">}</span></span></code></pre></div>
<p>So here this <code>EngineInstance</code> is available via injection in the app but you can't use this inside of enums I think, and so I can't actually instantiate the class there.</p>
<p>Could I move it out of the constructor and do a field injection</p>
</blockquote>
<p>In that case, you need to pass an EngineInstance.</p>
<p>Sounds dumb, but yeah. Ignore all the javax requirements for a second, since they aren't super relevant.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> JavascriptLanguageExecutor <span class="kw">extends</span> LanguageExecutor <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="fu">JavascriptLanguageExecutor</span><span class="op">(</span>EngineInstance engine<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">(</span>Language<span class="op">.</span><span class="fu">JAVASCRIPT</span><span class="op">,</span> engine<span class="op">.</span><span class="fu">instance</span><span class="op">);</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>What you want is, effectively, a map of Language -&gt; Executor. So just make one.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>var executors <span class="op">=</span> <span class="kw">new</span> <span class="bu">EnumMap</span><span class="op">&lt;</span>Language<span class="op">,</span> LanguageExecutor<span class="op">&gt;(</span><span class="kw">...</span><span class="op">);</span></span></code></pre></div>
<p>And then pass it around where you need it.</p>
<p>There are more options but generally speaking Java is structured in a way where passing the thing is the path of least resistance. Unless you made your LanguageExecutors work with the service provider stuff, but that's somewhat niche (for application code).</p>
<p>Im not gonna pretend you can't also have a static map and fill it up with instances - you can. Just then you need to be careful of when it is hydrated vs. uninitialized and make sure to synchronize if you need to etc.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How to execute code from a client side app</title><link>https://mccue.dev/pages/7-4-21-how-to-run-code-from-the-client</link><description></description><pubDate>Sun, 04 Jul 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How to execute code from a client side app</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How to execute code from a client side app</h1>
</header>
<blockquote>
<p>Is it possible to write complex code (like instantiating an object and use the stream API) in string then parse it using something like spring language expression? Basically what I'm trying to do is to write code from the client side in string format then find a way to parse it and execute it on the backend side. From a business use case what I want to do is write some code to out put something and simply store it in a column field named "result".</p>
<p>Someone replied to me before and said it's doable but I had to abandon the chat</p>
</blockquote>
<p>If you abandon Java you can do this with something you can sandbox in the jvm, like possibly nashorn or my pref. - SCI.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="bu">String</span> expressionStr <span class="op">=</span> <span class="st">&quot;&quot;&quot;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="op">(</span>let <span class="op">[</span>customer<span class="op">-</span><span class="dv">1</span> <span class="op">(</span>Customer<span class="op">.</span> <span class="st">&quot;Mike&quot;</span> <span class="dv">9</span><span class="op">)</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>      customer<span class="op">-</span><span class="dv">2</span> <span class="op">(</span>Customer<span class="op">.</span> <span class="st">&quot;Ted&quot;</span> <span class="dv">20</span><span class="op">)</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>      customers<span class="op">.</span> <span class="op">[</span>customer<span class="op">-</span><span class="dv">1</span> customer<span class="op">-</span><span class="dv">2</span><span class="op">]]</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">(-&gt;&gt;</span> customers</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>       <span class="op">(</span><span class="fu">filter</span> <span class="op">(</span>fn <span class="op">[</span>customer<span class="op">]</span> <span class="op">(=</span> <span class="st">&quot;Mike&quot;</span> <span class="op">(.</span><span class="fu">getName</span> customer<span class="op">))))</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>       <span class="op">(</span>first<span class="op">)))</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;&quot;&quot;</span></span></code></pre></div>
<p>Then evaluate that in SCI.</p>
<p><a href="https://github.com/borkdude/sci">https://github.com/borkdude/sci</a></p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>IFn eval <span class="op">=</span> Clojure<span class="op">.</span><span class="fu">read</span><span class="op">(</span><span class="st">&quot;sci.core&quot;</span><span class="op">,</span> <span class="st">&quot;eval-string&quot;</span><span class="op">);</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>Customer customer <span class="op">=</span> <span class="op">(</span>Customer<span class="op">)</span> eval<span class="op">.</span><span class="fu">invoke</span><span class="op">(</span>expressionStr<span class="op">);</span></span></code></pre></div>
<p>and to give it sandboxed access to your classes, probably do this</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>IFn symbol <span class="op">=</span> Clojure<span class="op">.</span><span class="fu">read</span><span class="op">(</span><span class="st">&quot;clojure.core&quot;</span><span class="op">,</span> <span class="st">&quot;symbol&quot;</span><span class="op">);</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>IFn keyword <span class="op">=</span> Clojure<span class="op">.</span><span class="fu">read</span><span class="op">(</span><span class="st">&quot;clojure.core&quot;</span><span class="op">,</span> <span class="st">&quot;keyword&quot;</span><span class="op">);</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>IFn eval <span class="op">=</span> Clojure<span class="op">.</span><span class="fu">read</span><span class="op">(</span><span class="st">&quot;sci.core&quot;</span><span class="op">,</span> <span class="st">&quot;eval-string&quot;</span><span class="op">);</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>Customer customer <span class="op">=</span> <span class="op">(</span>Customer<span class="op">)</span> eval<span class="op">.</span><span class="fu">invoke</span><span class="op">(</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    expressionStr<span class="op">,</span> </span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Map</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>keyword<span class="op">.</span><span class="fu">invoke</span><span class="op">(</span><span class="st">&quot;classes&quot;</span><span class="op">),</span> <span class="bu">Map</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span>symbol<span class="op">.</span><span class="fu">invoke</span><span class="op">(</span><span class="st">&quot;Customer&quot;</span><span class="op">),</span> Customer<span class="op">.</span><span class="fu">class</span><span class="op">))</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="op">);</span></span></code></pre></div>
<p>Full example if you have clojure and sci included in your project</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">clojure</span><span class="op">.</span><span class="im">java</span><span class="op">.</span><span class="im">api</span><span class="op">.</span><span class="im">Clojure</span><span class="op">;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">clojure</span><span class="op">.</span><span class="im">lang</span><span class="op">.</span><span class="im">IFn</span><span class="op">;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">Map</span><span class="op">;</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> SciTest <span class="op">{</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">SciTest</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">static</span> <span class="dt">final</span> IFn REQUIRE<span class="op">;</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">static</span> <span class="dt">final</span> IFn SYMBOL<span class="op">;</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">static</span> <span class="dt">final</span> IFn KEYWORD<span class="op">;</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">static</span> <span class="dt">final</span> IFn EVAL_STRING<span class="op">;</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>    <span class="dt">static</span> <span class="op">{</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>        REQUIRE <span class="op">=</span> Clojure<span class="op">.</span><span class="fu">var</span><span class="op">(</span><span class="st">&quot;clojure.core&quot;</span><span class="op">,</span> <span class="st">&quot;require&quot;</span><span class="op">);</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>        SYMBOL <span class="op">=</span> Clojure<span class="op">.</span><span class="fu">var</span><span class="op">(</span><span class="st">&quot;clojure.core&quot;</span><span class="op">,</span> <span class="st">&quot;symbol&quot;</span><span class="op">);</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>        KEYWORD <span class="op">=</span> Clojure<span class="op">.</span><span class="fu">var</span><span class="op">(</span><span class="st">&quot;clojure.core&quot;</span><span class="op">,</span> <span class="st">&quot;keyword&quot;</span><span class="op">);</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a>        REQUIRE<span class="op">.</span><span class="fu">invoke</span><span class="op">(</span>Clojure<span class="op">.</span><span class="fu">read</span><span class="op">(</span><span class="st">&quot;sci.core&quot;</span><span class="op">));</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a>        EVAL_STRING <span class="op">=</span> Clojure<span class="op">.</span><span class="fu">var</span><span class="op">(</span><span class="st">&quot;sci.core&quot;</span><span class="op">,</span> <span class="st">&quot;eval-string&quot;</span><span class="op">);</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> record <span class="fu">Thing</span><span class="op">(</span><span class="dt">int</span> x<span class="op">)</span> <span class="op">{}</span></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-26"><a href="#cb4-26" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>EVAL_STRING<span class="op">.</span><span class="fu">invoke</span><span class="op">(</span></span>
<span id="cb4-27"><a href="#cb4-27" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;&quot;&quot;</span></span>
<span id="cb4-28"><a href="#cb4-28" aria-hidden="true" tabindex="-1"></a>                <span class="op">(</span>Thing<span class="op">.</span> <span class="dv">10</span><span class="op">)</span></span>
<span id="cb4-29"><a href="#cb4-29" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;&quot;&quot;,</span></span>
<span id="cb4-30"><a href="#cb4-30" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Map</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb4-31"><a href="#cb4-31" aria-hidden="true" tabindex="-1"></a>                        KEYWORD<span class="op">.</span><span class="fu">invoke</span><span class="op">(</span><span class="st">&quot;classes&quot;</span><span class="op">),</span></span>
<span id="cb4-32"><a href="#cb4-32" aria-hidden="true" tabindex="-1"></a>                        <span class="bu">Map</span><span class="op">.</span><span class="fu">of</span><span class="op">(</span></span>
<span id="cb4-33"><a href="#cb4-33" aria-hidden="true" tabindex="-1"></a>                            SYMBOL<span class="op">.</span><span class="fu">invoke</span><span class="op">(</span><span class="st">&quot;Thing&quot;</span><span class="op">),</span> Thing<span class="op">.</span><span class="fu">class</span></span>
<span id="cb4-34"><a href="#cb4-34" aria-hidden="true" tabindex="-1"></a>                        <span class="op">)</span></span>
<span id="cb4-35"><a href="#cb4-35" aria-hidden="true" tabindex="-1"></a>                <span class="op">)</span></span>
<span id="cb4-36"><a href="#cb4-36" aria-hidden="true" tabindex="-1"></a>        <span class="op">));</span></span>
<span id="cb4-37"><a href="#cb4-37" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-38"><a href="#cb4-38" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<blockquote>
<p>Will take a look, thanks!</p>
</blockquote>
<p>Curious what the actual requirement here is though. Since this isn't exactly super duper safe to do even with the sandboxing. They can still OOM your machine or whatever.</p>
<blockquote>
<p>Requirement isn't fully clear but basically when creating a new entity record, there's a "result" field where the end user wants to write some code or formula based on other fields of the entity, ex: result = id + title + getUniqueRandNubr()</p>
</blockquote>
<p>Yeah this might be a better use for a little dsl. You can make a tiny lang with antlr pretty easily. This is more general purpose, you can basically write any code.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How does this stack implementation work</title><link>https://mccue.dev/pages/7-3-21-how-does-this-stack-work</link><description></description><pubDate>Sat, 03 Jul 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How does this stack implementation work</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How does this stack implementation work</h1>
</header>
<h2 id="question-from-whoopdoop7311">Question from whoopdoop#7311</h2>
<blockquote>
<p>Im looking at this stack implementation and</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> ArrayStackOfStrings <span class="kw">implements</span> <span class="bu">Iterable</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="bu">String</span><span class="op">[]</span> items<span class="op">;</span>  <span class="co">// holds the items</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">int</span> n<span class="op">;</span>           <span class="co">// number of items in stack</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">ArrayStackOfStrings</span><span class="op">(</span><span class="dt">int</span> capacity<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>        items <span class="op">=</span> <span class="kw">new</span> <span class="bu">String</span><span class="op">[</span>capacity<span class="op">];</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">push</span><span class="op">(</span><span class="bu">String</span> item<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>        items<span class="op">[</span>n<span class="op">++]</span> <span class="op">=</span> item<span class="op">;</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">String</span> <span class="fu">pop</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> items<span class="op">[--</span>n<span class="op">];</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span></code></pre></div>
<p>If I push an item using this push method, we are changing the items list, but how are we changing the variable n to update the new number of items? same with pop()</p>
</blockquote>
<p>n++ does the mutation</p>
<blockquote>
<p>wait so n is being changed impliciftly?</p>
</blockquote>
<p>yes.</p>
<p><code>n++</code> means return the current value of n and also increment it.</p>
<p><code>--n</code> means decrement it and then return the new value.</p>
<p>It's clearer to write it like this</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> ArrayStackOfStrings <span class="kw">implements</span> <span class="bu">Iterable</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="bu">String</span><span class="op">[]</span> items<span class="op">;</span>  <span class="co">// holds the items</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">int</span> n<span class="op">;</span>           <span class="co">// number of items in stack</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">ArrayStackOfStrings</span><span class="op">(</span><span class="dt">int</span> capacity<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>        items <span class="op">=</span> <span class="kw">new</span> <span class="bu">String</span><span class="op">[</span>capacity<span class="op">];</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">push</span><span class="op">(</span><span class="bu">String</span> item<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>        items<span class="op">[</span>n<span class="op">]</span> <span class="op">=</span> item<span class="op">;</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>        n<span class="op">++;</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">String</span> <span class="fu">pop</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>        n<span class="op">--;</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> items<span class="op">[</span>n<span class="op">];</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span></code></pre></div>
<p>or</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> ArrayStackOfStrings <span class="kw">implements</span> <span class="bu">Iterable</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="bu">String</span><span class="op">[]</span> items<span class="op">;</span>  <span class="co">// holds the items</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">int</span> n<span class="op">;</span>           <span class="co">// number of items in stack</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">ArrayStackOfStrings</span><span class="op">(</span><span class="dt">int</span> capacity<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">items</span> <span class="op">=</span> <span class="kw">new</span> <span class="bu">String</span><span class="op">[</span>capacity<span class="op">];</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">push</span><span class="op">(</span><span class="bu">String</span> item<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">items</span><span class="op">[</span><span class="kw">this</span><span class="op">.</span><span class="fu">n</span><span class="op">]</span> <span class="op">=</span> item<span class="op">;</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">n</span><span class="op">++;</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">String</span> <span class="fu">pop</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">n</span><span class="op">--;</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">items</span><span class="op">[</span><span class="kw">this</span><span class="op">.</span><span class="fu">n</span><span class="op">];</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span></code></pre></div>
<p>so you see more clearly the order of things without remembering the difference between <code>n++</code> and <code>++n</code></p>
<blockquote>
<p>ohhh that makes so much sense</p>
<p>theres no diff between n-- and --n?</p>
</blockquote>
<p>There is</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> x <span class="op">=</span> <span class="dv">5</span><span class="op">;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> y <span class="op">=</span> x<span class="op">++;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="co">// x is 6, y is 5</span></span></code></pre></div>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> x <span class="op">=</span> <span class="dv">5</span><span class="op">;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> y <span class="op">=</span> <span class="op">++</span>x<span class="op">;</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="co">// x is 6, y is 6</span></span></code></pre></div>
<p>But just don't get clever with it, do it on its own line</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Do you write incremental operators in loops and conditions?</title><link>https://mccue.dev/pages/7-3-21-should-i-use-incremental-operators</link><description></description><pubDate>Sat, 03 Jul 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Do you write incremental operators in loops and conditions?</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Do you write incremental operators in loops and conditions?</h1>
</header>
<h2 id="question-from-keldranase4427">Question from keldranase#4427</h2>
<blockquote>
<p>The question is more about coding style for production grade code. Do you write incremental operators in loops and conditions? Consider two pieces of merge algo. What version is better?</p>
</blockquote>
<blockquote>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>list<span class="op">.</span><span class="fu">get</span><span class="op">(</span>left<span class="op">)</span> <span class="op">&lt;</span> list<span class="op">.</span><span class="fu">get</span><span class="op">(</span>right<span class="op">))</span> <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>                result<span class="op">.</span><span class="fu">set</span><span class="op">(</span>writePtr<span class="op">,</span> list<span class="op">.</span><span class="fu">get</span><span class="op">(</span>left<span class="op">));</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>                <span class="op">++</span>left<span class="op">;</span>        <span class="co">// separated incremetns</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>                <span class="op">++</span>writePtr<span class="op">;</span>   </span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>                result<span class="op">.</span><span class="fu">set</span><span class="op">(</span>writePtr<span class="op">,</span> list<span class="op">.</span><span class="fu">get</span><span class="op">(</span>right<span class="op">));</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>                <span class="op">++</span>right<span class="op">;</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>                <span class="op">++</span>writePtr<span class="op">;</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>           <span class="cf">if</span> <span class="op">(</span>list<span class="op">.</span><span class="fu">get</span><span class="op">(</span>left<span class="op">)</span> <span class="op">&lt;</span> list<span class="op">.</span><span class="fu">get</span><span class="op">(</span>right<span class="op">))</span> <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>               result<span class="op">.</span><span class="fu">set</span><span class="op">(</span>writePtr<span class="op">++,</span> list<span class="op">.</span><span class="fu">get</span><span class="op">(</span>left<span class="op">++));</span>    <span class="co">// increments inside things</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>           <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>               result<span class="op">.</span><span class="fu">set</span><span class="op">(</span>writePtr<span class="op">++,</span> list<span class="op">.</span><span class="fu">get</span><span class="op">(</span>right<span class="op">++));</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>           <span class="op">}</span></span></code></pre></div>
<p>Another example is something like this:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="cf">while</span> <span class="op">(</span>someCounter<span class="op">--</span> <span class="op">&gt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">// do something</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Or more verbose, like this:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="cf">while</span> <span class="op">(</span>someCounter <span class="op">&gt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">// do something</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">--</span>someCounter<span class="op">;</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>Most increments are effectively just iterators. So if you are doing anything other than <code>(int i = 0; i &lt; container.size(); i++)</code> then the best code quality would come from working with the iterator/stream abstractions.</p>
<p>However the first one is the one I would go with, with the caveat that I would use <code>left++</code> instead of <code>++left</code>.</p>
<p>No one remembers operator precedence order except C programmers, so separating mutation from assignment/passing of values is best. Everyone does <code>thing++</code> usually and, outside of a context where you are passing at the same time you are changing it, it doesn't matter.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How do I fix my MS-Paint clone</title><link>https://mccue.dev/pages/7-3-21-dissapearing-lines-swing</link><description></description><pubDate>Sat, 03 Jul 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How do I fix my MS-Paint clone</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How do I fix my MS-Paint clone</h1>
</header>
<h2 id="question-from-connor1257">Question from CONNOR#1257</h2>
<blockquote>
<p>Hello, I am trying to make an application similar to ms paint.</p>
<p>When I add <code>super.paint(g)</code> to my paint method my panel appears, however, when I start drawing the lines keep disappearing. when I remove the <code>super.paint(g)</code> the panel is no longer visible but the drawing works perfectly fine.</p>
<p><img src="/pages/7-3-21-blank-swing.png"></img></p>
</blockquote>
<p>Your issue is this:</p>
<p>If you call <code>super.paint(g)</code> it will clear the screen. It then expects you to draw every point.</p>
<p>If you don't call <code>super.paint(g)</code> then the panel isn't redrawn, but whatever paints you have from previous render cycles are left.</p>
<p>The solution is to remember what has been drawn so far and just draw it on the screen again every time you re-render.</p>
<p>The easiest way to do this might be to have a 2d array of <code>java.awt.Color</code>.</p>
<p>When you draw update that array, and when you re-render just write every color to the screen.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>What is the difference between arguments and parameters</title><link>https://mccue.dev/pages/7-2-21-difference-between-arguments-and-parameters</link><description></description><pubDate>Fri, 02 Jul 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>What is the difference between arguments and parameters</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">What is the difference between arguments and parameters</h1>
</header>
<h2 id="question-from-aviral7054">Question from Aviral#7054</h2>
<blockquote>
<p>Hey guys. Can anyone please take 5 mins of their time and just explain the difference between arguments and parameters?</p>
<p>Some people say it's the same and I'm not really convinced...</p>
</blockquote>
<p>It's like magma and lava.</p>
<p>Same thing, different name based on context. Close enough that only total nerds will correct you if you use them interchangeably</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Are Hashtables not used anymore in Java?</title><link>https://mccue.dev/pages/7-2-21-are-hashtables-not-used-in-java</link><description></description><pubDate>Fri, 02 Jul 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Are Hashtables not used anymore in Java?</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Are Hashtables not used anymore in Java?</h1>
</header>
<h2 id="question-from-asianmalaysian-vietnamese1514">Question from asianmalaysian vietnamese#1514</h2>
<blockquote>
<p>Are hashtables like not used anymore in java? Is its synchronicity for key value pairs not a beneficial thing?</p>
<p>Oh if someone asks where did I hear hashtables not being used anymore, in a different group in a different social media platform</p>
</blockquote>
<p>They have been superseded.</p>
<p>People should now (generally) be writing code that targets the <code>Map</code> interface. If you want a synchronized map you can use <code>Collections.synchronizedMap</code> and if you want a good concurrent map there is <code>ConcurrentHashMap</code>.</p>
<p>That being said <code>Hashtable</code> isn't broken or anything. You can still use it if you want a synchronized map. It just comes from before the Java collections framework so the "default" we want to show people is <code>HashMap</code> and then how to synchronize whatever map they chose. So strictly speaking <code>Hashtable</code> is redundant.</p>
<blockquote>
<p>got it, thanks!</p>
</blockquote>
<p>same is true for <code>Vector</code> vs <code>ArrayList</code> also like,</p>
<p><img src="/pages/7-2-21-jdoc-1.png"></img></p>
<p><code>Hashtable</code> implements <code>Map</code> and extends <code>Dictionary</code></p>
<p><img src="/pages/7-2-21-jdoc-2.png"></img></p>
<p>Dictionary is this wierd abstract class that is basically an interface and some of its methods like keys() are redundant with keySet() on Map and also return <code>Enumeration</code>.</p>
<p><img src="/pages/7-2-21-jdoc-3.png"></img></p>
<p>which is like iterator but without syntax support.</p>
<p>So yeah, just generally more crufty.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Do I need new exceptions for every invalid field</title><link>https://mccue.dev/pages/7-1-21-do-i-need-exceptions-for-every-field</link><description></description><pubDate>Thu, 01 Jul 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Do I need new exceptions for every invalid field</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Do I need new exceptions for every invalid field</h1>
</header>
<h2 id="question-from-huh0893">Question from huh#0893</h2>
<blockquote>
<p>are exception classes used per class field or can one exception class handle every field?</p>
<p>If my class has fields for</p>
<pre><code>String name, int ID, double salary, double hours</code></pre>
<p>If I need exceptions for handling empty name <code>""</code>, negative number ID, negative salary, negative hours, do I need a new exception class for every field?</p>
<p>by exception class I mean something like this</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> InvalidPayRate <span class="kw">extends</span> <span class="bu">Exception</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">InvalidPayRate</span><span class="op">(</span><span class="dt">double</span> p<span class="op">)</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">(</span><span class="st">&quot;Hourly pay rate may not be negative or greater than 25: &quot;</span> <span class="op">+</span> p<span class="op">);</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>The reason you don't want a specific <code>InvalidPayRate</code> exception in this case is that it is an <em>unrecoverable</em> scenario.</p>
<p>An Invalid pay rate will almost always mean programmer error.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> InvalidPayRate <span class="kw">extends</span> <span class="bu">Exception</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">InvalidPayRate</span><span class="op">(</span><span class="dt">double</span> p<span class="op">)</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">(</span><span class="st">&quot;Hourly pay rate may nor be negative or greater than 25: &quot;</span> <span class="op">+</span> p<span class="op">);</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>if you were to throw this exception from somewhere you would need to declare that you throw it and then the caller would need to handle it.</p>
<p>So at the very least you want this to extend <code>RuntimeException</code>.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> InvalidPayRate <span class="kw">extends</span> <span class="bu">RuntimeException</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">InvalidPayRate</span><span class="op">(</span><span class="dt">double</span> p<span class="op">)</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">(</span><span class="st">&quot;Hourly pay rate may nor be negative or greater than 25: &quot;</span> <span class="op">+</span> p<span class="op">);</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Since it's a programmer error you don't expect to catch.</p>
<p>At that point you need to weigh the value of doing this for each field in a class and the value is just having the stack trace say "InvalidPayRate", which you can already put into the message.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Enums are a shorthand</title><link>https://mccue.dev/pages/6-28-21-enums-are-just-a-shorthand</link><description></description><pubDate>Mon, 28 Jun 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Enums are a shorthand</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Enums are a shorthand</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 

<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">enum</span> StopLight <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    RED<span class="op">,</span> GREEN<span class="op">,</span> YELLOW<span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Enums are a shorthand for this pattern</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> StopLight <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">final</span> StopLight RED <span class="op">=</span> <span class="kw">new</span> <span class="fu">StopLight</span><span class="op">();</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">final</span> StopLight GREEN <span class="op">=</span> <span class="kw">new</span> <span class="fu">StopLight</span><span class="op">();</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">final</span> StopLight YELLOW <span class="op">=</span> <span class="kw">new</span> <span class="fu">StopLight</span><span class="op">();</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">StopLight</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>They get more support by being a language feature just like records but this is it.</p>
<p>So when you say make a singleton like this</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> PlayerManager <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">static</span> <span class="dt">final</span> PlayerManager INSTANCE <span class="op">=</span> <span class="kw">new</span> <span class="fu">PlayerManager</span><span class="op">();</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> PlayerManager <span class="fu">getInstance</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> INSTANCE<span class="op">;</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>  </span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">PlayerManager</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>all I see is this</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">enum</span> PlayerManager <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    INSTANCE<span class="op">;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> PlayerManager <span class="fu">getInstance</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> INSTANCE<span class="op">;</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How do I make Yoté in JavaFX</title><link>https://mccue.dev/pages/6-28-21-how-to-make-yote-in-javafx</link><description></description><pubDate>Mon, 28 Jun 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How do I make Yoté in JavaFX</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How do I make Yoté in JavaFX</h1>
</header>
<h2 id="question-from-bruno-machado9013">Question from Bruno Machado#9013</h2>
<blockquote>
<p>Hi everyone, I want to develop the Yoté game in java fx with scenebuilder and sockets, but I'm having trouble figuring out how to make each client's interface change every moment. How can I do this kind of communication with the server in javafx? thank you all</p>
</blockquote>
<p>Have a dedicated thread poll the socket for the current state on an interval and communicate that to your UI thread.</p>
<p>I don't know the JavaFX specifics but the general concept is to constantly poll on a thread (or have the server push) and then update your model of the game accordingly.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How to handle passwords</title><link>https://mccue.dev/pages/6-27-21-how-to-handle-passwords</link><description></description><pubDate>Sun, 27 Jun 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How to handle passwords</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How to handle passwords</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
## DO NOT
Store passwords in plaintext. You should never have a record of what your user's passwords are in a way which you can read them.

<h2 id="do-not">DO NOT</h2>
<p>Encrypt passwords</p>
<p><a href="https://nakedsecurity.sophos.com/2013/11/04/anatomy-of-a-password-disaster-adobes-giant-sized-cryptographic-blunder/">https://nakedsecurity.sophos.com/2013/11/04/anatomy-of-a-password-disaster-adobes-giant-sized-cryptographic-blunder/</a></p>
<h2 id="do-not-1">DO NOT</h2>
<p>Use a general purpose hash function like SHA or MD5</p>
<p><a href="https://security.stackexchange.com/questions/90064/how-secure-are-sha256-salt-hashes-for-password-storage">https://security.stackexchange.com/questions/90064/how-secure-are-sha256-salt-hashes-for-password-storage</a></p>
<h2 id="do-not-2">DO NOT</h2>
<p>"roll your own" implementation of cryptographic functions. You will get it wrong.</p>
<p><a href="https://security.stackexchange.com/questions/18197/why-shouldnt-we-roll-our-own">https://security.stackexchange.com/questions/18197/why-shouldnt-we-roll-our-own</a></p>
<h2 id="do">DO</h2>
<p>Use a well tested implementation of PBKDF2, bcrypt, or scrypt to hash and salt passwords</p>
<p><a href="https://spring.io/projects/spring-security">https://spring.io/projects/spring-security</a> <a href="https://mvnrepository.com/artifact/org.springframework.security/spring-security-core">https://mvnrepository.com/artifact/org.springframework.security/spring-security-core</a></p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">springframework</span><span class="op">.</span><span class="im">security</span><span class="op">.</span><span class="im">crypto</span><span class="op">.</span><span class="im">password</span><span class="op">.</span><span class="im">PasswordEncoder</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">org</span><span class="op">.</span><span class="im">springframework</span><span class="op">.</span><span class="im">security</span><span class="op">.</span><span class="im">crypto</span><span class="op">.</span><span class="im">factory</span><span class="op">.</span><span class="im">PasswordEncoderFactories</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> PasswordUtils <span class="op">{</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">PasswordUtils</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">static</span> <span class="dt">final</span> PasswordEncoder PASSWORD_ENCODER <span class="op">=</span> </span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>        <span class="co">// At time of writing the default implementation uses BCrypt</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>        PasswordEncoderFactories<span class="op">.</span><span class="fu">createDelegatingPasswordEncoder</span><span class="op">();</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Store the result of this in your database</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="bu">String</span> <span class="fu">encode</span><span class="op">(</span><span class="bu">String</span> password<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> PASSWORD_ENCODER<span class="op">.</span><span class="fu">encode</span><span class="op">(</span>password<span class="op">);</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    <span class="co">// And use this to check if a user gave you the right password later</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">boolean</span> <span class="fu">matches</span><span class="op">(</span><span class="bu">String</span> password<span class="op">,</span> <span class="bu">String</span> encodedPassword<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> PASSWORD_ENCODER<span class="op">.</span><span class="fu">matches</span><span class="op">(</span>password<span class="op">,</span> encodedPassword<span class="op">);</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Why is my python so ugly</title><link>https://mccue.dev/pages/6-27-21-why-is-this-python-ugly</link><description></description><pubDate>Sun, 27 Jun 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Why is my python so ugly</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Why is my python so ugly</h1>
</header>
<h2 id="question-from-leslie7406">Question from Leslie#7406</h2>
<blockquote>
<div class="sourceCode" id="cb1"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>FRR <span class="op">=</span> <span class="bu">map</span>(<span class="kw">lambda</span> element: element[<span class="dv">1</span>], read_csv)</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>FAR <span class="op">=</span> <span class="bu">map</span>(<span class="kw">lambda</span> element: element[<span class="dv">2</span>], read_csv)</span></code></pre></div>
<p>why is this so ugly</p>
</blockquote>
<p>Use <code>operator.itemgetter(1)</code>, thats what it is for. Also a list comprehension is nicer usually.</p>
<blockquote>
<p>make an example out of my code pls</p>
</blockquote>
<div class="sourceCode" id="cb2"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>FRR <span class="op">=</span> <span class="bu">map</span>(operator.itemgetter(<span class="dv">1</span>), read_csv)</span></code></pre></div>
<p>But then also</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>FRR <span class="op">=</span> [ element[<span class="dv">1</span>] <span class="cf">for</span> element <span class="kw">in</span> read_csv ]</span></code></pre></div>
<p>But then also</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>FRR, FAR <span class="op">=</span> <span class="bu">zip</span>(<span class="op">*</span>[ (element[<span class="dv">1</span>], element[<span class="dv">2</span>]) <span class="cf">for</span> element <span class="kw">in</span> read_csv ])</span></code></pre></div>
<blockquote>
<p>idk Ive never seen a zip(* [ before</p>
</blockquote>
<p><code>*</code> is a splat. It unrolls an iterable into arguments.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How do I get this part of a String</title><link>https://mccue.dev/pages/6-23-21-how-to-pull-out-text-from-a-string</link><description></description><pubDate>Wed, 23 Jun 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How do I get this part of a String</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How do I get this part of a String</h1>
</header>
<h2 id="question-from-raiderross6666">Question from RaiderRoss#6666</h2>
<blockquote>
<p>hey</p>
<p>ik this might sound stupid but i need help with some string manipulation</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> pos <span class="op">=</span> e<span class="op">.</span><span class="fu">getMessage</span><span class="op">().</span><span class="fu">getContentRaw</span><span class="op">().</span><span class="fu">lastIndexOf</span><span class="op">(</span><span class="st">&quot; &quot;</span><span class="op">);</span></span></code></pre></div>
<p>So this is my code, my String would look like this</p>
<pre><code>~ban @RaiderRoss This is the whole reason including spaces
                 -----------------------------------------</code></pre>
<p>how would i get the underlined part as a string</p>
<p>so like the second index basically</p>
</blockquote>
<p>Once you have an index, you can trim the string from that point forward using substring.</p>
<p>so</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="bu">String</span> messageRaw <span class="op">=</span> e<span class="op">.</span><span class="fu">getMessage</span><span class="op">().</span><span class="fu">getContentRaw</span><span class="op">();</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="bu">String</span> reason <span class="op">=</span> messageRaw<span class="op">.</span><span class="fu">substring</span><span class="op">(</span>messageRaw<span class="op">.</span><span class="fu">lastIndexOf</span><span class="op">(</span><span class="st">&quot; &quot;</span><span class="op">));</span></span></code></pre></div>
<p>But in your case it seems like you would only get <code>spaces</code>. Instead, we can split on spaces.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="bu">String</span> messageRaw <span class="op">=</span> e<span class="op">.</span><span class="fu">getMessage</span><span class="op">().</span><span class="fu">getContentRaw</span><span class="op">();</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="bu">String</span><span class="op">[]</span> words <span class="op">=</span> messageRaw<span class="op">.</span><span class="fu">split</span><span class="op">(</span><span class="ch">&#39; &#39;</span><span class="op">);</span></span></code></pre></div>
<p>then join, skipping the first two</p>
<blockquote>
<p>how do I join</p>
<p>skipping the first two</p>
</blockquote>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="bu">String</span> messageRaw <span class="op">=</span> <span class="st">&quot;a b c &quot;</span><span class="op">;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="bu">String</span><span class="op">[]</span> words <span class="op">=</span> messageRaw<span class="op">.</span><span class="fu">split</span><span class="op">(</span><span class="st">&quot; &quot;</span><span class="op">);</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="bu">String</span> reason <span class="op">=</span> <span class="bu">Arrays</span><span class="op">.</span><span class="fu">stream</span><span class="op">(</span>words<span class="op">)</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">skip</span><span class="op">(</span><span class="dv">2</span><span class="op">)</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">collect</span><span class="op">(</span>Collectors<span class="op">.</span><span class="fu">joining</span><span class="op">(</span><span class="st">&quot; &quot;</span><span class="op">));</span></span></code></pre></div>
<blockquote>
<p>btw our teacher never thought us any of this I got to learn it all on my own so ty for the help</p>
</blockquote>
<p>This is one way. You can also do it manually or instead just find the index of the 2nd space and take a substring after that.</p>
<p><a href="https://stackoverflow.com/questions/19035893/finding-second-occurrence-of-a-substring-in-a-string-in-java/35155037">https://stackoverflow.com/questions/19035893/finding-second-occurrence-of-a-substring-in-a-string-in-java/35155037</a></p>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="bu">String</span> messageRaw <span class="op">=</span> <span class="st">&quot;a b c &quot;</span><span class="op">;</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="bu">String</span> reason <span class="op">=</span> messageRaw<span class="op">.</span><span class="fu">substring</span><span class="op">(</span>messageRaw<span class="op">.</span><span class="fu">indexOf</span><span class="op">(</span><span class="st">&quot; &quot;</span><span class="op">,</span> messageRaw<span class="op">.</span><span class="fu">indexOf</span><span class="op">(</span><span class="st">&quot; &quot;</span><span class="op">)</span> <span class="op">+</span> <span class="dv">1</span><span class="op">));</span></span></code></pre></div>
<p>and you can also use regex if you feel brave</p>
<blockquote>
<p>ok i got it now ty sm for the help</p>
</blockquote>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How to print data with proper spaces</title><link>https://mccue.dev/pages/6-22-21-how-to-print-with-proper-spaces</link><description></description><pubDate>Tue, 22 Jun 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How to print data with proper spaces</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How to print data with proper spaces</h1>
</header>
<h2 id="question-from-ericmp6201">Question from ericmp#6201</h2>
<blockquote>
<p>hi, im tring to print this but with proper spaces, to make it more visual:</p>
<p><img src="/pages/6-22-21-data.png"></img></p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">printf</span><span class="op">(</span><span class="st">&quot;</span><span class="sc">%-25s</span><span class="st"> </span><span class="sc">%-25s</span><span class="st"> </span><span class="sc">%-20s</span><span class="st"> </span><span class="sc">%-21s</span><span class="st"> </span><span class="sc">%-21s</span><span class="st"> </span><span class="sc">%-24s</span><span class="st"> </span><span class="sc">%-24s</span><span class="st"> </span><span class="sc">%-25s</span><span class="st"> </span><span class="sc">%-25s</span><span class="st"> </span><span class="sc">%-20s</span><span class="st"> </span><span class="sc">%-20s</span><span class="st"> </span><span class="sc">%-20s</span><span class="st"> </span><span class="sc">%-25s</span><span class="st"> </span><span class="sc">%n</span><span class="st">&quot;</span><span class="op">,</span> <span class="st">&quot;{ nom: &quot;</span> <span class="op">+</span> nom <span class="op">,</span> <span class="st">&quot;tipus: &quot;</span> <span class="op">+</span> tipusS <span class="op">,</span> <span class="st">&quot;número: &quot;</span> <span class="op">+</span> numeroS <span class="op">,</span> <span class="st">&quot;valor: &quot;</span> <span class="op">+</span> valorS <span class="op">,</span> <span class="st">&quot;pedres: &quot;</span> <span class="op">+</span> pedresS <span class="op">,</span> <span class="st">&quot;tirada: &quot;</span> <span class="op">+</span> tiradaS <span class="op">,</span> <span class="st">&quot;agafada: &quot;</span> <span class="op">+</span> agafadaS <span class="op">,</span> <span class="st">&quot;triomf: &quot;</span> <span class="op">+</span> triomfS <span class="op">,</span> <span class="st">&quot;última: &quot;</span> <span class="op">+</span> ultimaS <span class="op">,</span> <span class="st">&quot;tirada per: &quot;</span> <span class="op">+</span> tiradaPerS <span class="op">,</span> <span class="st">&quot;recollida per: &quot;</span> <span class="op">+</span> recollidaPerS <span class="op">,</span> <span class="st">&quot;tirada primer: &quot;</span> <span class="op">+</span> tiradaPrimerS <span class="op">,</span> <span class="st">&quot; }&quot;</span><span class="op">);</span></span></code></pre></div>
<p>but as u see, is not really good, like, sometimes there is more spaces, and sometimes less, and finally, there isnt</p>
<p>how could i do it better?</p>
<p>(i tried to put 20s to each one, but looks worse)</p>
</blockquote>
<p>So this is actually something that really old programs needed to do a lot. And honestly most bank statements, etc.</p>
<p>But it's weirdly not super supported in modern languages. If you don't care about how long it gets we can make a method that prints to a table so.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">outputAsTable</span><span class="op">(</span><span class="bu">List</span><span class="op">&lt;</span><span class="bu">Map</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">,</span> <span class="bu">String</span><span class="op">&gt;&gt;</span> stuff<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Start with this - assume we have a list of maps you want to print out. We can scan through each map and find the longest value for each key.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">outputAsTable</span><span class="op">(</span><span class="bu">List</span><span class="op">&lt;</span><span class="bu">Map</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">,</span> <span class="bu">String</span><span class="op">&gt;&gt;</span> stuff<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Map</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">,</span> <span class="bu">Integer</span><span class="op">&gt;</span> longestValues <span class="op">=</span> <span class="kw">new</span> <span class="bu">HashMap</span><span class="op">&lt;&gt;();</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span>var map <span class="op">:</span> stuff<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span>var entry <span class="op">:</span> map<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>longestValues<span class="op">.</span><span class="fu">getOrDefault</span><span class="op">(</span>entry<span class="op">.</span><span class="fu">getKey</span><span class="op">(),</span> <span class="dv">0</span><span class="op">)</span> <span class="op">&lt;</span> entry<span class="op">.</span><span class="fu">getValue</span><span class="op">().</span><span class="fu">length</span><span class="op">())</span> <span class="op">{</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>                longestValues<span class="op">.</span><span class="fu">put</span><span class="op">(</span>entry<span class="op">.</span><span class="fu">getKey</span><span class="op">(),</span> entry<span class="op">.</span><span class="fu">getValue</span><span class="op">().</span><span class="fu">length</span><span class="op">()</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">...</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Then once you have all those you can do math to figure out how many spaces to add.</p>
<blockquote>
<p>I think this will be hard, I've never worked with this maps, and this variables are not stored inside any array, they are just the attributes of a class, so I print them to check how all is working</p>
</blockquote>
<p>You just need to convert your objects to a list of maps, unfortunately. If you want it all properly spaced you need to print them all at once not individually since if you think about it, how much padding to give any one element can be determined by what you want to print 10 items later.</p>
<p>Another option is to print vertically</p>
<pre><code>field_1:   ...
field_abc: ...
ww:        ...
-------------------
field_1:   ...
field_abc: ...
ww:        ...</code></pre>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Is it possible to use SCSS in a Java project</title><link>https://mccue.dev/pages/6-22-21-scss-in-a-java-project</link><description></description><pubDate>Tue, 22 Jun 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Is it possible to use SCSS in a Java project</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Is it possible to use SCSS in a Java project</h1>
</header>
<h2 id="question-from-senhor3353">Question from Senhor#3353</h2>
<blockquote>
<p>hi</p>
<p>i have one question: is it possible to use SCSS in a Java project? I am currently generating PDF from HTML pages; i craft these pages with html and pure css, and i was wondering if there's a way to use SCSS instead</p>
</blockquote>
<p>Sure, but you are going to need to do some plumbing.</p>
<p>SCSS is built in JS so there really isn't a way to include it as part of a java build system.</p>
<p>You will need to install it with npm separately either globally, or in a project in the directory where you need to run your jar.</p>
<p>Then you need to invoke scss to generate CSS files.</p>
<p>You can do this through ProcessBuilder, so it is definitely doable - just not frictionless.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Simple AtomicReference Wrapper</title><link>https://mccue.dev/pages/6-19-21-atom</link><description></description><pubDate>Sat, 19 Jun 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Simple AtomicReference Wrapper</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Simple AtomicReference Wrapper</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
Simple wrapper around an atomic reference to provide a basic functional interface for CAS operations.

<p>Useful if you have some immutable state you want to share between and mutate on multiple threads</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span><span class="im"> dev</span><span class="op">.</span><span class="im">mccue</span><span class="op">.</span><span class="im">async</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">concurrent</span><span class="op">.</span><span class="im">atomic</span><span class="op">.</span><span class="im">AtomicReference</span><span class="op">;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">function</span><span class="op">.</span><span class="im">Function</span><span class="op">;</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="co">/**</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a> <span class="co">*</span> Simple wrapper over an AtomicReference to provide an API for doing compare and swap operations<span class="co">.</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a> <span class="co">*</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a> <span class="co">*</span> Modeled after the atom primitive in clojure<span class="co">.</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a> <span class="co">*</span> <span class="co">@</span>param <span class="kw">&lt;T&gt;</span> The type of data stored in the atom<span class="co">.</span> This is assumed to be an immutable object<span class="co">.</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a> <span class="co">*/</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> Atom<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="bu">AtomicReference</span><span class="op">&lt;</span>T<span class="op">&gt;</span> ref<span class="op">;</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Atom</span><span class="op">(</span>T data<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">ref</span> <span class="op">=</span> <span class="kw">new</span> <span class="bu">AtomicReference</span><span class="op">&lt;&gt;(</span>data<span class="op">);</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>    <span class="co">/**</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> Creates an atom wrapping the given data<span class="co">.</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> <span class="co">@</span>param data The data to be stored in the atom<span class="co">.</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> <span class="co">@</span>param <span class="kw">&lt;T&gt;</span> The type of data stored in the atom<span class="co">.</span> This is assumed to be an immutable object<span class="co">.</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> <span class="co">@</span>return An atom containing the given data<span class="co">.</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>     <span class="co">*/</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="op">&lt;</span>T<span class="op">&gt;</span> Atom<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="fu">of</span><span class="op">(</span>T data<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> Atom<span class="op">&lt;&gt;(</span>data<span class="op">);</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a>    <span class="co">/**</span></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> Swaps the current value in the atom for the value returned by the function<span class="co">.</span></span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> <span class="co">@</span>param f The function to apply to the current value<span class="co">.</span> It is expected that this</span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span>          will be a <span class="co">&quot;</span>pure<span class="co">&quot;</span> function and thus may be run multiple times<span class="co">.</span></span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> <span class="co">@</span>return The value in the Atom after the function is applied<span class="co">.</span></span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a>     <span class="co">*/</span></span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> T <span class="fu">swap</span><span class="op">(</span>Function<span class="op">&lt;?</span> <span class="kw">super</span> T<span class="op">,</span> <span class="op">?</span> <span class="kw">extends</span> T<span class="op">&gt;</span> f<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a>        <span class="cf">while</span> <span class="op">(</span><span class="kw">true</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-37"><a href="#cb1-37" aria-hidden="true" tabindex="-1"></a>            <span class="dt">final</span> var start <span class="op">=</span> ref<span class="op">.</span><span class="fu">get</span><span class="op">();</span></span>
<span id="cb1-38"><a href="#cb1-38" aria-hidden="true" tabindex="-1"></a>            <span class="dt">final</span> var res <span class="op">=</span> f<span class="op">.</span><span class="fu">apply</span><span class="op">(</span>start<span class="op">);</span></span>
<span id="cb1-39"><a href="#cb1-39" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span><span class="kw">this</span><span class="op">.</span><span class="fu">ref</span><span class="op">.</span><span class="fu">compareAndSet</span><span class="op">(</span>start<span class="op">,</span> res<span class="op">))</span> <span class="op">{</span></span>
<span id="cb1-40"><a href="#cb1-40" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> res<span class="op">;</span></span>
<span id="cb1-41"><a href="#cb1-41" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb1-42"><a href="#cb1-42" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-43"><a href="#cb1-43" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-44"><a href="#cb1-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-45"><a href="#cb1-45" aria-hidden="true" tabindex="-1"></a>    <span class="co">/**</span></span>
<span id="cb1-46"><a href="#cb1-46" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> Pair of the new value swapped into an atom and some value that was</span>
<span id="cb1-47"><a href="#cb1-47" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> derived in the course of calculating that new value<span class="co">.</span></span>
<span id="cb1-48"><a href="#cb1-48" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> <span class="co">@</span>param <span class="kw">&lt;T&gt;</span> Type of the new value<span class="co">.</span></span>
<span id="cb1-49"><a href="#cb1-49" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> <span class="co">@</span>param <span class="kw">&lt;R&gt;</span> Type of the derived value<span class="co">.</span></span>
<span id="cb1-50"><a href="#cb1-50" aria-hidden="true" tabindex="-1"></a>     <span class="co">*/</span></span>
<span id="cb1-51"><a href="#cb1-51" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> record SwapResult<span class="op">&lt;</span>T<span class="op">,</span> R<span class="op">&gt;(</span>T newValue<span class="op">,</span> R derivedValue<span class="op">)</span> <span class="op">{}</span></span>
<span id="cb1-52"><a href="#cb1-52" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-53"><a href="#cb1-53" aria-hidden="true" tabindex="-1"></a>    <span class="co">/**</span></span>
<span id="cb1-54"><a href="#cb1-54" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> Performs a swap that carries over some context from the computation to the caller<span class="co">.</span></span>
<span id="cb1-55"><a href="#cb1-55" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span></span>
<span id="cb1-56"><a href="#cb1-56" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> For example<span class="co">,</span> a basic usage would be to return some whether a value was inserted into a map<span class="co">.</span></span>
<span id="cb1-57"><a href="#cb1-57" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span></span>
<span id="cb1-58"><a href="#cb1-58" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> <span class="kw">&lt;pre&gt;</span><span class="co">{@</span>code</span>
<span id="cb1-59"><a href="#cb1-59" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> sealed interface PlayerJoinResult permits AlreadyInGame<span class="co">,</span> Success <span class="co">{}</span></span>
<span id="cb1-60"><a href="#cb1-60" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> record AlreadyInGame<span class="co">()</span> implements PlayerJoinResult<span class="co">{}</span></span>
<span id="cb1-61"><a href="#cb1-61" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> record Success<span class="co">(</span>String playerId<span class="co">)</span> implements PlayerJoinResult <span class="co">{}</span></span>
<span id="cb1-62"><a href="#cb1-62" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> <span class="co">//</span> <span class="co">...</span></span>
<span id="cb1-63"><a href="#cb1-63" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> final var playerId <span class="co">=</span> UUID<span class="co">.</span>randomUUID<span class="co">().</span>toString<span class="co">();</span></span>
<span id="cb1-64"><a href="#cb1-64" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> final var gameAtom <span class="co">=</span> Atom<span class="co">.</span>of<span class="co">(</span>Map<span class="co">.</span>empty<span class="co">());</span></span>
<span id="cb1-65"><a href="#cb1-65" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> final var swapResult <span class="co">=</span> gameAtom<span class="co">.</span>complexSwap<span class="co">(</span>game <span class="co">-&gt;</span> <span class="co">{</span></span>
<span id="cb1-66"><a href="#cb1-66" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span>    if <span class="co">(</span>game<span class="co">.</span>contains<span class="co">(</span>playerId<span class="co">))</span> <span class="co">{</span></span>
<span id="cb1-67"><a href="#cb1-67" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span>        return new ComplexSwapResult<span class="er">&lt;</span><span class="co">&gt;(</span>game<span class="co">,</span> new AlreadyInGame<span class="co">());</span></span>
<span id="cb1-68"><a href="#cb1-68" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span>    <span class="co">}</span></span>
<span id="cb1-69"><a href="#cb1-69" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span>    else <span class="co">{</span></span>
<span id="cb1-70"><a href="#cb1-70" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span>        return new ComplexSwapResult<span class="er">&lt;</span><span class="co">&gt;(</span>game<span class="co">.</span>put<span class="co">(</span>playerId<span class="co">,</span> new Object<span class="co">()),</span> new Success<span class="co">(</span>playerId<span class="co">));</span></span>
<span id="cb1-71"><a href="#cb1-71" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span>    <span class="co">}</span></span>
<span id="cb1-72"><a href="#cb1-72" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> <span class="co">});</span></span>
<span id="cb1-73"><a href="#cb1-73" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span></span>
<span id="cb1-74"><a href="#cb1-74" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> if <span class="co">(</span>swapResult<span class="co">.</span>derivedValue<span class="co">()</span> instanceof AlreadyInGame<span class="co">)</span> <span class="co">{</span></span>
<span id="cb1-75"><a href="#cb1-75" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span>     return <span class="co">&quot;</span>Oh no<span class="co">!&quot;;</span></span>
<span id="cb1-76"><a href="#cb1-76" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> <span class="co">}</span></span>
<span id="cb1-77"><a href="#cb1-77" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> else <span class="co">{</span></span>
<span id="cb1-78"><a href="#cb1-78" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span>     return <span class="co">&quot;</span>hooray<span class="co">&quot;;</span></span>
<span id="cb1-79"><a href="#cb1-79" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> <span class="co">}</span></span>
<span id="cb1-80"><a href="#cb1-80" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> <span class="co">}</span><span class="kw">&lt;/pre&gt;</span></span>
<span id="cb1-81"><a href="#cb1-81" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span></span>
<span id="cb1-82"><a href="#cb1-82" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> <span class="co">@</span>param f The function to apply to the current value<span class="co">.</span> It is expected that this</span>
<span id="cb1-83"><a href="#cb1-83" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span>          will be a <span class="co">&quot;</span>pure<span class="co">&quot;</span> function and thus may be run multiple times<span class="co">.</span></span>
<span id="cb1-84"><a href="#cb1-84" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> <span class="co">@</span>param <span class="kw">&lt;R&gt;</span> The type of the context attached to the final result<span class="co">.</span></span>
<span id="cb1-85"><a href="#cb1-85" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> <span class="co">@</span>return A pair of the new value put into the atom and the derived value from the</span>
<span id="cb1-86"><a href="#cb1-86" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> computation of that new value<span class="co">.</span></span>
<span id="cb1-87"><a href="#cb1-87" aria-hidden="true" tabindex="-1"></a>     <span class="co">*/</span></span>
<span id="cb1-88"><a href="#cb1-88" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="op">&lt;</span>R<span class="op">&gt;</span> SwapResult<span class="op">&lt;</span>T<span class="op">,</span> R<span class="op">&gt;</span> <span class="fu">complexSwap</span><span class="op">(</span></span>
<span id="cb1-89"><a href="#cb1-89" aria-hidden="true" tabindex="-1"></a>            Function<span class="op">&lt;?</span> <span class="kw">super</span> T<span class="op">,</span> SwapResult<span class="op">&lt;?</span> <span class="kw">extends</span>  T<span class="op">,</span> <span class="op">?</span> <span class="kw">extends</span> R<span class="op">&gt;&gt;</span> f</span>
<span id="cb1-90"><a href="#cb1-90" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-91"><a href="#cb1-91" aria-hidden="true" tabindex="-1"></a>        <span class="cf">while</span> <span class="op">(</span><span class="kw">true</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-92"><a href="#cb1-92" aria-hidden="true" tabindex="-1"></a>            <span class="dt">final</span> var start <span class="op">=</span> ref<span class="op">.</span><span class="fu">get</span><span class="op">();</span></span>
<span id="cb1-93"><a href="#cb1-93" aria-hidden="true" tabindex="-1"></a>            <span class="dt">final</span> var res <span class="op">=</span> f<span class="op">.</span><span class="fu">apply</span><span class="op">(</span>start<span class="op">);</span></span>
<span id="cb1-94"><a href="#cb1-94" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span><span class="kw">this</span><span class="op">.</span><span class="fu">ref</span><span class="op">.</span><span class="fu">compareAndSet</span><span class="op">(</span>start<span class="op">,</span> res<span class="op">.</span><span class="fu">newValue</span><span class="op">()))</span> <span class="op">{</span></span>
<span id="cb1-95"><a href="#cb1-95" aria-hidden="true" tabindex="-1"></a>                <span class="cf">return</span> <span class="kw">new</span> SwapResult<span class="op">&lt;&gt;(</span>res<span class="op">.</span><span class="fu">newValue</span><span class="op">(),</span> res<span class="op">.</span><span class="fu">derivedValue</span><span class="op">());</span></span>
<span id="cb1-96"><a href="#cb1-96" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb1-97"><a href="#cb1-97" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-98"><a href="#cb1-98" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-99"><a href="#cb1-99" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-100"><a href="#cb1-100" aria-hidden="true" tabindex="-1"></a>    <span class="co">/**</span></span>
<span id="cb1-101"><a href="#cb1-101" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> Resets the value in the atom to the given value<span class="co">.</span></span>
<span id="cb1-102"><a href="#cb1-102" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> <span class="co">@</span>param data The new value to be stored in the atom<span class="co">.</span></span>
<span id="cb1-103"><a href="#cb1-103" aria-hidden="true" tabindex="-1"></a>     <span class="co">*</span> <span class="co">@</span>return The new value stored in the atom<span class="co">.</span></span>
<span id="cb1-104"><a href="#cb1-104" aria-hidden="true" tabindex="-1"></a>     <span class="co">*/</span></span>
<span id="cb1-105"><a href="#cb1-105" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> T <span class="fu">reset</span><span class="op">(</span>T data<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-106"><a href="#cb1-106" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">ref</span><span class="op">.</span><span class="fu">set</span><span class="op">(</span>data<span class="op">);</span></span>
<span id="cb1-107"><a href="#cb1-107" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> data<span class="op">;</span></span>
<span id="cb1-108"><a href="#cb1-108" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-109"><a href="#cb1-109" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-110"><a href="#cb1-110" aria-hidden="true" tabindex="-1"></a>    <span class="co">/**</span></span>
<span id="cb1-111"><a href="#cb1-111" aria-hidden="true" tabindex="-1"></a><span class="co">     * @</span>return The atom<span class="co">&#39;</span>s current value<span class="co">.</span></span>
<span id="cb1-112"><a href="#cb1-112" aria-hidden="true" tabindex="-1"></a>     <span class="co">*/</span></span>
<span id="cb1-113"><a href="#cb1-113" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> T <span class="fu">get</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-114"><a href="#cb1-114" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">ref</span><span class="op">.</span><span class="fu">get</span><span class="op">();</span></span>
<span id="cb1-115"><a href="#cb1-115" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-116"><a href="#cb1-116" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-117"><a href="#cb1-117" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb1-118"><a href="#cb1-118" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">String</span> <span class="fu">toString</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-119"><a href="#cb1-119" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="st">&quot;Atom[value=&quot;</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">get</span><span class="op">()</span> <span class="op">+</span> <span class="st">&quot;]&quot;</span><span class="op">;</span></span>
<span id="cb1-120"><a href="#cb1-120" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-121"><a href="#cb1-121" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Why is the else not printing</title><link>https://mccue.dev/pages/6-19-21-why-is-the-else-not-printing</link><description></description><pubDate>Sat, 19 Jun 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Why is the else not printing</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Why is the else not printing</h1>
</header>
<h2 id="question-from-akira6298">Question from akira💖🌻#6298</h2>
<blockquote>
<p>hello i have a small small problem</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">package</span><span class="im"> HelloJaxa</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.*;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>        <span class="bu">Scanner</span> scan<span class="op">=</span><span class="kw">new</span> <span class="bu">Scanner</span><span class="op">(</span><span class="bu">System</span><span class="op">.</span><span class="fu">in</span><span class="op">);</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">print</span><span class="op">(</span><span class="st">&quot;Enter 10 Grades--&gt; &quot;</span><span class="op">);</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> <span class="bu">Number</span><span class="op">=</span><span class="dv">0</span><span class="op">;</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> counter90<span class="op">=</span><span class="dv">0</span><span class="op">;</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>        <span class="dt">int</span> counterless<span class="op">=</span><span class="dv">0</span><span class="op">;</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span><span class="bu">Number</span><span class="op">&gt;=</span><span class="dv">0</span> <span class="op">&amp;&amp;</span> <span class="bu">Number</span><span class="op">&lt;=</span><span class="dv">100</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>            <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">10</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>                <span class="bu">Number</span> <span class="op">=</span> scan<span class="op">.</span><span class="fu">nextInt</span><span class="op">();</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>                <span class="cf">if</span> <span class="op">(</span><span class="bu">Number</span> <span class="op">&gt;=</span> <span class="dv">90</span><span class="op">)</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>                    counter90<span class="op">++;</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>                <span class="cf">if</span> <span class="op">(</span><span class="bu">Number</span> <span class="op">&gt;</span> <span class="dv">60</span> <span class="op">&amp;&amp;</span> <span class="bu">Number</span> <span class="op">&lt;</span> <span class="dv">90</span><span class="op">)</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>                    counterless<span class="op">++;</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>            <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Grades that equal 90 or more--&gt;&quot;</span><span class="op">+</span>counter90<span class="op">);</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>            <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Grades that are between 60 and 90--&gt; &quot;</span><span class="op">+</span> counterless<span class="op">);</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>            <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Error!&quot;</span><span class="op">);</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}}</span></span></code></pre></div>
<p>why is the else not printing when i input a number thats &lt;0 or &gt;100</p>
</blockquote>
<p>First, put the <code>{}</code> around the else. Sometimes that can be the whole issue. Try not to omit the <code>{}</code> even though its technically allowed.</p>
<p>And you will never reach the else since you check if the number is between 0 and 100 before entering the loop where you ask for input.</p>
<p>You never return to that check again so it only runs once and sees 0.</p>
<blockquote>
<p>what do i do now ?</p>
</blockquote>
<p>Move your check inside your for loop</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How is abstraction achieved through abstract classes and interfaces</title><link>https://mccue.dev/pages/6-8-21-how-is-abstraction-achieved</link><description></description><pubDate>Tue, 08 Jun 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How is abstraction achieved through abstract classes and interfaces</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How is abstraction achieved through abstract classes and interfaces</h1>
</header>
<h2 id="question-from-data205839">Question from Data20#5839</h2>
<blockquote>
<p>How is abstraction achieved through abstract classes and interfaces?</p>
<p>I may have a misunderstanding somewhere, so I'll elaborate on where I'm at with the concept.</p>
<p>From my understanding: Abstraction is a concept of OOP that focuses on hiding implementation detail and showing only what is necessary. The functional detail</p>
<p>This is the example I see when I go with this definition:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Base <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">int</span> <span class="fu">area</span><span class="op">(</span><span class="dt">int</span> length<span class="op">,</span> <span class="dt">int</span> width<span class="op">){</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> length <span class="op">*</span> width<span class="op">;</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>   <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>        Base r1 <span class="op">=</span> <span class="kw">new</span> <span class="fu">Base</span><span class="op">();</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;The area of this rectangle is &quot;</span> <span class="op">+</span> r1<span class="op">.</span><span class="fu">area</span><span class="op">(</span><span class="dv">5</span><span class="op">,</span><span class="dv">6</span><span class="op">)</span> <span class="op">+</span> <span class="st">&quot;.&quot;</span><span class="op">);</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>When I called the area method in Base, I just wanted the area of a rectangle. I didn't need to know the actual formula for it, just the result of it.</p>
<p>Having said that, I feel that I'm off somewhere and am confused with how abstraction is achieved with Abstract classes and Interfaces.</p>
</blockquote>
<p>Okay so first - abstraction is not a concept of OOP.</p>
<p>Your area method does abstract the actual mechanism of computation. i.e. you could rewrite it like this</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">int</span> <span class="fu">area</span><span class="op">(</span><span class="dt">int</span> length<span class="op">,</span> <span class="dt">int</span> width<span class="op">){</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>width <span class="op">&lt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="fu">area</span><span class="op">(</span>length<span class="op">,</span> <span class="op">-</span><span class="dv">1</span> <span class="op">*</span> width<span class="op">)</span> <span class="op">*</span> <span class="op">-</span><span class="dv">1</span><span class="op">;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>width <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> length <span class="op">+</span> <span class="fu">area</span><span class="op">(</span>length<span class="op">,</span> width <span class="op">-</span> <span class="dv">1</span><span class="op">);</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>and its contract to the rest of the code would remain the same.</p>
<p>What interfaces give you is a mechanism for <em>polymorphism</em>. For instance if I wrote code like this</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">enum</span> IntOrder <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    LessThan<span class="op">,</span> EqualTo<span class="op">,</span> GreaterThan<span class="op">;</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> IntComparator <span class="op">{</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> IntOrder <span class="fu">compare</span><span class="op">(</span><span class="dt">int</span> a<span class="op">,</span> <span class="dt">int</span> b<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>a <span class="op">&lt;</span> b<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> LessThan<span class="op">;</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>a <span class="op">==</span> b<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> EqualTo<span class="op">;</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> GreaterThan</span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>I've successfully abstracted the process of comparing two integers and if I wanted to write a sort function</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">static</span> <span class="dt">int</span><span class="op">[]</span> <span class="fu">sort</span><span class="op">(</span><span class="dt">int</span><span class="op">[]</span> xs<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// somewhere i can call new IntComparator.compare(...); and use that for ordering</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>I could use that abstracted comparison behavior.</p>
<p>But if I wanted the sort function to "be abstracted" over how it compares these integers I could use an interface</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">interface</span> IntComparator <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    IntOrder <span class="fu">compare</span><span class="op">(</span><span class="dt">int</span> a<span class="op">,</span> <span class="dt">int</span> b<span class="op">);</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> NormalIntComparator <span class="kw">implements</span> IntComparator <span class="op">{</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> IntOrder <span class="fu">compare</span><span class="op">(</span><span class="dt">int</span> a<span class="op">,</span> <span class="dt">int</span> b<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>a <span class="op">&lt;</span> b<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> LessThan<span class="op">;</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>a <span class="op">==</span> b<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> EqualTo<span class="op">;</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> GreaterThan</span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true" tabindex="-1"></a><span class="kw">...</span></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">static</span> <span class="dt">int</span><span class="op">[]</span> <span class="fu">sort</span><span class="op">(</span><span class="dt">int</span><span class="op">[]</span> xs<span class="op">,</span> IntComparator comparator<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true" tabindex="-1"></a>    <span class="co">// somewhere i can call comparator.compare(...); and use that for ordering</span></span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And this would let me write many different implementations of comparing ints. For instance, maybe comparing them in reverse order and treat them "the same" in some other abstraction.</p>
<p>So polymorphism has utility in building abstractions and interfaces give you polymorphism.</p>
<p>Abstract classes give you polymorphism and code sharing, but their primary utility is code sharing.</p>
<p>You can still make abstractions and get polymorphism in non OOP languages your mechanisms for doing so will just be different.</p>
<blockquote>
<p>I'm taking in what all you said. From the readings I've done, I've always thought that Abstraction was apart of OOP.</p>
</blockquote>
<p>In your defense, a large part of why OOP and specifically Java is so omnipresent is heavy degrees of marketing and hype. A lot of what you read probably never stops to point out nuance since its all somewhat derived from marketing.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How to connect opencv in Python to Java Swing</title><link>https://mccue.dev/pages/6-6-21-connect-python-to-swing</link><description></description><pubDate>Sun, 06 Jun 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How to connect opencv in Python to Java Swing</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How to connect opencv in Python to Java Swing</h1>
</header>
<h2 id="question-from-𝙬𝙖𝙟𝙚𝙚𝙝𝙖5024">Question from ☮𝙬𝙖𝙟𝙚𝙚𝙝𝙖☮#5024</h2>
<blockquote>
<p>hey people. so, i did my backend of the project in opencv-python and developed the front end using swing java. now i want to connect them. can somebody guide me how to do this?</p>
</blockquote>
<p>This is, conceptually, what an API is for.</p>
<p>Not necessarily an "api served over http" but just the general thrust of "these are two independent processes that will communicate via some mechanism".</p>
<p>More details about how you want these things to communicate would be helpful - are they going to be run on the same machine, etc.</p>
<blockquote>
<p>Yes I want them to run on the same machine</p>
<p>I searched a little bit and found some method</p>
<p>Using execute shell command</p>
<p>But I'm not receiving the output I want</p>
<p>Maybe I'm doing something wrong idk</p>
</blockquote>
<p>From the Java side you can launch the python app using <code>ProcessBuilder</code> and then. communicate that way.</p>
<p><a href="https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/lang/ProcessBuilder.html">https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/lang/ProcessBuilder.html</a></p>
<blockquote>
<p>Ok I will try this thanks for the link.</p>
</blockquote>
<p>That's just step 1, but yeah start there.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How to make infinite character combinations</title><link>https://mccue.dev/pages/6-1-21-infinite-char-combinations</link><description></description><pubDate>Tue, 01 Jun 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How to make infinite character combinations</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How to make infinite character combinations</h1>
</header>
<h2 id="question-from-bulver9256">Question from Bulver#9256</h2>
<blockquote>
<p>Hey, please forgive my bad english. I am trying to get an infinite amount of char combinations which are stored in an array. I cant figure out how i can implement this in one method. Does anyone have ideas?</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">one</span><span class="op">(</span><span class="dt">char</span><span class="op">[]</span> arr<span class="op">){</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>       <span class="cf">for</span><span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i<span class="op">&lt;</span><span class="dv">95</span><span class="op">;</span> i<span class="op">++){</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>           <span class="bu">String</span> a <span class="op">=</span> <span class="st">&quot;&quot;</span><span class="op">+</span>arr<span class="op">[</span>i<span class="op">];</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>           <span class="cf">if</span><span class="op">(</span><span class="fu">hash2</span><span class="op">(</span>a<span class="op">)%</span>m<span class="op">==</span><span class="dv">0</span><span class="op">){</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>               <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>a<span class="op">);</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>           <span class="op">}</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>       <span class="op">}</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>   <span class="op">}</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>   <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">two</span><span class="op">(</span><span class="dt">char</span><span class="op">[]</span> arr<span class="op">){</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>       <span class="cf">for</span><span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i<span class="op">&lt;</span><span class="dv">95</span><span class="op">;</span> i<span class="op">++){</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>           <span class="cf">for</span><span class="op">(</span><span class="dt">int</span> j <span class="op">=</span> <span class="dv">0</span><span class="op">;</span>j<span class="op">&lt;</span><span class="dv">95</span><span class="op">;</span>j<span class="op">++){</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>               <span class="bu">String</span> a <span class="op">=</span> <span class="st">&quot;&quot;</span><span class="op">+</span>arr<span class="op">[</span>i<span class="op">]+</span>arr<span class="op">[</span>j<span class="op">];</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>               <span class="cf">if</span><span class="op">(</span><span class="fu">hash2</span><span class="op">(</span>a<span class="op">)%</span>m<span class="op">==</span><span class="dv">0</span><span class="op">){</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>                   <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>a<span class="op">);</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>               <span class="op">}</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>           <span class="op">}</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>       <span class="op">}</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>   <span class="op">}</span></span></code></pre></div>
<p>any ideas on how to infinitely stack for loops?</p>
<p>I don't know how many digits i need</p>
<p>I'd like to have one method which runs till i stop it and checks every combination</p>
<p>Do you understand my problem?</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">three</span><span class="op">(</span><span class="dt">char</span><span class="op">[]</span> arr<span class="op">){</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span><span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i<span class="op">&lt;</span><span class="dv">95</span><span class="op">;</span> i<span class="op">++){</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>            <span class="cf">for</span><span class="op">(</span><span class="dt">int</span> j <span class="op">=</span> <span class="dv">0</span><span class="op">;</span>j<span class="op">&lt;</span><span class="dv">95</span><span class="op">;</span>j<span class="op">++){</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>                <span class="cf">for</span><span class="op">(</span><span class="dt">int</span> k <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> k<span class="op">&lt;</span><span class="dv">95</span><span class="op">;</span>k<span class="op">++){</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>                    <span class="bu">String</span> a <span class="op">=</span> <span class="st">&quot;&quot;</span><span class="op">+</span>arr<span class="op">[</span>i<span class="op">]+</span>arr<span class="op">[</span>j<span class="op">]+</span>arr<span class="op">[</span>k<span class="op">];</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>                    <span class="cf">if</span><span class="op">(</span><span class="fu">hash2</span><span class="op">(</span>a<span class="op">)%</span>m<span class="op">==</span><span class="dv">0</span><span class="op">){</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>                       <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>a<span class="op">);</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>                    <span class="op">}</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span></code></pre></div>
<p>There must be a better way to check for more digits</p>
</blockquote>
<p>One way - Instead of having all the digits be "on the stack"</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="bu">String</span> a <span class="op">=</span> <span class="st">&quot;&quot;</span><span class="op">+</span>arr<span class="op">[</span>i<span class="op">]+</span>arr<span class="op">[</span>j<span class="op">]+</span>arr<span class="op">[</span>k<span class="op">];</span></span></code></pre></div>
<p>store each loop's state in an object</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> CharIterator <span class="kw">implements</span> <span class="bu">Iterator</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">int</span> i<span class="op">;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">boolean</span> <span class="fu">hasNext</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> i <span class="op">&lt;</span> <span class="dv">95</span><span class="op">;</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">String</span> <span class="fu">next</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>        <span class="dt">char</span> c <span class="op">=</span> <span class="op">(</span><span class="dt">char</span><span class="op">)</span> i<span class="op">;</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>        i<span class="op">++;</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="bu">Character</span><span class="op">.</span><span class="fu">toString</span><span class="op">(</span>c<span class="op">);</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>and then all you need is a way to</p>
<ol type="1">
<li>make an Iterable from that (should be fairly simple)</li>
<li>chain two iterables into one larger iterable</li>
</ol>
<p>basically make this</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="dt">final</span> <span class="kw">class</span> IterableChain<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="kw">implements</span> <span class="bu">Iterable</span><span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="op">&lt;</span>A<span class="op">,</span> B<span class="op">&gt;</span> <span class="fu">IterableChain</span><span class="op">(</span><span class="bu">Iterable</span><span class="op">&lt;</span>A<span class="op">&gt;</span> i1<span class="op">,</span> <span class="bu">Iterable</span><span class="op">&lt;</span>B<span class="op">&gt;</span> i2<span class="op">,</span> Function<span class="op">&lt;</span>A<span class="op">,</span> B<span class="op">,</span> T<span class="op">&gt;</span> combine<span class="op">)</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>and then all you'll need to do is</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="bu">Iterable</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">&gt;</span> iterable <span class="op">=</span> <span class="kw">new</span> <span class="fu">CharIterable</span><span class="op">();</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">10</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>    iterable <span class="op">=</span> <span class="kw">new</span> <span class="fu">IterableChain</span><span class="op">(</span><span class="kw">new</span> <span class="fu">CharIterable</span><span class="op">(),</span> iterable<span class="op">);</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> <span class="op">(</span><span class="bu">String</span> s <span class="op">:</span> iterable<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">...</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>does that make sense?</p>
<blockquote>
<p>Yes, thanks alot!!</p>
</blockquote>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>What are Servlets</title><link>https://mccue.dev/pages/5-31-21-what-are-servlets-and-jetty</link><description></description><pubDate>Mon, 31 May 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>What are Servlets</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">What are Servlets</h1>
</header>
<h2 id="question-from-gergő5263">Question from Gergő#5263</h2>
<blockquote>
<p>What does Servlet mean?</p>
<p>And DispatchServlet</p>
</blockquote>
<p>It's kinda historical.</p>
<p>It's a term for a small, pluggable bit of what would be a larger server.</p>
<p>The only aspect you should need to care about is that it is the interface by which you can attach to Jetty and handle http requests.</p>
<blockquote>
<p>thanks!, and what is jetty? 🧐</p>
</blockquote>
<p>It's a Java web server.</p>
<p>You would have Jetty handle connecting to whatever ports and parsing http requests and your code in the "servlet" would decide how to respond to those requests.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Basic Cleaner Example</title><link>https://mccue.dev/pages/5-7-21-basic-cleaner-example</link><description></description><pubDate>Fri, 07 May 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Basic Cleaner Example</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Basic Cleaner Example</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
```java
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.Cleaner;

<p>public final class HasResource implements AutoCloseable { // This has a Thread backing it so you want to share your cleaner across the whole lib private static final Cleaner CLEANER = Cleaner.create();</p>
<pre><code>private final FileOutputStream outputStream;
private final Cleaner.Cleanable cleanable;

// You don&#39;t want your cleaner task to be a lambda so you don&#39;t accidentally capture a
// ref. to the wrapping object.
private static final class CleanerTask implements Runnable {
    private final FileOutputStream outputStream;

    private CleanerTask(FileOutputStream outputStream) {
        this.outputStream = outputStream;
    }

    @Override
    public void run() {
        try {
            this.outputStream.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

public HasResource() {
    try {
        this.outputStream = new FileOutputStream(&quot;ex.csv&quot;);
    } catch (FileNotFoundException e) {
        throw new RuntimeException(e);
    }
    this.cleanable = CLEANER.register(this, new CleanerTask(this.outputStream));
}

@Override
public void close() {
    // This has &quot;at most once&quot; semantics so if they close it the cleaner won&#39;t run your cleanup logic a second time
    this.cleanable.clean();
}</code></pre>
<p>}</p>
<pre><code>

----
 #### [&lt;- Index](/) 
&lt;script src=&quot;https://utteranc.es/client.js&quot;
        repo=&quot;bowbahdoe/mccue.dev-comments&quot;
        issue-term=&quot;pathname&quot;
        theme=&quot;github-light&quot;
        crossorigin=&quot;anonymous&quot;
        async&gt;
&lt;/script&gt;&lt;style&gt;div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode &gt; span { -webkit-text-size-adjust: none; }</code></pre>
</body>
</html>
]]></content:encoded></item><item><title>The Problem with Annotation Processors</title><link>https://mccue.dev/pages/3-18-21-the-problem-with-annotation-processors</link><description></description><pubDate>Thu, 18 Mar 0021 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>The Problem with Annotation Processors</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">The Problem with Annotation Processors</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Matthias Ngeo</b></div>

<p>For reasons unknown, broaching the subject of annotation processors seem to elicit some primordial fear in developers. People tend to associate annotation processing with borderline witchcraft and sorcery perform-able only by most adept of basement wizards. It doesn’t have to be that way. Annotation processing doesn’t have to be the big scary monster hiding under the bed.</p>
<figure>
  <img src="/pages/3-18-21-bed.png" alt="Image taken from https://sourcesofinsight.com/monsters-under-the-bed/"/>
  <figcaption>Image taken from <a href="Image taken from https://sourcesofinsight.com/monsters-under-the-bed/">https://sourcesofinsight.com/monsters-under-the-bed/</a></figcaption>
</figure>

<p>No doubt, problems with annotation processing <em>do</em> exist, but so do solutions to those problems. One problem that stands out in particular, is the difficulty in unit testing annotation processors. A problem that <a href="https://github.com/Pante/elementary">elementary</a>, a suite of JUnit 5 extensions, solves.</p>
<h2 id="whats-this-annotation-processing-thingamajig">What’s this Annotation Processing Thingamajig?</h2>
<p>For the uninitiated, an annotation processor is similar to a compiler plug-in. Like it’s namesake, it can be called by the compiler to <em>process</em> annotations, i.e. <code>@Nullable</code> during compilation. Said process covers an extremely broad and vague expanse. Everything from simple value validation to a full-blown pluggable type system like the <a href="https://github.com/typetools/checker-framework">checker-framework</a>. A simple <code>@Builder</code> annotation builder to full-blown dependency injection via code generation like <a href="https://github.com/google/dagger">Dagger</a>.</p>
<p>Post Java 9, it resides inside the <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.compiler/module-summary.html"><code>java.compiler</code></a> module. Inside an annotation processor lies the fabled domain of <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.compiler/javax/lang/model/element/package-summary.html"><code>Element</code></a>s and <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.compiler/javax/lang/model/type/package-summary.html"><code>TypeMirror</code></a>s, abstract Syntax Tree (AST) representations of the Java language and counterparts to the reflection framework found in Javaland. <code>Element</code>s represent syntactical constructs such as methods, arrays etc. while <code>TypeMirror</code>s represent, well, types such as reference types (classes) and primitives but we digress.</p>
<h2 id="why-so-difficult">Why So Difficult?</h2>
<p>So what makes testing annotation processing so difficult? In our opinion, everything about the annotation processing environment. We’re not claiming that the environment is some evil grotesque being, it’s actually surprisingly well-designed. The problem lies squarely with the unavailability of the environment outside the compiler. Without its environment, testing an annotation processor is a lost cause.</p>
<p>A good drinking game is taking a shot for each method call in an annotation processor that requires an annotation processing environment.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">karuslabs</span><span class="op">.</span><span class="im">utilitary</span><span class="op">.</span><span class="im">Logger</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">karuslabs</span><span class="op">.</span><span class="im">utilitary</span><span class="op">.</span><span class="im">type</span><span class="op">.</span><span class="im">TypeMirrors</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">Set</span><span class="op">;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">javax</span><span class="op">.</span><span class="im">annotation</span><span class="op">.</span><span class="im">processing</span><span class="op">.</span><span class="im">AbstractProcessor</span><span class="op">;</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">javax</span><span class="op">.</span><span class="im">annotation</span><span class="op">.</span><span class="im">processing</span><span class="op">.</span><span class="im">ProcessingEnvironment</span><span class="op">;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">javax</span><span class="op">.</span><span class="im">annotation</span><span class="op">.</span><span class="im">processing</span><span class="op">.</span><span class="im">RoundEnvironment</span><span class="op">;</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">javax</span><span class="op">.</span><span class="im">lang</span><span class="op">.</span><span class="im">model</span><span class="op">.</span><span class="im">element</span><span class="op">.</span><span class="im">TypeElement</span><span class="op">;</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">javax</span><span class="op">.</span><span class="im">lang</span><span class="op">.</span><span class="im">model</span><span class="op">.</span><span class="im">element</span><span class="op">.</span><span class="im">VariableElement</span><span class="op">;</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">javax</span><span class="op">.</span><span class="im">lang</span><span class="op">.</span><span class="im">model</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">Elements</span><span class="op">;</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> StringFieldLint <span class="kw">extends</span> <span class="bu">AbstractProcessor</span> <span class="op">{</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Elements</span> elements<span class="op">;</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>    TypeMirrors types<span class="op">;</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>    <span class="bu">Logger</span> logger<span class="op">;</span>    </span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">init</span><span class="op">(</span><span class="bu">ProcessingEnvironment</span> environment<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">.</span><span class="fu">init</span><span class="op">(</span>environment<span class="op">);</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>        elements <span class="op">=</span> environment<span class="op">.</span><span class="fu">getElementUtils</span><span class="op">();</span> <span class="co">// (1)</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>        types <span class="op">=</span> <span class="kw">new</span> <span class="fu">TypeMirrors</span><span class="op">(</span>elements<span class="op">,</span> environment<span class="op">.</span><span class="fu">getTypeUtils</span><span class="op">());</span> <span class="co">// (2)</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>        logger <span class="op">=</span> <span class="kw">new</span> <span class="bu">Logger</span><span class="op">(</span>environment<span class="op">.</span><span class="fu">getMessager</span><span class="op">());</span> <span class="co">// (3)</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">boolean</span> <span class="fu">process</span><span class="op">(</span><span class="bu">Set</span><span class="op">&lt;?</span> <span class="kw">extends</span> <span class="bu">TypeElement</span><span class="op">&gt;</span> set<span class="op">,</span> <span class="bu">RoundEnvironment</span> round<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>        var elements <span class="op">=</span> round<span class="op">.</span><span class="fu">getElementsAnnotatedWith</span><span class="op">(</span>Case<span class="op">.</span><span class="fu">class</span><span class="op">);</span> <span class="co">// (4)</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span>var element <span class="op">:</span> elements<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(!(</span>element <span class="kw">instanceof</span> <span class="bu">VariableElement</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a>                logger<span class="op">.</span><span class="fu">error</span><span class="op">(</span>element<span class="op">,</span> <span class="st">&quot;Element is not a variable&quot;</span><span class="op">);</span> <span class="co">// (5)</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a>                <span class="cf">continue</span><span class="op">;</span></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a>            </span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a>            var variable <span class="op">=</span> <span class="op">(</span><span class="bu">VariableElement</span><span class="op">)</span> element<span class="op">;</span></span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(!</span>types<span class="op">.</span><span class="fu">isSameType</span><span class="op">(</span>variable<span class="op">.</span><span class="fu">asType</span><span class="op">(),</span> types<span class="op">.</span><span class="fu">type</span><span class="op">(</span><span class="bu">String</span><span class="op">.</span><span class="fu">class</span><span class="op">)))</span> <span class="op">{</span> <span class="co">// (6) (7) (8)</span></span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a>                logger<span class="op">.</span><span class="fu">error</span><span class="op">(</span>element<span class="op">,</span> <span class="st">&quot;Element is not a string&quot;</span><span class="op">);</span> <span class="co">// (9)</span></span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a>                <span class="cf">continue</span><span class="op">;</span></span>
<span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb1-37"><a href="#cb1-37" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-38"><a href="#cb1-38" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">false</span><span class="op">;</span></span>
<span id="cb1-39"><a href="#cb1-39" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-40"><a href="#cb1-40" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Pretty much everything requires an annotation processing environment as illustrated above.</p>
<p>At this junction, we have four solutions to overcome this pickle:</p>
<ul>
<li>Don’t bother with unit testing</li>
<li>Wait for something, anything to happen</li>
<li>Mock/re-implement the annotation processing environment</li>
<li>Smuggle the annotation processing environment out of the compiler</li>
</ul>
<p>To keep a long story short, we ended up becoming smugglers.</p>
<h2 id="smugglers-discovery">Smuggler’s Discovery</h2>
<p>While trawling the web, we discovered Google’s <a href="https://github.com/google/compile-testing">compile-testing</a> project, a hidden gem buried beneath the swathes of GitHub projects. Through some clever hacks, the project managed to provide an annotation processing environment for unit tests albeit a little lackluster and limited. Exploring the project, it became obvious that it wasn’t the panacea that we had hoped. The project suffered from a few limitations that we weren’t able to stomach:</p>
<ul>
<li>Supports only JUnit 4. The annotation processing environment is only available through a JUnit rule, something that is no longer supported in JUnit 5. We have been using JUnit 5 for the longest time and don’t intend to downgrade anytime soon.</li>
<li>The utilities for working with the annotation processing environment is limited. It <em>works</em>, but it can be significantly more ergonomic.</li>
<li>Inability to traverse the <code>Element</code>s and <code>TypeMirror</code>s of compiled files in a test. This is essential to allow compiled files to be used as test cases.</li>
<li>Scope limitation of the annotation processing environment. The annotation processing environment is limited to the scope of a test method. This is inconvenient as initialization of test state cannot be shared between multiple tests. Furthermore, the design lends itself to unexpected behaviour.</li>
</ul>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> SomeTest <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  <span class="at">@Rule</span> CompilationRule rule <span class="op">=</span> <span class="kw">new</span> <span class="fu">CompilationRule</span><span class="op">();</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  <span class="bu">Types</span> types <span class="op">=</span> rule<span class="op">.</span><span class="fu">getTypes</span><span class="op">();</span> <span class="co">// Throws an exception when the method can be called</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>  </span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>  <span class="at">@Test</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> <span class="fu">test</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">...</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This isn’t to say that the project is <em>bad</em>, just that our objectives are different. In fact, some parts of elementary is based on compile-testing. As its name implies, compile-testing focuses on testing the compilation of code, not annotation processing. That’s not our objective. Our objective is to simplify unit testing annotation processors. Thus, after a healthy dose of <em>“Hold my beer”</em> and <a href="https://docs.oracle.com/javase/8/docs/api/java/util/logging/package-summary.html"><em>Not Invented Here Syndrome</em></a>, the elementary project was conceived.</p>
<h2 id="elementary-my-dear-watson">Elementary, My Dear Watson</h2>
<p>With compile-testing as a foundation, we embarked on a quest to bring Elementary to life. Starting with a clean slate blessed us with the freedom to make decisions that would otherwise incite an angry mob with pitchforks and torches:</p>
<ul>
<li>Support only Java 11 &amp; above. The module system in Java 9 introduced some breaking changes to the <code>jdk.compiler</code> module and <code>ClassLoader</code>s. We don't want to deal with that.</li>
<li>Support only JUnit 5. We do not want to support a JUnit 4 equivalent that we do not use.</li>
</ul>
<p>Our experience working on <a href="https://github.com/Pante/chimera">Chimera code generation tool</a> told us that tests for annotation processors fell into the classic black-box and white-box testing categories. For small and/or simple annotation processors, it was more efficient to invoke the annotation processor inside a compiler against sample Java source files. As the complexity and size of an annotation processor increases, running the annotation processor against sample files yields diminishing returns. It will be far less tedious to isolate and test the individual logical components. Two different categories with two completely different sets of requirements.</p>
<h2 id="box-of-fun"> Box of Fun Things </h2>

<p>Black-box testing annotation processors <em>can</em> be fun. It <em>doesn’t</em> have to be a myriad of set-up, tear-down and configuration. Not accordingly to <code>JavacExtension</code> at least. For each test, <code>JavacExtension</code> compiles a suite of test cases with the given annotation processor(s). The results of the compilation is then funneled to the test method for subsequent assertions. All configuration is handled via annotations with no additional set-up or tear-down required.</p>
<blockquote>
<p>They say seeing is believing so let’s get on with the seeing.</p>
</blockquote>
<p>Our imaginary annotation processor is fairly straightforward. All it does is check whether an element that is annotated with <code>@Case</code> is also a string field. If an element isn't a string or variable, an error message is printed. Since it's <em>that</em> straightforward, just black-box testing our annotation processor is enough.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="at">@SupportedAnnotationTypes</span><span class="op">({</span><span class="st">&quot;*&quot;</span><span class="op">})</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> ImaginaryProcessor <span class="kw">extends</span> AnnotationProcessor <span class="op">{</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">boolean</span> <span class="fu">process</span><span class="op">(</span><span class="bu">Set</span><span class="op">&lt;?</span> <span class="kw">extends</span> <span class="bu">TypeElement</span><span class="op">&gt;</span> set<span class="op">,</span> <span class="bu">RoundEnvironment</span> round<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>        var elements <span class="op">=</span> round<span class="op">.</span><span class="fu">getElementsAnnotatedWith</span><span class="op">(</span>Case<span class="op">.</span><span class="fu">class</span><span class="op">);</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> <span class="op">(</span>var element <span class="op">:</span> elements<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>element <span class="kw">instanceof</span> <span class="bu">VariableElement</span><span class="op">)</span>) <span class="op">{</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>                var variable <span class="op">=</span> <span class="op">(</span><span class="bu">VariableElement</span><span class="op">)</span> element<span class="op">;</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>                <span class="cf">if</span> <span class="op">(!</span>types<span class="op">.</span><span class="fu">isSameType</span><span class="op">(</span>variable<span class="op">.</span><span class="fu">asType</span><span class="op">(),</span> types<span class="op">.</span><span class="fu">type</span><span class="op">(</span><span class="bu">String</span><span class="op">.</span><span class="fu">class</span><span class="op">)))</span> <span class="op">{</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>                    logger<span class="op">.</span><span class="fu">error</span><span class="op">(</span>element<span class="op">,</span> <span class="st">&quot;Element is not a string&quot;</span><span class="op">);</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>                logger<span class="op">.</span><span class="fu">error</span><span class="op">(</span>element<span class="op">,</span> <span class="st">&quot;Element is not a variable&quot;</span><span class="op">);</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">false</span><span class="op">;</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Testing our imaginary annotation processor isn’t too difficult either. All we need to do is to sprinkle a few annotations on the test class, create some test cases, check the compilation results, and Voila! We’re done.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">karuslabs</span><span class="op">.</span><span class="im">elementary</span><span class="op">.</span><span class="im">Results</span><span class="op">;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">karuslabs</span><span class="op">.</span><span class="im">elementary</span><span class="op">.</span><span class="im">junit</span><span class="op">.</span><span class="im">JavacExtension</span><span class="op">;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">karuslabs</span><span class="op">.</span><span class="im">elementary</span><span class="op">.</span><span class="im">junit</span><span class="op">.</span><span class="im">annotations</span><span class="op">.</span><span class="im">Case</span><span class="op">;</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">karuslabs</span><span class="op">.</span><span class="im">elementary</span><span class="op">.</span><span class="im">junit</span><span class="op">.</span><span class="im">annotations</span><span class="op">.</span><span class="im">Classpath</span><span class="op">;</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">karuslabs</span><span class="op">.</span><span class="im">elementary</span><span class="op">.</span><span class="im">junit</span><span class="op">.</span><span class="im">annotations</span><span class="op">.</span><span class="im">Options</span><span class="op">;</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">karuslabs</span><span class="op">.</span><span class="im">elementary</span><span class="op">.</span><span class="im">junit</span><span class="op">.</span><span class="im">annotations</span><span class="op">.</span><span class="im">Processors</span><span class="op">;</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a><span class="at">@ExtendWith</span><span class="op">(</span>JavacExtension<span class="op">.</span><span class="fu">class</span><span class="op">)</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a><span class="at">@Options</span><span class="op">(</span><span class="st">&quot;-Werror&quot;</span><span class="op">)</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a><span class="at">@Processors</span><span class="op">({</span>ImaginaryProcessor<span class="op">.</span><span class="fu">class</span><span class="op">})</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a><span class="at">@Classpath</span><span class="op">(</span><span class="st">&quot;my.package.ValidCase&quot;</span><span class="op">)</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> ImaginaryTest <span class="op">{</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Test</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">process_string_field</span><span class="op">(</span>Results results<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>        <span class="fu">assertEquals</span><span class="op">(</span><span class="dv">0</span><span class="op">,</span> results<span class="op">.</span><span class="fu">find</span><span class="op">().</span><span class="fu">errors</span><span class="op">().</span><span class="fu">count</span><span class="op">());</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Test</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Classpath</span><span class="op">(</span><span class="st">&quot;my.package.InvalidCase&quot;</span><span class="op">)</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">process_int_field</span><span class="op">(</span>Results results<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a>        <span class="fu">assertEquals</span><span class="op">(</span><span class="dv">1</span><span class="op">,</span> results<span class="op">.</span><span class="fu">find</span><span class="op">().</span><span class="fu">errors</span><span class="op">().</span><span class="fu">contains</span><span class="op">(</span><span class="st">&quot;Element is not a string&quot;</span><span class="op">).</span><span class="fu">count</span><span class="op">());</span></span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Let’s break down the code snippet.</p>
<ul>
<li>By annotating the test class with <code>@Options</code>, we can specify the <a href="https://docs.oracle.com/en/java/javase/11/tools/javac.html">compiler flags</a> used when compiling the test cases. In this snippet, <code>-Werror</code> indicates that all warnings will be treated as errors.</li>
<li>To specify which annotation processor(s) is to be invoked with the compiler, we can annotate the test class with <code>@Processors</code>. No prizes for correctly guessing which annotation processor in this snippet.</li>
<li>Test cases can be included for compilation by annotating the test class with either <code>@Classpath</code> or <code>@Inline</code>. Java source files on the classpath can be included using <code>@Classpath</code> while strings inside <code>@Inline</code> can be transformed into an inline source file for compilation. In this snippet, both <a href="https://github.com/Pante/elementary/blob/master/elementary/src/test/resources/ValidCase.java"><code>ValidCase</code></a> and <a href="https://github.com/Pante/elementary/blob/master/elementary/src/test/resources/InvalidCase.java"><code>InvalidCase</code></a> is included for compilation.</li>
<li>An annotation’s scope is tied to its target’s scope. If a test class is annotated, the annotation will be applied for all test methods in that class. On the same note, an annotation on a test method will only be applied on said method.</li>
<li><code>Results</code> represent the results of a compilation. We can specify <code>Results</code> as a parameter of test methods to obtain the compilation results. In this snippet, <code>process_string_field(...)</code> will receive the results for <code>ValidCase</code> while <code>process_int_field(...)</code> will receive the results for both <code>ValidCase</code> and <code>InvalidCase</code>.</li>
</ul>
<h2 id="pandoras-box"> Pandora’s Box </h2>

<p>This is where things become really interesting. White-box testing isn’t as simple as invoking an annotation processor since the possibilities of what a test is trying to prove is unlimited. In a black-box test, we need only to prove that the compilation results of a known annotation processor against a fixed number of files matches certain criterion. On the contrary, in a white-box test, we do not know why, what and how a component is being tested. The best we can do is make the annotation processing environment accessible inside the test class.</p>
<blockquote>
<p>“It can’t be that difficult to allow class scoped annotation processing environments, compile-testing already does that.”</p>
</blockquote>
<p>We too, initially felt the same way and boy, were we wrong. While compile-testing does provide an annotation processing environment, it is limited to the scope of a test method. Not being able to access said environment outside of methods means repetitive and verbose initialization code, which blows. Sadly, we couldn’t just tweak compile-testing’s trick either as it was found to be incompatible with our objective.</p>
<p>The secret sauce behind compile-testing is actually pretty straightforward. Each test method is intercepted by a <a href="https://github.com/google/compile-testing/blob/master/src/main/java/com/google/testing/compile/CompilationRule.java">JUnit rule</a> and wrapped in an annotation processor that invokes the method during processing. The test is subsequently executed inside a compiler that the JUnit rule invokes. Unfortunately, in this technique, an annotation processing environment is available only when a test method. It isn’t possible to tweak the technique to intercept the creation of a test instance and inject the test instance inside an annotation processor either due to the constraints of the JUnit lifecycle.</p>
<p>A great deal of time spent at the drawing board later, we succeeded in creating the <code>ToolsExtension</code>. This extension exploited the fact that a test instance only needed access to an annotation processing environment. Tests didn't need to be executed inside an annotation processor. Once we established that, our trick was run a compiler with a blocking annotation processor on a daemon thread before each test instance was created. With compilation suspended inside the processor, the environment is made accessible to the test instance on the main thread. Only after all tests has been executed does compilation resume.</p>
<figure>
  <img width="100%" src="/pages/3-18-21-diagram.png" alt="Here’s a poorly drawn MS Paint diagram illustrating the entire process"/>
  <figcaption>Here’s a poorly drawn MS Paint diagram illustrating the entire process</figcaption>
</figure>

<p>Let’s pretend that as a result of the imaginary processor we described in <a href="#box-of-fun">Box of Fun Things</a> having grown in scope and size, it was refactored into multiple components, one of which checks if an element is a string variable like the original annotation processor.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Lint <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">final</span> TypeMirrors types<span class="op">;</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">final</span> <span class="bu">TypeMirror</span> expectedType<span class="op">;</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>    <span class="fu">Lint</span><span class="op">(</span>TypeMirrors types<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">types</span> <span class="op">=</span> types<span class="op">;</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">expectedType</span> <span class="op">=</span> types<span class="op">.</span><span class="fu">type</span><span class="op">(</span><span class="bu">String</span><span class="op">.</span><span class="fu">class</span><span class="op">);</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">boolean</span> <span class="fu">lint</span><span class="op">(</span><span class="bu">Element</span> element<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(!(</span>element <span class="kw">instanceof</span> <span class="bu">VariableElement</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">false</span><span class="op">;</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a>        var variable <span class="op">=</span> <span class="op">(</span><span class="bu">VariableElement</span><span class="op">)</span> element<span class="op">;</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> types<span class="op">.</span><span class="fu">isSameType</span><span class="op">(</span>expectedType<span class="op">,</span> variable<span class="op">.</span><span class="fu">asType</span><span class="op">());</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Using the <code>ToolsExtension</code> to test the annotation processor yields the following code snippet:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">karuslabs</span><span class="op">.</span><span class="im">elementary</span><span class="op">.</span><span class="im">junit</span><span class="op">.</span><span class="im">Cases</span><span class="op">;</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">karuslabs</span><span class="op">.</span><span class="im">elementary</span><span class="op">.</span><span class="im">junit</span><span class="op">.</span><span class="im">Tools</span><span class="op">;</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">karuslabs</span><span class="op">.</span><span class="im">elementary</span><span class="op">.</span><span class="im">junit</span><span class="op">.</span><span class="im">ToolsExtension</span><span class="op">;</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">karuslabs</span><span class="op">.</span><span class="im">elementary</span><span class="op">.</span><span class="im">junit</span><span class="op">.</span><span class="im">annotations</span><span class="op">.</span><span class="im">Inline</span><span class="op">;</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">karuslabs</span><span class="op">.</span><span class="im">utilitary</span><span class="op">.</span><span class="im">type</span><span class="op">.</span><span class="im">TypeMirrors</span><span class="op">;</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a><span class="at">@ExtendWith</span><span class="op">(</span>ToolsExtension<span class="op">.</span><span class="fu">class</span><span class="op">)</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a><span class="at">@Inline</span><span class="op">(</span>name <span class="op">=</span> <span class="st">&quot;Samples&quot;</span><span class="op">,</span> source <span class="op">=</span> <span class="op">{</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;import com.karuslabs.elementary.junit.annotations.Case;&quot;</span><span class="op">,</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;&quot;</span><span class="op">,</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;class Samples {&quot;</span><span class="op">,</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;  @Case(</span><span class="sc">\&quot;</span><span class="st">first</span><span class="sc">\&quot;</span><span class="st">) String first;&quot;</span><span class="op">,</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;  @Case String second() { return </span><span class="sc">\&quot;\&quot;</span><span class="st">;}&quot;</span><span class="op">,</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;}&quot;</span><span class="op">})</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> ToolsExtensionExampleTest <span class="op">{</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a>    Lint lint <span class="op">=</span> <span class="kw">new</span> <span class="fu">Lint</span><span class="op">(</span>Tools<span class="op">.</span><span class="fu">typeMirrors</span><span class="op">());</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Test</span></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">lint_string_variable</span><span class="op">(</span>Cases cases<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a>        var first <span class="op">=</span> cases<span class="op">.</span><span class="fu">one</span><span class="op">(</span><span class="st">&quot;first&quot;</span><span class="op">);</span></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a>        <span class="fu">assertTrue</span><span class="op">(</span>lint<span class="op">.</span><span class="fu">lint</span><span class="op">(</span>first<span class="op">));</span></span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Test</span></span>
<span id="cb6-26"><a href="#cb6-26" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">lint_method_that_returns_string</span><span class="op">(</span>Cases cases<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-27"><a href="#cb6-27" aria-hidden="true" tabindex="-1"></a>        var second <span class="op">=</span> cases<span class="op">.</span><span class="fu">get</span><span class="op">(</span><span class="dv">1</span><span class="op">);</span></span>
<span id="cb6-28"><a href="#cb6-28" aria-hidden="true" tabindex="-1"></a>        <span class="fu">assertFalse</span><span class="op">(</span>lint<span class="op">.</span><span class="fu">lint</span><span class="op">(</span>second<span class="op">));</span></span>
<span id="cb6-29"><a href="#cb6-29" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb6-30"><a href="#cb6-30" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb6-31"><a href="#cb6-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Let’s break down the code snippet:</p>
<ul>
<li>By annotating the class with <code>@Inline</code> we can specify an inline Java source file which <code>ToolsExtension</code> includes for compilation.</li>
<li>The annotation processing environment can be accessed via either the <code>Tools</code> class or dependency injection into the test class's constructor or test methods. In this case, we access the current <code>TypeMirrors</code> using the static method on <code>Tools</code>.</li>
<li>An in-depth explanation for both <code>@Case</code> and <code>Cases</code> will be provided in the following section. For now, it's just the mechanism used to find elements in compiled files.</li>
</ul>
<h2 id="the-case-for-cases">The Case for Cases</h2>
<p>With the completion of <code>ToolsExtension</code>, we succeeded in our quest to smuggle an annotation processing environment out of the compiler. Yet one final piece in the puzzle still remains. How do we create those elements to test our code against? The <code>jdk.compiler</code> module doesn't provide a way to create elements. While mocking an <code>Element</code> is possible it is far from developer-friendly. Not only is the initialization verbose, unwieldy and convoluted, it is also difficult to guarantee that the mocked element's behaviour matches its actual counterpart. We can't look to compile=testing for guidance either since it doesn't provide anything like that.</p>
<p>After much headache, we managed to find the missing piece. Let’s have the compiler transform our test cases written in idiomatic Java into elements for us. That way, we avoid the mess surrounding the initialization of elements and the resultant code is far easier to understand. To achieve that, we required some way to fetch elements from the compiler. After further refinement of the concept, we eventually developed the <code>Cases</code> class and corresponding <code>@Case</code> annotation.</p>
<p>Returning to our code snippet from <a href="#pandoras-box">Pandora’s Box</a>, let’s analyze it in greater detail.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">karuslabs</span><span class="op">.</span><span class="im">elementary</span><span class="op">.</span><span class="im">junit</span><span class="op">.</span><span class="im">Cases</span><span class="op">;</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">karuslabs</span><span class="op">.</span><span class="im">elementary</span><span class="op">.</span><span class="im">junit</span><span class="op">.</span><span class="im">Tools</span><span class="op">;</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">karuslabs</span><span class="op">.</span><span class="im">elementary</span><span class="op">.</span><span class="im">junit</span><span class="op">.</span><span class="im">ToolsExtension</span><span class="op">;</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">karuslabs</span><span class="op">.</span><span class="im">elementary</span><span class="op">.</span><span class="im">junit</span><span class="op">.</span><span class="im">annotations</span><span class="op">.</span><span class="im">Inline</span><span class="op">;</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">com</span><span class="op">.</span><span class="im">karuslabs</span><span class="op">.</span><span class="im">utilitary</span><span class="op">.</span><span class="im">type</span><span class="op">.</span><span class="im">TypeMirrors</span><span class="op">;</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a><span class="at">@ExtendWith</span><span class="op">(</span>ToolsExtension<span class="op">.</span><span class="fu">class</span><span class="op">)</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a><span class="at">@Inline</span><span class="op">(</span>name <span class="op">=</span> <span class="st">&quot;Samples&quot;</span><span class="op">,</span> source <span class="op">=</span> <span class="op">{</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;import com.karuslabs.elementary.junit.annotations.Case;&quot;</span><span class="op">,</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;&quot;</span><span class="op">,</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;class Samples {&quot;</span><span class="op">,</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;  @Case(</span><span class="sc">\&quot;</span><span class="st">first</span><span class="sc">\&quot;</span><span class="st">) String first;&quot;</span><span class="op">,</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;  @Case String second() { return </span><span class="sc">\&quot;\&quot;</span><span class="st">;}&quot;</span><span class="op">,</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;}&quot;</span><span class="op">})</span></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> ToolsExtensionExampleTest <span class="op">{</span></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true" tabindex="-1"></a>    Lint lint <span class="op">=</span> <span class="kw">new</span> <span class="fu">Lint</span><span class="op">(</span>Tools<span class="op">.</span><span class="fu">typeMirrors</span><span class="op">());</span></span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Test</span></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">lint_string_variable</span><span class="op">(</span>Cases cases<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true" tabindex="-1"></a>        var first <span class="op">=</span> cases<span class="op">.</span><span class="fu">one</span><span class="op">(</span><span class="st">&quot;first&quot;</span><span class="op">);</span></span>
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true" tabindex="-1"></a>        <span class="fu">assertTrue</span><span class="op">(</span>lint<span class="op">.</span><span class="fu">lint</span><span class="op">(</span>first<span class="op">));</span></span>
<span id="cb7-23"><a href="#cb7-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-24"><a href="#cb7-24" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb7-25"><a href="#cb7-25" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Test</span></span>
<span id="cb7-26"><a href="#cb7-26" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="fu">lint_method_that_returns_string</span><span class="op">(</span>Cases cases<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-27"><a href="#cb7-27" aria-hidden="true" tabindex="-1"></a>        var second <span class="op">=</span> cases<span class="op">.</span><span class="fu">get</span><span class="op">(</span><span class="dv">1</span><span class="op">);</span></span>
<span id="cb7-28"><a href="#cb7-28" aria-hidden="true" tabindex="-1"></a>        <span class="fu">assertFalse</span><span class="op">(</span>lint<span class="op">.</span><span class="fu">lint</span><span class="op">(</span>second<span class="op">));</span></span>
<span id="cb7-29"><a href="#cb7-29" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-30"><a href="#cb7-30" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb7-31"><a href="#cb7-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<ul>
<li>By annotating a test case with <code>@Case</code> inside a Java source file, we can fetch its corresponding element from <code>Cases</code>. A <code>@Case</code> may also contain a label to simplify retrieval.</li>
<li>Through <code>Cases</code>, we can fetch elements by either the label or index of the case. We can obtain an instance of <code>Cases</code> via <code>Tools.cases</code> or like in this code snippet, through dependency injection.</li>
</ul>
<h2 id="idea-graveyard">Idea Graveyard</h2>
<p>As mentioned at the beginning of this article, we explored a few other avenues which eventually led to dead-ends. We thought them to be interesting enough to discuss in the following sections. Most of them ended up getting shelved due to the impracticality and unacceptable trade-offs for the solution.</p>
<p>Not testing annotation processors goes without saying to be a terrible choice. Just because testing them is difficult doesn’t give us the liberty of skipping that. The problems will only worsen over time if we choose to take the easy route out. Furthermore, most annotation processors usually do code generation and static type analysis. Both of which are extremely difficult to troubleshoot.</p>
<blockquote>
<p>“Good things come to those wait. But better things come to those who work for it.”</p>
</blockquote>
<p>Had <a href="https://openjdk.java.net/jeps/119">JEP 119: javax.lang.model Implementation Backed by Core Reflection</a> been shipped with JDK 8, I highly doubt elementary would have even been conceived. It solved the issue with accessing an annotation processing environment outside of a compiler by providing a standard implementation. Sadly, it was shelved and future efforts seems to have stalled. A wait and see approach to unit testing annotation processors would thus be unfeasible as there isn’t anything to wait on.</p>
<p>A problem more difficult than testing annotation processing is trying to mock/re-implement the annotation processing environment. Since elements represent an AST for the Java language, we need to be intimate with the language specification to guarantee that the behaviour of mocked/re-implemented elements do not deviate from the original. This honestly makes testing annotation processors seem like a Disney fairy-tale, we don’t want to touch that even with a ten-foot pole. A few existing re-implementations do exist but seem to have been long-abandoned for years. In the end, it boils down to the troubles outweighing the benefits that led us to abandon this avenue.</p>
<h2 id="final-thoughts">Final Thoughts</h2>
<p>We’ve reached the end of our journey to simplify the testing of annotation processors. Looking back, it has been an absolute blast working on the project. How adopted this project is still remains to be seen. But if anything, I hope that this article encouraged you start playing around with annotation processors.</p>
<p>In summary, Elementary introduces:</p>
<ul>
<li>The <code>JavacExtension</code> for black-box testing and testing of simple annotation processors.</li>
<li>A class-scoped annotation processing environment for test classes annotated with <code>ToolsExtension</code>. Utilities for fetching elements from the compiler to the test class</li>
</ul>
<p>That said, this is only beginning of yet another journey. A journey that I am hopeful will bring many new feature and improvements to elementary in the time to come. Until the next time, happy coding!</p>
<hr />
<p>Article was originally published on <a href="https://matthiasngeo.medium.com/the-problem-with-annotation-processors-802548a3bfdb">Medium</a>. <em>Shameless advertising</em> This article is based on Elementary, <a href="https://github.com/Pante/elementary">https://github.com/Pante/elementary</a>.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Should array variable names be plural</title><link>https://mccue.dev/pages/3-23-19-should-array-names-be-plural</link><description></description><pubDate>Sat, 23 Mar 0019 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Should array variable names be plural</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Should array variable names be plural</h1>
</header>
<h2 id="question-from-abdul4709">Question from Abdul#4709</h2>
<blockquote>
<p>Just wondering for arrays is it considered a better practice to keep the var names plural?</p>
<p>Or I guess it depends on language?</p>
</blockquote>
<p>For me, when I name a collection of things it usually ends up that using plural describes it better, but it all depends on what you are naming.</p>
<p>I wouldn't make a collection of cats and call it <code>cat</code>. That's just confusing. But if you are keeping some messages in a queue <code>messageQueue</code> works as a name since having the word queue implies both the direction data flows and the idea of possible plurality.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How to do abstractions in JS</title><link>https://mccue.dev/pages/3-22-19-how-to-do-abstractions-in-js</link><description></description><pubDate>Fri, 22 Mar 0019 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How to do abstractions in JS</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How to do abstractions in JS</h1>
</header>
<h2 id="question-from-forkyfork7118">Question from ForkyFork#7118</h2>
<blockquote>
<p>javascript does not have good OOP, no types</p>
<p>e.g. how are you going to do abstraction in js? interfaces?</p>
</blockquote>
<p>You really haven't been around the block enough to compare languages to Java.</p>
<p>So here is the issue with that as a question.</p>
<p>When you say "abstraction", what you are referring to are the static typing constructs in Java that allow you to declare the relationships between objects. Just because JS lacks the ability to declare those constructs in a way that can be checked by a compiler doesn't mean you can't write abstracted code in it.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Should a game use mutable state</title><link>https://mccue.dev/pages/3-22-19-should-a-game-use-mutable-state</link><description></description><pubDate>Fri, 22 Mar 0019 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Should a game use mutable state</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Should a game use mutable state</h1>
</header>
<h2 id="question-from-decentdrei7560">Question from decentDrei#7560</h2>
<blockquote>
<p>Would you say that a basic game, like a canvas game should use mutable state?</p>
<p>2d physics. Standard side-scroll</p>
</blockquote>
<p>Pretty solidly going to say not to worry about it. Games were made forever with a global mutable area for gamestate.</p>
<p><a href="https://youtu.be/aKLntZcp27M">https://youtu.be/aKLntZcp27M</a></p>
<p>This talk has some good pointers on game dev. It's part of a much larger topic but the speaker is good. And there are gradients to avoiding mutation. Don't avoid it like the plague, just keep it in mind.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>JS vs Java - dynamic typing</title><link>https://mccue.dev/pages/3-22-19-js-vs-java</link><description></description><pubDate>Fri, 22 Mar 0019 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>JS vs Java - dynamic typing</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">JS vs Java - dynamic typing</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
## Conversation with somebody#0002

<p>So as far as JS and Java are concerned the syntaxes of the two languages are very similar but the semantics between the two vary wildly even discounting browser weirdness.</p>
<blockquote>
<p>but for simple things it's very similar. small algorithms and things like that</p>
</blockquote>
<p>For simple things all languages are similar</p>
<p>okay, so here's a bet. I will write a bit of javascript code. very small, very simple.</p>
<p>You will try to write some mock Java that does the same thing.</p>
<p>I bet that you will find it harder to do</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">function</span> <span class="fu">upperCaseName</span>(entity) {</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> {<span class="op">...</span>entity<span class="op">,</span> <span class="dt">name</span><span class="op">:</span> entity<span class="op">.</span><span class="at">name</span><span class="op">.</span><span class="fu">toUpperCase</span>() }</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>}</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> dog <span class="op">=</span> { <span class="dt">name</span><span class="op">:</span> <span class="st">&quot;Fido&quot;</span><span class="op">,</span> <span class="dt">favorite_toy</span><span class="op">:</span> <span class="st">&quot;Squeeks&quot;</span> }</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> person { <span class="dt">name</span><span class="op">:</span> <span class="st">&quot;Bob&quot;</span><span class="op">,</span> <span class="dt">majored_in</span><span class="op">:</span> <span class="st">&quot;Physics&quot;</span> <span class="op">,</span> <span class="dt">age</span><span class="op">:</span> <span class="dv">30</span> }</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="fu">upperCaseName</span>(dog) <span class="co">//  { name: &quot;FIDO&quot;, favorite_toy: &quot;Squeeks&quot; }</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="fu">upperCaseName</span>(person) <span class="co">// { name: &quot;BOB&quot;, majored_in: &quot;Physics&quot; , age: 30 }</span></span></code></pre></div>
<blockquote>
<p>Objects are a JS-specific thing, but... that should be doable in Java. won't look nice, won't behave well, but it'll be doable</p>
</blockquote>
<p>oh so the thing that most libraries in JS use as their primary data representation are JS specific?</p>
<blockquote>
<p>yes</p>
<p>in Java you'd use a POD for them</p>
<p>in JS you don't want that overhead, in Java it's kinda unavoidable</p>
</blockquote>
<p>POD?</p>
<blockquote>
<p>plain old data</p>
</blockquote>
<p>You mean a class with getters and setters right? That won't work here.</p>
<p>Dynamic languages have a whole set of design patterns unique to their inherit flexibility in the same way Functional Languages like Haskell have a whole set of design patterns unique to their inherit restrictions.</p>
<p>Javascript is dynamic and weakly typed and Java is static and strongly typed. The second bit there is very important because it clues to the underlying semantics of the language.</p>
<blockquote>
<p>yeah, of course.</p>
<p>also kinda working in Java:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">Map</span><span class="op">;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">HashMap</span><span class="op">;</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>      <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="fu">upperCaseName</span><span class="op">(</span><span class="kw">new</span> <span class="bu">HashMap</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">,</span> <span class="bu">Object</span><span class="op">&gt;()</span> <span class="op">{{</span> <span class="fu">put</span><span class="op">(</span><span class="st">&quot;name&quot;</span><span class="op">,</span> <span class="st">&quot;Fido&quot;</span><span class="op">);</span> <span class="fu">put</span><span class="op">(</span><span class="st">&quot;favorite_toy&quot;</span><span class="op">,</span> <span class="st">&quot;Squeeks&quot;</span><span class="op">);</span> <span class="op">}}));</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">static</span> <span class="bu">Map</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">,</span> <span class="bu">Object</span><span class="op">&gt;</span> <span class="fu">upperCaseName</span><span class="op">(</span><span class="bu">Map</span><span class="op">&lt;</span><span class="bu">String</span><span class="op">,</span> <span class="bu">Object</span><span class="op">&gt;</span> map<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>map<span class="op">.</span><span class="fu">containsKey</span><span class="op">(</span><span class="st">&quot;name&quot;</span><span class="op">)</span> <span class="op">&amp;&amp;</span> map<span class="op">.</span><span class="fu">get</span><span class="op">(</span><span class="st">&quot;name&quot;</span><span class="op">)</span> <span class="kw">instanceof</span> <span class="bu">String</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>          map<span class="op">.</span><span class="fu">put</span><span class="op">(</span><span class="st">&quot;name&quot;</span><span class="op">,</span> <span class="op">((</span><span class="bu">String</span><span class="op">)</span> map<span class="op">.</span><span class="fu">get</span><span class="op">(</span><span class="st">&quot;name&quot;</span><span class="op">)).</span><span class="fu">toUpperCase</span><span class="op">());</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> map<span class="op">;</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>In Javascript saying <code>class</code> has an insanely different meaning than in Javascript.</p>
<p>In java when you say class you are declaring a template for a concrete object to be created later. You are saying that your object will have these slots, that your object will have these methods that will work on said slots of data, and you define how the object will be constructed.</p>
<p>But in Javascript you aren't doing that. In Javascript you are actually creating an object.</p>
<p>That object is the "prototype" for new objects to be created from and you are saying "hey just copy this object"</p>
<blockquote>
<p>that's the prototype, not the class</p>
</blockquote>
<p>There is no such thing as the class Not in any form that isn't syntax sugar.</p>
<p>The main similarity between JS and Java is the syntax, which was done on purpose. Hence the misleading name of JavaScript.</p>
<p>The whole point was to <em>look</em> like Have at first glance but at its core JS is more a badly implemented lisp than anything else.</p>
<p>Now I am going to do the dog example in idiomatic java give me a few minutes</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="im">java</span><span class="op">.</span><span class="im">util</span><span class="op">.</span><span class="im">Objects</span><span class="op">;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">interface</span> HasName<span class="op">&lt;</span>T <span class="kw">extends</span> HasName<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    <span class="bu">String</span> <span class="fu">getName</span><span class="op">();</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    T <span class="fu">withName</span><span class="op">(</span><span class="bu">String</span> name<span class="op">);</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Dog <span class="kw">implements</span> HasName<span class="op">&lt;</span>Dog<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="bu">String</span> name<span class="op">;</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">final</span> <span class="bu">String</span> favoriteToy<span class="op">;</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>    <span class="fu">Dog</span><span class="op">(</span><span class="bu">String</span> name<span class="op">,</span> <span class="bu">String</span> favoriteToy<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>        Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>name<span class="op">,</span> <span class="st">&quot;Name should not be null&quot;</span><span class="op">);</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>        Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>favoriteToy<span class="op">,</span> <span class="st">&quot;Favorite Toy should not be null&quot;</span><span class="op">);</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">name</span> <span class="op">=</span> name<span class="op">;</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">favoriteToy</span> <span class="op">=</span> favoriteToy<span class="op">;</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">String</span> <span class="fu">getName</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">name</span><span class="op">;</span></span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> Dog <span class="fu">withName</span><span class="op">(</span><span class="bu">String</span> name<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Dog</span><span class="op">(</span>name<span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">favoriteToy</span><span class="op">);</span></span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">String</span> <span class="fu">getFavoriteToy</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">favoriteToy</span><span class="op">;</span></span>
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-32"><a href="#cb3-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-33"><a href="#cb3-33" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> Dog <span class="fu">withFavoriteToy</span><span class="op">(</span><span class="bu">String</span> favoriteToy<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-34"><a href="#cb3-34" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Dog</span><span class="op">(</span><span class="kw">this</span><span class="op">.</span><span class="fu">name</span><span class="op">,</span> favoriteToy<span class="op">);</span></span>
<span id="cb3-35"><a href="#cb3-35" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-36"><a href="#cb3-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-37"><a href="#cb3-37" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb3-38"><a href="#cb3-38" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">boolean</span> <span class="fu">equals</span><span class="op">(</span><span class="bu">Object</span> o<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-39"><a href="#cb3-39" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span><span class="kw">this</span> <span class="op">==</span> o<span class="op">)</span> <span class="cf">return</span> <span class="kw">true</span><span class="op">;</span></span>
<span id="cb3-40"><a href="#cb3-40" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>o <span class="op">==</span> <span class="kw">null</span> <span class="op">||</span> <span class="fu">getClass</span><span class="op">()</span> <span class="op">!=</span> o<span class="op">.</span><span class="fu">getClass</span><span class="op">())</span> <span class="cf">return</span> <span class="kw">false</span><span class="op">;</span></span>
<span id="cb3-41"><a href="#cb3-41" aria-hidden="true" tabindex="-1"></a>        Dog dog <span class="op">=</span> <span class="op">(</span>Dog<span class="op">)</span> o<span class="op">;</span></span>
<span id="cb3-42"><a href="#cb3-42" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> Objects<span class="op">.</span><span class="fu">equals</span><span class="op">(</span>name<span class="op">,</span> dog<span class="op">.</span><span class="fu">name</span><span class="op">)</span> <span class="op">&amp;&amp;</span></span>
<span id="cb3-43"><a href="#cb3-43" aria-hidden="true" tabindex="-1"></a>                Objects<span class="op">.</span><span class="fu">equals</span><span class="op">(</span>favoriteToy<span class="op">,</span> dog<span class="op">.</span><span class="fu">favoriteToy</span><span class="op">);</span></span>
<span id="cb3-44"><a href="#cb3-44" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-45"><a href="#cb3-45" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-46"><a href="#cb3-46" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb3-47"><a href="#cb3-47" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">int</span> <span class="fu">hashCode</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-48"><a href="#cb3-48" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> Objects<span class="op">.</span><span class="fu">hash</span><span class="op">(</span>name<span class="op">,</span> favoriteToy<span class="op">);</span></span>
<span id="cb3-49"><a href="#cb3-49" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-50"><a href="#cb3-50" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-51"><a href="#cb3-51" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb3-52"><a href="#cb3-52" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">String</span> <span class="fu">toString</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-53"><a href="#cb3-53" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="st">&quot;Dog{&quot;</span> <span class="op">+</span></span>
<span id="cb3-54"><a href="#cb3-54" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;name=&#39;&quot;</span> <span class="op">+</span> name <span class="op">+</span> <span class="ch">&#39;\&#39;&#39;</span> <span class="op">+</span></span>
<span id="cb3-55"><a href="#cb3-55" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, favoriteToy=&#39;&quot;</span> <span class="op">+</span> favoriteToy <span class="op">+</span> <span class="ch">&#39;\&#39;&#39;</span> <span class="op">+</span></span>
<span id="cb3-56"><a href="#cb3-56" aria-hidden="true" tabindex="-1"></a>                <span class="ch">&#39;}&#39;</span><span class="op">;</span></span>
<span id="cb3-57"><a href="#cb3-57" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-58"><a href="#cb3-58" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb3-59"><a href="#cb3-59" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-60"><a href="#cb3-60" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Person <span class="kw">implements</span> HasName<span class="op">&lt;</span>Person<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb3-61"><a href="#cb3-61" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="bu">String</span> name<span class="op">;</span></span>
<span id="cb3-62"><a href="#cb3-62" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="bu">String</span> majoredIn<span class="op">;</span></span>
<span id="cb3-63"><a href="#cb3-63" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">int</span> age<span class="op">;</span></span>
<span id="cb3-64"><a href="#cb3-64" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-65"><a href="#cb3-65" aria-hidden="true" tabindex="-1"></a>    <span class="fu">Person</span><span class="op">(</span><span class="bu">String</span> name<span class="op">,</span> <span class="bu">String</span> majoredIn<span class="op">,</span> <span class="dt">int</span> age<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-66"><a href="#cb3-66" aria-hidden="true" tabindex="-1"></a>        Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>name<span class="op">,</span> <span class="st">&quot;Name should not be null&quot;</span><span class="op">);</span></span>
<span id="cb3-67"><a href="#cb3-67" aria-hidden="true" tabindex="-1"></a>        Objects<span class="op">.</span><span class="fu">requireNonNull</span><span class="op">(</span>majoredIn<span class="op">,</span> <span class="st">&quot;Majored In should not be null&quot;</span><span class="op">);</span></span>
<span id="cb3-68"><a href="#cb3-68" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">name</span> <span class="op">=</span> name<span class="op">;</span></span>
<span id="cb3-69"><a href="#cb3-69" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">majoredIn</span> <span class="op">=</span> majoredIn<span class="op">;</span></span>
<span id="cb3-70"><a href="#cb3-70" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">age</span> <span class="op">=</span> age<span class="op">;</span></span>
<span id="cb3-71"><a href="#cb3-71" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-72"><a href="#cb3-72" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-73"><a href="#cb3-73" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb3-74"><a href="#cb3-74" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">String</span> <span class="fu">getName</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-75"><a href="#cb3-75" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">name</span><span class="op">;</span></span>
<span id="cb3-76"><a href="#cb3-76" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-77"><a href="#cb3-77" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-78"><a href="#cb3-78" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb3-79"><a href="#cb3-79" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> Person <span class="fu">withName</span><span class="op">(</span><span class="bu">String</span> name<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-80"><a href="#cb3-80" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Person</span><span class="op">(</span>name<span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">majoredIn</span><span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">age</span><span class="op">);</span></span>
<span id="cb3-81"><a href="#cb3-81" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-82"><a href="#cb3-82" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-83"><a href="#cb3-83" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">String</span> <span class="fu">getMajoredIn</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-84"><a href="#cb3-84" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">majoredIn</span><span class="op">;</span></span>
<span id="cb3-85"><a href="#cb3-85" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-86"><a href="#cb3-86" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-87"><a href="#cb3-87" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> Person <span class="fu">withMajoredIn</span><span class="op">(</span><span class="bu">String</span> majoredIn<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-88"><a href="#cb3-88" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Person</span><span class="op">(</span><span class="kw">this</span><span class="op">.</span><span class="fu">name</span><span class="op">,</span> majoredIn<span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">age</span><span class="op">);</span></span>
<span id="cb3-89"><a href="#cb3-89" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-90"><a href="#cb3-90" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-91"><a href="#cb3-91" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">int</span> <span class="fu">getAge</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-92"><a href="#cb3-92" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">age</span><span class="op">;</span></span>
<span id="cb3-93"><a href="#cb3-93" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-94"><a href="#cb3-94" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-95"><a href="#cb3-95" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> Person <span class="fu">withAge</span><span class="op">(</span><span class="dt">int</span> age<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-96"><a href="#cb3-96" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Person</span><span class="op">(</span><span class="kw">this</span><span class="op">.</span><span class="fu">name</span><span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">majoredIn</span><span class="op">,</span> age<span class="op">);</span></span>
<span id="cb3-97"><a href="#cb3-97" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-98"><a href="#cb3-98" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-99"><a href="#cb3-99" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb3-100"><a href="#cb3-100" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">boolean</span> <span class="fu">equals</span><span class="op">(</span><span class="bu">Object</span> o<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-101"><a href="#cb3-101" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span><span class="kw">this</span> <span class="op">==</span> o<span class="op">)</span> <span class="cf">return</span> <span class="kw">true</span><span class="op">;</span></span>
<span id="cb3-102"><a href="#cb3-102" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>o <span class="op">==</span> <span class="kw">null</span> <span class="op">||</span> <span class="fu">getClass</span><span class="op">()</span> <span class="op">!=</span> o<span class="op">.</span><span class="fu">getClass</span><span class="op">())</span> <span class="cf">return</span> <span class="kw">false</span><span class="op">;</span></span>
<span id="cb3-103"><a href="#cb3-103" aria-hidden="true" tabindex="-1"></a>        Person person <span class="op">=</span> <span class="op">(</span>Person<span class="op">)</span> o<span class="op">;</span></span>
<span id="cb3-104"><a href="#cb3-104" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> age <span class="op">==</span> person<span class="op">.</span><span class="fu">age</span> <span class="op">&amp;&amp;</span></span>
<span id="cb3-105"><a href="#cb3-105" aria-hidden="true" tabindex="-1"></a>                Objects<span class="op">.</span><span class="fu">equals</span><span class="op">(</span>name<span class="op">,</span> person<span class="op">.</span><span class="fu">name</span><span class="op">)</span> <span class="op">&amp;&amp;</span></span>
<span id="cb3-106"><a href="#cb3-106" aria-hidden="true" tabindex="-1"></a>                Objects<span class="op">.</span><span class="fu">equals</span><span class="op">(</span>majoredIn<span class="op">,</span> person<span class="op">.</span><span class="fu">majoredIn</span><span class="op">);</span></span>
<span id="cb3-107"><a href="#cb3-107" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-108"><a href="#cb3-108" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-109"><a href="#cb3-109" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb3-110"><a href="#cb3-110" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">int</span> <span class="fu">hashCode</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-111"><a href="#cb3-111" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> Objects<span class="op">.</span><span class="fu">hash</span><span class="op">(</span>name<span class="op">,</span> majoredIn<span class="op">,</span> age<span class="op">);</span></span>
<span id="cb3-112"><a href="#cb3-112" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-113"><a href="#cb3-113" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-114"><a href="#cb3-114" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb3-115"><a href="#cb3-115" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">String</span> <span class="fu">toString</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-116"><a href="#cb3-116" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="st">&quot;Person{&quot;</span> <span class="op">+</span></span>
<span id="cb3-117"><a href="#cb3-117" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;name=&#39;&quot;</span> <span class="op">+</span> name <span class="op">+</span> <span class="ch">&#39;\&#39;&#39;</span> <span class="op">+</span></span>
<span id="cb3-118"><a href="#cb3-118" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, majoredIn=&#39;&quot;</span> <span class="op">+</span> majoredIn <span class="op">+</span> <span class="ch">&#39;\&#39;&#39;</span> <span class="op">+</span></span>
<span id="cb3-119"><a href="#cb3-119" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, age=&quot;</span> <span class="op">+</span> age <span class="op">+</span></span>
<span id="cb3-120"><a href="#cb3-120" aria-hidden="true" tabindex="-1"></a>                <span class="ch">&#39;}&#39;</span><span class="op">;</span></span>
<span id="cb3-121"><a href="#cb3-121" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-122"><a href="#cb3-122" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb3-123"><a href="#cb3-123" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-124"><a href="#cb3-124" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-125"><a href="#cb3-125" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Main <span class="op">{</span></span>
<span id="cb3-126"><a href="#cb3-126" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">static</span> <span class="op">&lt;</span>T <span class="kw">extends</span> HasName<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span> T <span class="fu">upperCaseName</span><span class="op">(</span>HasName<span class="op">&lt;</span>T<span class="op">&gt;</span> entity<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-127"><a href="#cb3-127" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> entity<span class="op">.</span><span class="fu">withName</span><span class="op">(</span>entity<span class="op">.</span><span class="fu">getName</span><span class="op">().</span><span class="fu">toUpperCase</span><span class="op">());</span></span>
<span id="cb3-128"><a href="#cb3-128" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-129"><a href="#cb3-129" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-130"><a href="#cb3-130" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span><span class="op">(</span><span class="bu">String</span><span class="op">[]</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-131"><a href="#cb3-131" aria-hidden="true" tabindex="-1"></a>        Dog fido <span class="op">=</span> <span class="kw">new</span> <span class="fu">Dog</span><span class="op">(</span><span class="st">&quot;Fido&quot;</span><span class="op">,</span> <span class="st">&quot;Squeeks&quot;</span><span class="op">);</span></span>
<span id="cb3-132"><a href="#cb3-132" aria-hidden="true" tabindex="-1"></a>        Person bob <span class="op">=</span> <span class="kw">new</span> <span class="fu">Person</span><span class="op">(</span><span class="st">&quot;Bob&quot;</span><span class="op">,</span> <span class="st">&quot;Physics&quot;</span><span class="op">,</span> <span class="dv">30</span><span class="op">);</span></span>
<span id="cb3-133"><a href="#cb3-133" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;Before:&quot;</span><span class="op">);</span></span>
<span id="cb3-134"><a href="#cb3-134" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>fido<span class="op">);</span></span>
<span id="cb3-135"><a href="#cb3-135" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>bob<span class="op">);</span></span>
<span id="cb3-136"><a href="#cb3-136" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-137"><a href="#cb3-137" aria-hidden="true" tabindex="-1"></a>        Dog fidoUpper <span class="op">=</span> <span class="fu">upperCaseName</span><span class="op">(</span>fido<span class="op">);</span></span>
<span id="cb3-138"><a href="#cb3-138" aria-hidden="true" tabindex="-1"></a>        Person bobUpper <span class="op">=</span> <span class="fu">upperCaseName</span><span class="op">(</span>bob<span class="op">);</span></span>
<span id="cb3-139"><a href="#cb3-139" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-140"><a href="#cb3-140" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span><span class="st">&quot;After:&quot;</span><span class="op">);</span></span>
<span id="cb3-141"><a href="#cb3-141" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>fidoUpper<span class="op">);</span></span>
<span id="cb3-142"><a href="#cb3-142" aria-hidden="true" tabindex="-1"></a>        <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>bobUpper<span class="op">);</span></span>
<span id="cb3-143"><a href="#cb3-143" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-144"><a href="#cb3-144" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How to append to an array in C</title><link>https://mccue.dev/pages/3-22-19-how-to-append-to-an-array-in-c</link><description></description><pubDate>Fri, 22 Mar 0019 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How to append to an array in C</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How to append to an array in C</h1>
</header>
<h2 id="question-from-deleted-user">Question from Deleted User</h2>
<blockquote>
<p>is there a way to append to an array in C</p>
<p>not linked lists</p>
<p>i have a callback function which needs to add an item to an array every time it's called</p>
<p>i can't figure out how to do that</p>
</blockquote>
<p>Conceptually an array is not a good fit for continual appending. If you want to do an operation like that you would be best off writing or finding your own "ArrayList" kind of wrapper.</p>
<blockquote>
<p>is there a way to find the index of the last item in the list</p>
<p>array*</p>
</blockquote>
<p>An array in c is a fixed size block of memory that you have a pointer to the start of.</p>
<p>It is up to you to keep track of the size of that array usually in a separate <code>int</code>.</p>
<p>Because you only have the pointer to the start of the block of memory, nothing about that pointer can tell you how much memory ahead of that you are allowed to access.</p>
<p>So if you keep the size of the array and the pointer to the start of the array held somewhere then the "index of the last item" is something you implicitly know.</p>
<p>I might be wrong when I say to store it in an <code>int</code> it might be a <code>usize</code> or some other type.</p>
<blockquote>
<p>time to check out rust</p>
<p>if anyone can help me out with this i might consider going back to C</p>
</blockquote>
<p>The type you are looking for in rust is probably <code>Vec</code>.</p>
<p>Can you share your problem and what you were thinking of for a solution? I can maybe whip up a quick A/B of what it would be in <code>C</code> vs <code>Rust</code>.</p>
<blockquote>
<p>I have a function which retrieves a few rows from a database and uses a callback function to individually process each row. The callback function is supposed to map the row's data to a structure and add it to an array.</p>
<p>this is what i was trying to do</p>
</blockquote>
<div class="sourceCode" id="cb1"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> handle_entry<span class="op">(</span><span class="dt">void</span> <span class="op">*</span>entries<span class="op">,</span> <span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>argv<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>column_name<span class="op">){</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  Entry entry<span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  strcpy<span class="op">(</span>entry<span class="op">.</span>title<span class="op">,</span> argv<span class="op">[</span><span class="dv">1</span><span class="op">]);</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  strcpy<span class="op">(</span>entry<span class="op">.</span>content<span class="op">,</span> argv<span class="op">[</span><span class="dv">2</span><span class="op">]);</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> get_entries<span class="op">(){</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>  sqlite3 <span class="op">*</span>DB<span class="op">;</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>  sqlite3_stmt <span class="op">*</span>stmt<span class="op">;</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">char</span> <span class="op">*</span>sql <span class="op">=</span> <span class="st">&quot;SELECT * FROM Entries;&quot;</span><span class="op">;</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>  Entry <span class="op">*</span>entries<span class="op">[</span><span class="dv">100</span><span class="op">];</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>  sqlite3_open<span class="op">(</span><span class="st">&quot;entries.db&quot;</span><span class="op">,</span> <span class="op">&amp;</span>DB<span class="op">);</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>  sqlite3_exec<span class="op">(</span>DB<span class="op">,</span> sql<span class="op">,</span> handle_entry<span class="op">,</span> entries<span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span></code></pre></div>
<p>What is the schema for entries?</p>
<blockquote>
<p>ID, Title, Content</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">typedef</span> <span class="kw">struct</span> Entry <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> ID<span class="op">;</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">char</span> <span class="op">*</span>title<span class="op">;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">char</span> <span class="op">*</span>content<span class="op">;</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> Entry<span class="op">;</span></span></code></pre></div>
<div class="sourceCode" id="cb3"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> <span class="kw">TABLE</span> Entries(</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>              <span class="kw">ID</span> <span class="dt">INTEGER</span> <span class="kw">PRIMARY</span> <span class="kw">KEY</span>,</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>              Title <span class="dt">CHAR</span>(<span class="dv">512</span>),</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>              Content TEXT);</span></code></pre></div>
</blockquote>
<p>Here ya go</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">rusqlite::</span><span class="op">{</span>Connection<span class="op">,</span> NO_PARAMS<span class="op">};</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>derive<span class="at">(</span><span class="bu">Debug</span><span class="at">)]</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Entry <span class="op">{</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>    id<span class="op">:</span> <span class="dt">i64</span><span class="op">,</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    title<span class="op">:</span> <span class="dt">String</span><span class="op">,</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>    content<span class="op">:</span> <span class="dt">String</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> insert_entry(conn<span class="op">:</span> <span class="op">&amp;</span>Connection<span class="op">,</span> entry<span class="op">:</span> <span class="op">&amp;</span>Entry) <span class="op">-&gt;</span> <span class="pp">rusqlite::</span><span class="dt">Result</span><span class="op">&lt;</span><span class="dt">usize</span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>    conn<span class="op">.</span>execute(<span class="st">&quot;</span><span class="sc">\</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a><span class="st">    INSERT INTO Entries (Title, Content)</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a><span class="st">        VALUES (?1, ?2)</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a><span class="st">    &quot;</span><span class="op">,</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">&amp;</span>[<span class="op">&amp;</span>entry<span class="op">.</span>title<span class="op">,</span> <span class="op">&amp;</span>entry<span class="op">.</span>content])</span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> all_entries(conn<span class="op">:</span> <span class="op">&amp;</span>Connection) <span class="op">-&gt;</span> <span class="pp">rusqlite::</span><span class="dt">Result</span><span class="op">&lt;</span><span class="dt">Vec</span><span class="op">&lt;</span>Entry<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> stmt <span class="op">=</span> conn</span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>prepare(<span class="st">&quot;SELECT ID, Title, Content FROM Entries&quot;</span>)<span class="op">?;</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> entry_iter <span class="op">=</span> stmt<span class="op">.</span>query_map(</span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true" tabindex="-1"></a>        NO_PARAMS<span class="op">,</span></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true" tabindex="-1"></a>        <span class="op">|</span>row<span class="op">|</span> <span class="cn">Ok</span>(Entry<span class="op">{</span></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true" tabindex="-1"></a>            id<span class="op">:</span> row<span class="op">.</span>get(<span class="dv">0</span>)<span class="op">?,</span></span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true" tabindex="-1"></a>            title<span class="op">:</span> row<span class="op">.</span>get(<span class="dv">1</span>)<span class="op">?,</span></span>
<span id="cb4-26"><a href="#cb4-26" aria-hidden="true" tabindex="-1"></a>            content<span class="op">:</span> row<span class="op">.</span>get(<span class="dv">2</span>)<span class="op">?</span></span>
<span id="cb4-27"><a href="#cb4-27" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span>)</span>
<span id="cb4-28"><a href="#cb4-28" aria-hidden="true" tabindex="-1"></a>    )<span class="op">?;</span></span>
<span id="cb4-29"><a href="#cb4-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-30"><a href="#cb4-30" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> entries <span class="op">=</span> <span class="dt">Vec</span><span class="pp">::</span>new()<span class="op">;</span></span>
<span id="cb4-31"><a href="#cb4-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">for</span> entry <span class="kw">in</span> entry_iter <span class="op">{</span></span>
<span id="cb4-32"><a href="#cb4-32" aria-hidden="true" tabindex="-1"></a>        entries<span class="op">.</span>push(entry<span class="op">?</span>)<span class="op">;</span></span>
<span id="cb4-33"><a href="#cb4-33" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-34"><a href="#cb4-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-35"><a href="#cb4-35" aria-hidden="true" tabindex="-1"></a>    <span class="cn">Ok</span>(entries)</span>
<span id="cb4-36"><a href="#cb4-36" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb4-37"><a href="#cb4-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-38"><a href="#cb4-38" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> main() <span class="op">-&gt;</span> <span class="pp">rusqlite::</span><span class="dt">Result</span><span class="op">&lt;</span>()<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb4-39"><a href="#cb4-39" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> conn <span class="op">=</span> <span class="pp">Connection::</span>open(<span class="st">&quot;db.sqlite&quot;</span>)<span class="op">?;</span></span>
<span id="cb4-40"><a href="#cb4-40" aria-hidden="true" tabindex="-1"></a>    conn<span class="op">.</span>execute(<span class="st">&quot;</span><span class="sc">\</span></span>
<span id="cb4-41"><a href="#cb4-41" aria-hidden="true" tabindex="-1"></a><span class="st">    CREATE TABLE IF NOT EXISTS Entries(</span></span>
<span id="cb4-42"><a href="#cb4-42" aria-hidden="true" tabindex="-1"></a><span class="st">              ID INTEGER PRIMARY KEY,</span></span>
<span id="cb4-43"><a href="#cb4-43" aria-hidden="true" tabindex="-1"></a><span class="st">              Title CHAR(512),</span></span>
<span id="cb4-44"><a href="#cb4-44" aria-hidden="true" tabindex="-1"></a><span class="st">              Content TEXT);</span></span>
<span id="cb4-45"><a href="#cb4-45" aria-hidden="true" tabindex="-1"></a><span class="st">    &quot;</span><span class="op">,</span></span>
<span id="cb4-46"><a href="#cb4-46" aria-hidden="true" tabindex="-1"></a>    NO_PARAMS)<span class="op">?;</span></span>
<span id="cb4-47"><a href="#cb4-47" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-48"><a href="#cb4-48" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> entry_1 <span class="op">=</span> Entry <span class="op">{</span></span>
<span id="cb4-49"><a href="#cb4-49" aria-hidden="true" tabindex="-1"></a>        id<span class="op">:</span> <span class="dv">0</span><span class="op">,</span></span>
<span id="cb4-50"><a href="#cb4-50" aria-hidden="true" tabindex="-1"></a>        title<span class="op">:</span> <span class="dt">String</span><span class="pp">::</span>from(<span class="st">&quot;Entry Number One&quot;</span>)<span class="op">,</span></span>
<span id="cb4-51"><a href="#cb4-51" aria-hidden="true" tabindex="-1"></a>        content<span class="op">:</span> <span class="dt">String</span><span class="pp">::</span>from(<span class="st">&quot;This is the text for my entry.&quot;</span>)</span>
<span id="cb4-52"><a href="#cb4-52" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb4-53"><a href="#cb4-53" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-54"><a href="#cb4-54" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> entry_2 <span class="op">=</span> Entry <span class="op">{</span></span>
<span id="cb4-55"><a href="#cb4-55" aria-hidden="true" tabindex="-1"></a>        id<span class="op">:</span> <span class="dv">1</span><span class="op">,</span></span>
<span id="cb4-56"><a href="#cb4-56" aria-hidden="true" tabindex="-1"></a>        title<span class="op">:</span> <span class="dt">String</span><span class="pp">::</span>from(<span class="st">&quot;Le Second Entreee&quot;</span>)<span class="op">,</span></span>
<span id="cb4-57"><a href="#cb4-57" aria-hidden="true" tabindex="-1"></a>        content<span class="op">:</span> <span class="dt">String</span><span class="pp">::</span>from(<span class="st">&quot;2. What is 2? Can you taste it?&quot;</span>)</span>
<span id="cb4-58"><a href="#cb4-58" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb4-59"><a href="#cb4-59" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-60"><a href="#cb4-60" aria-hidden="true" tabindex="-1"></a>    insert_entry(<span class="op">&amp;</span>conn<span class="op">,&amp;</span>entry_1)<span class="op">?;</span></span>
<span id="cb4-61"><a href="#cb4-61" aria-hidden="true" tabindex="-1"></a>    insert_entry(<span class="op">&amp;</span>conn<span class="op">,&amp;</span>entry_2)<span class="op">?;</span></span>
<span id="cb4-62"><a href="#cb4-62" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-63"><a href="#cb4-63" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-64"><a href="#cb4-64" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-65"><a href="#cb4-65" aria-hidden="true" tabindex="-1"></a>    <span class="pp">println!</span>(<span class="st">&quot;{:?}&quot;</span><span class="op">,</span> all_entries(<span class="op">&amp;</span>conn))<span class="op">;</span></span>
<span id="cb4-66"><a href="#cb4-66" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-67"><a href="#cb4-67" aria-hidden="true" tabindex="-1"></a>    <span class="cn">Ok</span>(())</span>
<span id="cb4-68"><a href="#cb4-68" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<pre><code>/Users/emccue/.cargo/bin/cargo run --color=always --package sequel --bin sequel
   Compiling sequel v0.1.0 (/Users/emccue/Development/sequel)
    Finished dev [unoptimized + debuginfo] target(s) in 1.63s
     Running `target/debug/sequel`
Ok([Entry { id: 1, title: &quot;Entry Number One&quot;, content: &quot;This is the text for my entry.&quot; }, Entry { id: 2, title: &quot;Le Second Entreee&quot;, content: &quot;2. What is 2? Can you taste it?&quot; }])

Process finished with exit code 0</code></pre>
<blockquote>
<p>that's gonna take a long time to understand for me</p>
<p>im still in ch one in the rust tutorial</p>
</blockquote>
<p>That's fair. C is definitely a simpler language in terms of number of concepts you need to understand.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>I like it when "if" is an expression</title><link>https://mccue.dev/pages/3-13-19-if-expression</link><description></description><pubDate>Wed, 13 Mar 0019 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>I like it when &quot;if&quot; is an expression</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">I like it when "if" is an expression</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
One of the small conveniences ive grown to really like in a programming language is "if" being an expression.

<p>I found myself hacking it into some JS I was writing today.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> thing <span class="op">=</span> (() <span class="kw">=&gt;</span> {</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> (condition) {</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="st">&quot;hello&quot;</span><span class="op">;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    } <span class="cf">else</span> {</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="st">&quot;world&quot;</span><span class="op">;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    }</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>})()<span class="op">;</span></span></code></pre></div>
<p>Now, feel free to weigh in on that being bad practice.</p>
<blockquote>
<p>as a non JS programmer I have no idea what "thing = (() =&gt; {" is supposed to do</p>
</blockquote>
<p>That creates an anonymous function then calls it immediately.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>The Ferry Problem in Rust</title><link>https://mccue.dev/pages/3-11-19-ferry-problem-in-rust</link><description></description><pubDate>Mon, 11 Mar 0019 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>The Ferry Problem in Rust</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">The Ferry Problem in Rust</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
## Someone else's C homework done in rust

<div class="sourceCode" id="cb1"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Ferry Loading</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="co">// Before bridges were common, ferries were used to transport cars across rivers.</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="co">// River ferries, unlike their larger cousins, run on a guide line and are powered by the</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="co">// river&#39;s current. Cars drive onto the ferry from one end, the ferry crosses the river, and</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="co">// the cars exit from the other end of the ferry.</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="co">// There is an l-meter-long ferry that crosses the river. A car may arrive at either</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="co">// river bank to be transported by the ferry to the opposite bank. The ferry travels</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="co">// continuously back and forth between the banks so long as it is carrying a car or there</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="co">// is at least one car waiting at either bank. Whenever the ferry arrives at one of the</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="co">// banks, it unloads its cargo and loads up cars that are waiting to cross as long as they</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="co">// fit on its deck. The cars are loaded in the order of their arrival and the ferry&#39;s deck</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="co">// accommodates only one lane of cars. The ferry is initially on the left bank where it</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="co">// had mechanical problems and it took quite some time to fix it. In the meantime, lines</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="co">// of cars formed on both banks that wait to cross the river.</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="co">// The first line of input contains c, the number of test cases. Each test case begins</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a><span class="co">// with the number l, a space and then the number m. m lines follow describing the cars</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="co">// that arrive in this order to be transported. Each line gives the length of a car (in</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a><span class="co">// centimeters), and the bank at which the car awaits the ferry (&quot;left&quot; or &quot;right&quot;).</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a><span class="co">// For each test case, output one line giving the number of times the ferry has to cross</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a><span class="co">// the river in order to serve all waiting cars.</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a><span class="co">// Sample input</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a><span class="co">// 4</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a><span class="co">// 20 4</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a><span class="co">// 380 left</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a><span class="co">// 720 left</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a><span class="co">// 1340 right</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a><span class="co">// 1040 left</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a><span class="co">// 15 4</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a><span class="co">// 380 left</span></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a><span class="co">// 720 left</span></span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a><span class="co">// 1340 right</span></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a><span class="co">// 1040 left</span></span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a><span class="co">// 15 4</span></span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a><span class="co">// 380 left</span></span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a><span class="co">// 720 left</span></span>
<span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a><span class="co">// 1340 left</span></span>
<span id="cb1-37"><a href="#cb1-37" aria-hidden="true" tabindex="-1"></a><span class="co">// 1040 left</span></span>
<span id="cb1-38"><a href="#cb1-38" aria-hidden="true" tabindex="-1"></a><span class="co">// 15 4</span></span>
<span id="cb1-39"><a href="#cb1-39" aria-hidden="true" tabindex="-1"></a><span class="co">// 380 right</span></span>
<span id="cb1-40"><a href="#cb1-40" aria-hidden="true" tabindex="-1"></a><span class="co">// 720 right</span></span>
<span id="cb1-41"><a href="#cb1-41" aria-hidden="true" tabindex="-1"></a><span class="co">// 1340 right</span></span>
<span id="cb1-42"><a href="#cb1-42" aria-hidden="true" tabindex="-1"></a><span class="co">// 1040 right</span></span>
<span id="cb1-43"><a href="#cb1-43" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-44"><a href="#cb1-44" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">std::collections::</span>LinkedList<span class="op">;</span></span>
<span id="cb1-45"><a href="#cb1-45" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">std::error::</span><span class="bu">Error</span><span class="op">;</span></span>
<span id="cb1-46"><a href="#cb1-46" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">std::io::</span><span class="bu">BufRead</span><span class="op">;</span></span>
<span id="cb1-47"><a href="#cb1-47" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-48"><a href="#cb1-48" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>derive<span class="at">(</span><span class="bu">Debug</span><span class="op">,</span> <span class="bu">PartialEq</span><span class="op">,</span> <span class="bu">Eq</span><span class="at">)]</span></span>
<span id="cb1-49"><a href="#cb1-49" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> RiverBank <span class="op">{</span></span>
<span id="cb1-50"><a href="#cb1-50" aria-hidden="true" tabindex="-1"></a>    Left<span class="op">,</span></span>
<span id="cb1-51"><a href="#cb1-51" aria-hidden="true" tabindex="-1"></a>    Right<span class="op">,</span></span>
<span id="cb1-52"><a href="#cb1-52" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-53"><a href="#cb1-53" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-54"><a href="#cb1-54" aria-hidden="true" tabindex="-1"></a><span class="kw">impl</span> RiverBank <span class="op">{</span></span>
<span id="cb1-55"><a href="#cb1-55" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> try_from(value<span class="op">:</span> <span class="op">&amp;</span><span class="dt">str</span>) <span class="op">-&gt;</span> <span class="dt">Result</span><span class="op">&lt;</span>RiverBank<span class="op">,</span> <span class="dt">Box</span><span class="op">&lt;</span><span class="bu">Error</span><span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb1-56"><a href="#cb1-56" aria-hidden="true" tabindex="-1"></a>        <span class="kw">match</span> value <span class="op">{</span></span>
<span id="cb1-57"><a href="#cb1-57" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;left&quot;</span> <span class="op">=&gt;</span> <span class="cn">Ok</span>(<span class="pp">RiverBank::</span>Left)<span class="op">,</span></span>
<span id="cb1-58"><a href="#cb1-58" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;right&quot;</span> <span class="op">=&gt;</span> <span class="cn">Ok</span>(<span class="pp">RiverBank::</span>Right)<span class="op">,</span></span>
<span id="cb1-59"><a href="#cb1-59" aria-hidden="true" tabindex="-1"></a>            _ <span class="op">=&gt;</span> <span class="cn">Err</span>(<span class="st">&quot;A river bank must either be </span><span class="sc">\&quot;</span><span class="st">left</span><span class="sc">\&quot;</span><span class="st"> or </span><span class="sc">\&quot;</span><span class="st">right</span><span class="sc">\&quot;</span><span class="st">&quot;</span><span class="op">.</span>into())<span class="op">,</span></span>
<span id="cb1-60"><a href="#cb1-60" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-61"><a href="#cb1-61" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-62"><a href="#cb1-62" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-63"><a href="#cb1-63" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> switch(<span class="op">&amp;</span><span class="kw">self</span>) <span class="op">-&gt;</span> RiverBank <span class="op">{</span></span>
<span id="cb1-64"><a href="#cb1-64" aria-hidden="true" tabindex="-1"></a>        <span class="kw">match</span> <span class="kw">self</span> <span class="op">{</span></span>
<span id="cb1-65"><a href="#cb1-65" aria-hidden="true" tabindex="-1"></a>            <span class="op">&amp;</span><span class="pp">RiverBank::</span>Left <span class="op">=&gt;</span> <span class="pp">RiverBank::</span>Right<span class="op">,</span></span>
<span id="cb1-66"><a href="#cb1-66" aria-hidden="true" tabindex="-1"></a>            <span class="op">&amp;</span><span class="pp">RiverBank::</span>Right <span class="op">=&gt;</span> <span class="pp">RiverBank::</span>Left<span class="op">,</span></span>
<span id="cb1-67"><a href="#cb1-67" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-68"><a href="#cb1-68" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-69"><a href="#cb1-69" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-70"><a href="#cb1-70" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-71"><a href="#cb1-71" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> CarLength <span class="op">=</span> <span class="dt">u64</span><span class="op">;</span></span>
<span id="cb1-72"><a href="#cb1-72" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> FerryLength <span class="op">=</span> <span class="dt">u64</span><span class="op">;</span></span>
<span id="cb1-73"><a href="#cb1-73" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-74"><a href="#cb1-74" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>derive<span class="at">(</span><span class="bu">Debug</span><span class="at">)]</span></span>
<span id="cb1-75"><a href="#cb1-75" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> StartingCarState <span class="op">{</span></span>
<span id="cb1-76"><a href="#cb1-76" aria-hidden="true" tabindex="-1"></a>    river_bank<span class="op">:</span> RiverBank<span class="op">,</span></span>
<span id="cb1-77"><a href="#cb1-77" aria-hidden="true" tabindex="-1"></a>    car_length<span class="op">:</span> CarLength<span class="op">,</span></span>
<span id="cb1-78"><a href="#cb1-78" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-79"><a href="#cb1-79" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-80"><a href="#cb1-80" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>derive<span class="at">(</span><span class="bu">Debug</span><span class="at">)]</span></span>
<span id="cb1-81"><a href="#cb1-81" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> FerryProblem <span class="op">{</span></span>
<span id="cb1-82"><a href="#cb1-82" aria-hidden="true" tabindex="-1"></a>    ferry_length<span class="op">:</span> FerryLength<span class="op">,</span></span>
<span id="cb1-83"><a href="#cb1-83" aria-hidden="true" tabindex="-1"></a>    car_descriptions<span class="op">:</span> <span class="dt">Vec</span><span class="op">&lt;</span>StartingCarState<span class="op">&gt;,</span></span>
<span id="cb1-84"><a href="#cb1-84" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-85"><a href="#cb1-85" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-86"><a href="#cb1-86" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> read_input(from<span class="op">:</span> <span class="kw">impl</span> <span class="bu">BufRead</span>) <span class="op">-&gt;</span> <span class="dt">Result</span><span class="op">&lt;</span><span class="dt">Vec</span><span class="op">&lt;</span>FerryProblem<span class="op">&gt;,</span> <span class="dt">Box</span><span class="op">&lt;</span><span class="bu">Error</span><span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb1-87"><a href="#cb1-87" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> lines <span class="op">=</span> from<span class="op">.</span>lines()<span class="op">;</span></span>
<span id="cb1-88"><a href="#cb1-88" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> first_line <span class="op">=</span> <span class="kw">match</span> lines<span class="op">.</span>next() <span class="op">{</span></span>
<span id="cb1-89"><a href="#cb1-89" aria-hidden="true" tabindex="-1"></a>        <span class="cn">Some</span>(<span class="cn">Ok</span>(line)) <span class="op">=&gt;</span> line<span class="op">,</span></span>
<span id="cb1-90"><a href="#cb1-90" aria-hidden="true" tabindex="-1"></a>        <span class="cn">Some</span>(<span class="cn">Err</span>(err)) <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb1-91"><a href="#cb1-91" aria-hidden="true" tabindex="-1"></a>            <span class="kw">return</span> <span class="cn">Err</span>(err<span class="op">.</span>into())<span class="op">;</span></span>
<span id="cb1-92"><a href="#cb1-92" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-93"><a href="#cb1-93" aria-hidden="true" tabindex="-1"></a>        <span class="cn">None</span> <span class="op">=&gt;</span> <span class="kw">return</span> <span class="cn">Err</span>(<span class="st">&quot;There was no first line provided to stdin&quot;</span><span class="op">.</span>into())<span class="op">,</span></span>
<span id="cb1-94"><a href="#cb1-94" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb1-95"><a href="#cb1-95" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-96"><a href="#cb1-96" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> number_of_test_cases<span class="op">:</span> <span class="dt">u64</span> <span class="op">=</span> first_line</span>
<span id="cb1-97"><a href="#cb1-97" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>parse()</span>
<span id="cb1-98"><a href="#cb1-98" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>map_err(<span class="op">|</span>_<span class="op">|</span> <span class="st">&quot;The first line needs to be a single non-negative number.&quot;</span>)<span class="op">?;</span></span>
<span id="cb1-99"><a href="#cb1-99" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-100"><a href="#cb1-100" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> ferry_problems <span class="op">=</span> <span class="dt">Vec</span><span class="pp">::</span>new()<span class="op">;</span></span>
<span id="cb1-101"><a href="#cb1-101" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-102"><a href="#cb1-102" aria-hidden="true" tabindex="-1"></a>    <span class="kw">for</span> _ <span class="kw">in</span> <span class="dv">0</span><span class="op">..</span>number_of_test_cases <span class="op">{</span></span>
<span id="cb1-103"><a href="#cb1-103" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> ferry_description_line <span class="op">=</span> <span class="kw">match</span> lines<span class="op">.</span>next() <span class="op">{</span></span>
<span id="cb1-104"><a href="#cb1-104" aria-hidden="true" tabindex="-1"></a>            <span class="cn">Some</span>(<span class="cn">Ok</span>(line)) <span class="op">=&gt;</span> line<span class="op">,</span></span>
<span id="cb1-105"><a href="#cb1-105" aria-hidden="true" tabindex="-1"></a>            <span class="cn">Some</span>(<span class="cn">Err</span>(err)) <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb1-106"><a href="#cb1-106" aria-hidden="true" tabindex="-1"></a>                <span class="kw">return</span> <span class="cn">Err</span>(err<span class="op">.</span>into())<span class="op">;</span></span>
<span id="cb1-107"><a href="#cb1-107" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb1-108"><a href="#cb1-108" aria-hidden="true" tabindex="-1"></a>            <span class="cn">None</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb1-109"><a href="#cb1-109" aria-hidden="true" tabindex="-1"></a>                <span class="kw">return</span> <span class="cn">Err</span>(<span class="st">&quot;Ran out of input when parsing test cases&quot;</span><span class="op">.</span>into())<span class="op">;</span></span>
<span id="cb1-110"><a href="#cb1-110" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb1-111"><a href="#cb1-111" aria-hidden="true" tabindex="-1"></a>        <span class="op">};</span></span>
<span id="cb1-112"><a href="#cb1-112" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-113"><a href="#cb1-113" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> (ferry_length<span class="op">,</span> number_of_cars) <span class="op">=</span> <span class="op">{</span></span>
<span id="cb1-114"><a href="#cb1-114" aria-hidden="true" tabindex="-1"></a>            <span class="kw">let</span> split_by_whitespace<span class="op">:</span> <span class="dt">Vec</span><span class="op">&lt;&amp;</span><span class="dt">str</span><span class="op">&gt;</span> <span class="op">=</span> ferry_description_line<span class="op">.</span>split(<span class="st">&quot;</span><span class="sc">\\</span><span class="st">w+&quot;</span>)<span class="op">.</span>collect()<span class="op">;</span></span>
<span id="cb1-115"><a href="#cb1-115" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-116"><a href="#cb1-116" aria-hidden="true" tabindex="-1"></a>            <span class="kw">if</span> split_by_whitespace<span class="op">.</span>len() <span class="op">==</span> <span class="dv">2</span> <span class="op">{</span></span>
<span id="cb1-117"><a href="#cb1-117" aria-hidden="true" tabindex="-1"></a>                <span class="kw">let</span> <span class="kw">mut</span> ferry_length <span class="op">=</span> split_by_whitespace[<span class="dv">0</span>]<span class="op">.</span>parse()<span class="op">?;</span></span>
<span id="cb1-118"><a href="#cb1-118" aria-hidden="true" tabindex="-1"></a>                ferry_length <span class="op">*=</span> <span class="dv">100</span><span class="op">;</span></span>
<span id="cb1-119"><a href="#cb1-119" aria-hidden="true" tabindex="-1"></a>                <span class="kw">let</span> number_of_cars<span class="op">:</span> <span class="dt">u64</span> <span class="op">=</span> split_by_whitespace[<span class="dv">1</span>]<span class="op">.</span>parse()<span class="op">?;</span></span>
<span id="cb1-120"><a href="#cb1-120" aria-hidden="true" tabindex="-1"></a>                (ferry_length<span class="op">,</span> number_of_cars)</span>
<span id="cb1-121"><a href="#cb1-121" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> <span class="kw">else</span> <span class="op">{</span></span>
<span id="cb1-122"><a href="#cb1-122" aria-hidden="true" tabindex="-1"></a>                <span class="kw">return</span> <span class="cn">Err</span>(<span class="st">&quot;Malformed ferry description line&quot;</span><span class="op">.</span>into())<span class="op">;</span></span>
<span id="cb1-123"><a href="#cb1-123" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb1-124"><a href="#cb1-124" aria-hidden="true" tabindex="-1"></a>        <span class="op">};</span></span>
<span id="cb1-125"><a href="#cb1-125" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-126"><a href="#cb1-126" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> <span class="kw">mut</span> car_descriptions <span class="op">=</span> <span class="dt">Vec</span><span class="pp">::</span>new()<span class="op">;</span></span>
<span id="cb1-127"><a href="#cb1-127" aria-hidden="true" tabindex="-1"></a>        <span class="kw">for</span> _ <span class="kw">in</span> <span class="dv">0</span><span class="op">..</span>number_of_cars <span class="op">{</span></span>
<span id="cb1-128"><a href="#cb1-128" aria-hidden="true" tabindex="-1"></a>            <span class="kw">let</span> car_description_line <span class="op">=</span> <span class="kw">match</span> lines<span class="op">.</span>next() <span class="op">{</span></span>
<span id="cb1-129"><a href="#cb1-129" aria-hidden="true" tabindex="-1"></a>                <span class="cn">Some</span>(<span class="cn">Ok</span>(line)) <span class="op">=&gt;</span> line<span class="op">,</span></span>
<span id="cb1-130"><a href="#cb1-130" aria-hidden="true" tabindex="-1"></a>                <span class="cn">Some</span>(<span class="cn">Err</span>(err)) <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb1-131"><a href="#cb1-131" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">return</span> <span class="cn">Err</span>(err<span class="op">.</span>into())<span class="op">;</span></span>
<span id="cb1-132"><a href="#cb1-132" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb1-133"><a href="#cb1-133" aria-hidden="true" tabindex="-1"></a>                <span class="cn">None</span> <span class="op">=&gt;</span> <span class="kw">return</span> <span class="cn">Err</span>(<span class="st">&quot;Not enough descriptions of cars given&quot;</span><span class="op">.</span>into())<span class="op">,</span></span>
<span id="cb1-134"><a href="#cb1-134" aria-hidden="true" tabindex="-1"></a>            <span class="op">};</span></span>
<span id="cb1-135"><a href="#cb1-135" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-136"><a href="#cb1-136" aria-hidden="true" tabindex="-1"></a>            <span class="kw">let</span> car_state <span class="op">=</span> <span class="op">{</span></span>
<span id="cb1-137"><a href="#cb1-137" aria-hidden="true" tabindex="-1"></a>                <span class="kw">let</span> split_by_whitespace<span class="op">:</span> <span class="dt">Vec</span><span class="op">&lt;&amp;</span><span class="dt">str</span><span class="op">&gt;</span> <span class="op">=</span> car_description_line<span class="op">.</span>split(<span class="st">&quot;</span><span class="sc">\\</span><span class="st">w+&quot;</span>)<span class="op">.</span>collect()<span class="op">;</span></span>
<span id="cb1-138"><a href="#cb1-138" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-139"><a href="#cb1-139" aria-hidden="true" tabindex="-1"></a>                <span class="kw">if</span> split_by_whitespace<span class="op">.</span>len() <span class="op">==</span> <span class="dv">2</span> <span class="op">{</span></span>
<span id="cb1-140"><a href="#cb1-140" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">let</span> car_length <span class="op">=</span> split_by_whitespace[<span class="dv">0</span>]<span class="op">.</span>parse()<span class="op">?;</span></span>
<span id="cb1-141"><a href="#cb1-141" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">let</span> river_bank <span class="op">=</span> <span class="pp">RiverBank::</span>try_from(split_by_whitespace[<span class="dv">1</span>])<span class="op">?;</span></span>
<span id="cb1-142"><a href="#cb1-142" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-143"><a href="#cb1-143" aria-hidden="true" tabindex="-1"></a>                    StartingCarState <span class="op">{</span></span>
<span id="cb1-144"><a href="#cb1-144" aria-hidden="true" tabindex="-1"></a>                        river_bank<span class="op">:</span> river_bank<span class="op">,</span></span>
<span id="cb1-145"><a href="#cb1-145" aria-hidden="true" tabindex="-1"></a>                        car_length<span class="op">:</span> car_length<span class="op">,</span></span>
<span id="cb1-146"><a href="#cb1-146" aria-hidden="true" tabindex="-1"></a>                    <span class="op">}</span></span>
<span id="cb1-147"><a href="#cb1-147" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span> <span class="kw">else</span> <span class="op">{</span></span>
<span id="cb1-148"><a href="#cb1-148" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">return</span> <span class="cn">Err</span>(<span class="st">&quot;Malformed car description line&quot;</span><span class="op">.</span>into())<span class="op">;</span></span>
<span id="cb1-149"><a href="#cb1-149" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb1-150"><a href="#cb1-150" aria-hidden="true" tabindex="-1"></a>            <span class="op">};</span></span>
<span id="cb1-151"><a href="#cb1-151" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-152"><a href="#cb1-152" aria-hidden="true" tabindex="-1"></a>            car_descriptions<span class="op">.</span>push(car_state)<span class="op">;</span></span>
<span id="cb1-153"><a href="#cb1-153" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-154"><a href="#cb1-154" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-155"><a href="#cb1-155" aria-hidden="true" tabindex="-1"></a>        ferry_problems<span class="op">.</span>push(FerryProblem <span class="op">{</span></span>
<span id="cb1-156"><a href="#cb1-156" aria-hidden="true" tabindex="-1"></a>            ferry_length<span class="op">,</span></span>
<span id="cb1-157"><a href="#cb1-157" aria-hidden="true" tabindex="-1"></a>            car_descriptions<span class="op">,</span></span>
<span id="cb1-158"><a href="#cb1-158" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span>)</span>
<span id="cb1-159"><a href="#cb1-159" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-160"><a href="#cb1-160" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-161"><a href="#cb1-161" aria-hidden="true" tabindex="-1"></a>    <span class="cn">Ok</span>(ferry_problems)</span>
<span id="cb1-162"><a href="#cb1-162" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-163"><a href="#cb1-163" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-164"><a href="#cb1-164" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>derive<span class="at">(</span><span class="bu">Debug</span><span class="at">)]</span></span>
<span id="cb1-165"><a href="#cb1-165" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> FerryProblemSolution <span class="op">{</span></span>
<span id="cb1-166"><a href="#cb1-166" aria-hidden="true" tabindex="-1"></a>    RequiredTrips(<span class="dt">u64</span>)<span class="op">,</span></span>
<span id="cb1-167"><a href="#cb1-167" aria-hidden="true" tabindex="-1"></a>    Impossible<span class="op">,</span></span>
<span id="cb1-168"><a href="#cb1-168" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-169"><a href="#cb1-169" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-170"><a href="#cb1-170" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> required_crossings(problem<span class="op">:</span> FerryProblem) <span class="op">-&gt;</span> FerryProblemSolution <span class="op">{</span></span>
<span id="cb1-171"><a href="#cb1-171" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> left_bank<span class="op">:</span> LinkedList<span class="op">&lt;</span>CarLength<span class="op">&gt;</span> <span class="op">=</span> problem</span>
<span id="cb1-172"><a href="#cb1-172" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>car_descriptions</span>
<span id="cb1-173"><a href="#cb1-173" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>iter()</span>
<span id="cb1-174"><a href="#cb1-174" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>filter(<span class="op">|</span>car<span class="op">|</span> car<span class="op">.</span>river_bank <span class="op">==</span> <span class="pp">RiverBank::</span>Left)</span>
<span id="cb1-175"><a href="#cb1-175" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>map(<span class="op">|</span>car<span class="op">|</span> car<span class="op">.</span>car_length)</span>
<span id="cb1-176"><a href="#cb1-176" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>collect()<span class="op">;</span></span>
<span id="cb1-177"><a href="#cb1-177" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> right_bank<span class="op">:</span> LinkedList<span class="op">&lt;</span>CarLength<span class="op">&gt;</span> <span class="op">=</span> problem</span>
<span id="cb1-178"><a href="#cb1-178" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>car_descriptions</span>
<span id="cb1-179"><a href="#cb1-179" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>iter()</span>
<span id="cb1-180"><a href="#cb1-180" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>filter(<span class="op">|</span>car<span class="op">|</span> car<span class="op">.</span>river_bank <span class="op">==</span> <span class="pp">RiverBank::</span>Right)</span>
<span id="cb1-181"><a href="#cb1-181" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>map(<span class="op">|</span>car<span class="op">|</span> car<span class="op">.</span>car_length)</span>
<span id="cb1-182"><a href="#cb1-182" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span>collect()<span class="op">;</span></span>
<span id="cb1-183"><a href="#cb1-183" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-184"><a href="#cb1-184" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> bank <span class="op">=</span> <span class="pp">RiverBank::</span>Left<span class="op">;</span></span>
<span id="cb1-185"><a href="#cb1-185" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-186"><a href="#cb1-186" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> used_capacity <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb1-187"><a href="#cb1-187" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> <span class="kw">mut</span> trips_made <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb1-188"><a href="#cb1-188" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-189"><a href="#cb1-189" aria-hidden="true" tabindex="-1"></a>    <span class="kw">loop</span> <span class="op">{</span></span>
<span id="cb1-190"><a href="#cb1-190" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> next_car <span class="op">=</span> <span class="kw">match</span> bank <span class="op">{</span></span>
<span id="cb1-191"><a href="#cb1-191" aria-hidden="true" tabindex="-1"></a>            <span class="pp">RiverBank::</span>Left <span class="op">=&gt;</span> left_bank<span class="op">.</span>pop_front()<span class="op">,</span></span>
<span id="cb1-192"><a href="#cb1-192" aria-hidden="true" tabindex="-1"></a>            <span class="pp">RiverBank::</span>Right <span class="op">=&gt;</span> right_bank<span class="op">.</span>pop_front()<span class="op">,</span></span>
<span id="cb1-193"><a href="#cb1-193" aria-hidden="true" tabindex="-1"></a>        <span class="op">};</span></span>
<span id="cb1-194"><a href="#cb1-194" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-195"><a href="#cb1-195" aria-hidden="true" tabindex="-1"></a>        <span class="kw">match</span> next_car <span class="op">{</span></span>
<span id="cb1-196"><a href="#cb1-196" aria-hidden="true" tabindex="-1"></a>            <span class="cn">Some</span>(car) <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb1-197"><a href="#cb1-197" aria-hidden="true" tabindex="-1"></a>                <span class="kw">if</span> car <span class="op">&gt;</span> problem<span class="op">.</span>ferry_length <span class="op">{</span></span>
<span id="cb1-198"><a href="#cb1-198" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">return</span> <span class="pp">FerryProblemSolution::</span>Impossible<span class="op">;</span></span>
<span id="cb1-199"><a href="#cb1-199" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span> <span class="kw">else</span> <span class="kw">if</span> car <span class="op">+</span> used_capacity <span class="op">&gt;</span> problem<span class="op">.</span>ferry_length <span class="op">{</span></span>
<span id="cb1-200"><a href="#cb1-200" aria-hidden="true" tabindex="-1"></a>                    trips_made <span class="op">+=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb1-201"><a href="#cb1-201" aria-hidden="true" tabindex="-1"></a>                    used_capacity <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb1-202"><a href="#cb1-202" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">match</span> bank <span class="op">{</span></span>
<span id="cb1-203"><a href="#cb1-203" aria-hidden="true" tabindex="-1"></a>                        <span class="pp">RiverBank::</span>Left <span class="op">=&gt;</span> left_bank<span class="op">.</span>push_front(car)<span class="op">,</span></span>
<span id="cb1-204"><a href="#cb1-204" aria-hidden="true" tabindex="-1"></a>                        <span class="pp">RiverBank::</span>Right <span class="op">=&gt;</span> right_bank<span class="op">.</span>push_front(car)<span class="op">,</span></span>
<span id="cb1-205"><a href="#cb1-205" aria-hidden="true" tabindex="-1"></a>                    <span class="op">};</span></span>
<span id="cb1-206"><a href="#cb1-206" aria-hidden="true" tabindex="-1"></a>                    bank <span class="op">=</span> bank<span class="op">.</span>switch()</span>
<span id="cb1-207"><a href="#cb1-207" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span> <span class="kw">else</span> <span class="op">{</span></span>
<span id="cb1-208"><a href="#cb1-208" aria-hidden="true" tabindex="-1"></a>                    used_capacity <span class="op">+=</span> car<span class="op">;</span></span>
<span id="cb1-209"><a href="#cb1-209" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb1-210"><a href="#cb1-210" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb1-211"><a href="#cb1-211" aria-hidden="true" tabindex="-1"></a>            <span class="cn">None</span> <span class="op">=&gt;</span> <span class="op">{</span></span>
<span id="cb1-212"><a href="#cb1-212" aria-hidden="true" tabindex="-1"></a>                trips_made <span class="op">+=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb1-213"><a href="#cb1-213" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-214"><a href="#cb1-214" aria-hidden="true" tabindex="-1"></a>                <span class="kw">let</span> other_bank_is_empty <span class="op">=</span> <span class="kw">match</span> bank <span class="op">{</span></span>
<span id="cb1-215"><a href="#cb1-215" aria-hidden="true" tabindex="-1"></a>                    <span class="pp">RiverBank::</span>Left <span class="op">=&gt;</span> right_bank<span class="op">.</span>is_empty()<span class="op">,</span></span>
<span id="cb1-216"><a href="#cb1-216" aria-hidden="true" tabindex="-1"></a>                    <span class="pp">RiverBank::</span>Right <span class="op">=&gt;</span> left_bank<span class="op">.</span>is_empty()<span class="op">,</span></span>
<span id="cb1-217"><a href="#cb1-217" aria-hidden="true" tabindex="-1"></a>                <span class="op">};</span></span>
<span id="cb1-218"><a href="#cb1-218" aria-hidden="true" tabindex="-1"></a>                <span class="kw">if</span> other_bank_is_empty <span class="op">{</span></span>
<span id="cb1-219"><a href="#cb1-219" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">return</span> <span class="pp">FerryProblemSolution::</span>RequiredTrips(trips_made)<span class="op">;</span></span>
<span id="cb1-220"><a href="#cb1-220" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span> <span class="kw">else</span> <span class="op">{</span></span>
<span id="cb1-221"><a href="#cb1-221" aria-hidden="true" tabindex="-1"></a>                    used_capacity <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb1-222"><a href="#cb1-222" aria-hidden="true" tabindex="-1"></a>                    bank <span class="op">=</span> bank<span class="op">.</span>switch()</span>
<span id="cb1-223"><a href="#cb1-223" aria-hidden="true" tabindex="-1"></a>                <span class="op">}</span></span>
<span id="cb1-224"><a href="#cb1-224" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb1-225"><a href="#cb1-225" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-226"><a href="#cb1-226" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-227"><a href="#cb1-227" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-228"><a href="#cb1-228" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-229"><a href="#cb1-229" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> main() <span class="op">-&gt;</span> <span class="dt">Result</span><span class="op">&lt;</span>()<span class="op">,</span> <span class="dt">Box</span><span class="op">&lt;</span><span class="bu">Error</span><span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb1-230"><a href="#cb1-230" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> test_input <span class="op">=</span> <span class="st">&quot;4</span></span>
<span id="cb1-231"><a href="#cb1-231" aria-hidden="true" tabindex="-1"></a><span class="st">20 4</span></span>
<span id="cb1-232"><a href="#cb1-232" aria-hidden="true" tabindex="-1"></a><span class="st">380 left</span></span>
<span id="cb1-233"><a href="#cb1-233" aria-hidden="true" tabindex="-1"></a><span class="st">720 left</span></span>
<span id="cb1-234"><a href="#cb1-234" aria-hidden="true" tabindex="-1"></a><span class="st">1340 right</span></span>
<span id="cb1-235"><a href="#cb1-235" aria-hidden="true" tabindex="-1"></a><span class="st">1040 left</span></span>
<span id="cb1-236"><a href="#cb1-236" aria-hidden="true" tabindex="-1"></a><span class="st">15 4</span></span>
<span id="cb1-237"><a href="#cb1-237" aria-hidden="true" tabindex="-1"></a><span class="st">380 left</span></span>
<span id="cb1-238"><a href="#cb1-238" aria-hidden="true" tabindex="-1"></a><span class="st">720 left</span></span>
<span id="cb1-239"><a href="#cb1-239" aria-hidden="true" tabindex="-1"></a><span class="st">1340 right</span></span>
<span id="cb1-240"><a href="#cb1-240" aria-hidden="true" tabindex="-1"></a><span class="st">1040 left</span></span>
<span id="cb1-241"><a href="#cb1-241" aria-hidden="true" tabindex="-1"></a><span class="st">15 4</span></span>
<span id="cb1-242"><a href="#cb1-242" aria-hidden="true" tabindex="-1"></a><span class="st">380 left</span></span>
<span id="cb1-243"><a href="#cb1-243" aria-hidden="true" tabindex="-1"></a><span class="st">720 left</span></span>
<span id="cb1-244"><a href="#cb1-244" aria-hidden="true" tabindex="-1"></a><span class="st">1340 left</span></span>
<span id="cb1-245"><a href="#cb1-245" aria-hidden="true" tabindex="-1"></a><span class="st">1040 left</span></span>
<span id="cb1-246"><a href="#cb1-246" aria-hidden="true" tabindex="-1"></a><span class="st">15 4</span></span>
<span id="cb1-247"><a href="#cb1-247" aria-hidden="true" tabindex="-1"></a><span class="st">380 right</span></span>
<span id="cb1-248"><a href="#cb1-248" aria-hidden="true" tabindex="-1"></a><span class="st">720 right</span></span>
<span id="cb1-249"><a href="#cb1-249" aria-hidden="true" tabindex="-1"></a><span class="st">1340 right</span></span>
<span id="cb1-250"><a href="#cb1-250" aria-hidden="true" tabindex="-1"></a><span class="st">1040 right</span></span>
<span id="cb1-251"><a href="#cb1-251" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;</span><span class="op">;</span></span>
<span id="cb1-252"><a href="#cb1-252" aria-hidden="true" tabindex="-1"></a>    <span class="co">/* replace with io::stdin().lock() for real input */</span></span>
<span id="cb1-253"><a href="#cb1-253" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> problems <span class="op">=</span> read_input(test_input<span class="op">.</span>as_bytes())<span class="op">?;</span></span>
<span id="cb1-254"><a href="#cb1-254" aria-hidden="true" tabindex="-1"></a>    <span class="kw">for</span> problem <span class="kw">in</span> problems <span class="op">{</span></span>
<span id="cb1-255"><a href="#cb1-255" aria-hidden="true" tabindex="-1"></a>        <span class="kw">let</span> solution <span class="op">=</span> required_crossings(problem)<span class="op">;</span></span>
<span id="cb1-256"><a href="#cb1-256" aria-hidden="true" tabindex="-1"></a>        <span class="kw">match</span> solution <span class="op">{</span></span>
<span id="cb1-257"><a href="#cb1-257" aria-hidden="true" tabindex="-1"></a>            <span class="pp">FerryProblemSolution::</span>Impossible <span class="op">=&gt;</span> <span class="pp">println!</span>(<span class="st">&quot;There is no solution&quot;</span>)<span class="op">,</span></span>
<span id="cb1-258"><a href="#cb1-258" aria-hidden="true" tabindex="-1"></a>            <span class="pp">FerryProblemSolution::</span>RequiredTrips(trips) <span class="op">=&gt;</span> <span class="pp">println!</span>(<span class="st">&quot;{}&quot;</span><span class="op">,</span> trips)<span class="op">,</span></span>
<span id="cb1-259"><a href="#cb1-259" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb1-260"><a href="#cb1-260" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-261"><a href="#cb1-261" aria-hidden="true" tabindex="-1"></a>    <span class="cn">Ok</span>(())</span>
<span id="cb1-262"><a href="#cb1-262" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Is there a better way of storing a JSON entry</title><link>https://mccue.dev/pages/3-10-19-is-there-a-better-way-of-storing-a-json-entry</link><description></description><pubDate>Sun, 10 Mar 0019 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Is there a better way of storing a JSON entry</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Is there a better way of storing a JSON entry</h1>
</header>
<h2 id="question-from-anonymous-">Question from Anonymous <!-- Zombie_Pigdragon#3468 --></h2>
<blockquote>
<div class="sourceCode" id="cb1"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Event:</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>, name, time, location):</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>        <span class="va">self</span>.name <span class="op">=</span> name</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>        <span class="va">self</span>.time <span class="op">=</span> time</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>        <span class="va">self</span>.location <span class="op">=</span> location</span></code></pre></div>
<p>Is this a good thing to do or should I not</p>
</blockquote>
<blockquote>
<p>(Deleted User) I'd suggest a namedtuple instead. it's much faster and efficient.</p>
<p>Or dataclasses if you're using py 3.7.</p>
</blockquote>
<blockquote>
<p>How do I use a namedtuple?</p>
</blockquote>
<p>Actually quick disclaimer.</p>
<p>The way python's JSON module works, it's impossible for you to dump <code>namedtuple</code>s as anything other than a list.</p>
<p>Here you should just use a dictionary (IMO).</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>event <span class="op">=</span> {<span class="st">&quot;name&quot;</span>: name,</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>         <span class="st">&quot;time&quot;</span>: time,</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>         <span class="st">&quot;location&quot;</span>: location}</span></code></pre></div>
<p>But if I'm being honest that's just my clojure brain talking.</p>
<p>pro: If you deserialize from json you get this anyways and you can do round-trip serde and have the same representation.</p>
<p>con: The "shape" of the dict doesn't have a name and you can't use the <code>.</code> syntax to access stuff by default.</p>
<p>If you want to use the dot-notation for access with a <code>dict</code> just wrap it in this lib.</p>
<p><a href="https://github.com/Infinidat/munch">https://github.com/Infinidat/munch</a></p>
<p>In general, you don't gain much by "dressing up" your data though named tuples are immutable, which is nice.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How to make a custom python templating engine</title><link>https://mccue.dev/pages/3-9-19-python-for-html-templates</link><description></description><pubDate>Sat, 09 Mar 0019 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How to make a custom python templating engine</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How to make a custom python templating engine</h1>
</header>
<h2 id="question-from-anonymous-">Question from Anonymous <!-- Zombie_Pigdragon#3468 --></h2>
<blockquote>
<p>I have now used a language I am barely familiar with (Python) (I don't like the scopes) to parse a webpage I built off of online tutorials and it's shitty embeds of python so I could generate a new page that has the current information from Google Calendar and presentation slides from Dropbox, neither of which are APIs I had experience with. I have the shittiest code ever written</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;div</span> <span class="er">id</span><span class="ot">=</span><span class="st">&quot;SlideshowContainer&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    ${&quot;\n\t\t\t&quot;.join(getImageFiles(imageList))}</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;/div&gt;</span></span></code></pre></div>
<p>a small sample of the HTML part.</p>
<p>But I don't like Python, it's just what I'm required to use</p>
<p>I have the code execution working, it's basically my own implementation of templates</p>
<p>Python scopes trip me up for no reason, as well as types Holy wars of editors don't ever change my opinion; I just use Visual Studio because I normally use C#, but I switched to IDLE for this one, because I was hoping it would be able to work better for Python (it doesn't)</p>
</blockquote>
<p>What exactly do you mean by scopes though? like, declarations of things?</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> thing:</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    x <span class="op">=</span> <span class="dv">2</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="cf">else</span>:</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    x <span class="op">=</span> <span class="dv">3</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="co"># x exists here</span></span></code></pre></div>
<blockquote>
<p>Declarations in particular, but then I always forget the global keyword in particularly</p>
</blockquote>
<p>Wait, that's a codesmell. In 5 years of python ive never needed to use the global keyword more than 1 time and even that was a mistake.</p>
<p>I've had to use nonlocal for one assignment - but this is indicitive probably of a larger problem in how you write code.</p>
<blockquote>
<p>No, Python just feels like shitty scripting IMO and I treat Python like I treat a one shot bash/batch script.</p>
</blockquote>
<p>(my main interest here is just to get to the root of why you feel this way)</p>
<p>(not to knock the case of one off hacky scripts - it's pretty good for that)</p>
<blockquote>
<p>But I only ever need Python for either scripting or small programs</p>
<p>It's only in use here because it's the one language I can remotely use that works on Linux</p>
</blockquote>
<p>What are the other languages you can use? That might give me some context on what angle you are coming from here.</p>
<blockquote>
<p>C# mostly</p>
</blockquote>
<p>okay, ill loop back around after I have run your code, but I have a hypothesis here.</p>
<p>Also, if you have any of your C# code that you can share I am curious how you write code with the guard rails of static typing.</p>
<blockquote>
<p>I have code that I think kinda doesn't suck, but it does in retrospect</p>
</blockquote>
<p>Good enough.</p>
<p>So anyways, first I'm walking through your script. First issue</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>data <span class="op">=</span> []</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, <span class="dv">10</span>):</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    data.append((<span class="st">&quot;&amp;nbsp&quot;</span>, <span class="st">&quot;&amp;nbsp&quot;</span>, <span class="st">&quot;&amp;nbsp&quot;</span>))</span></code></pre></div>
<p>"data" tells me nothing about what this is. Why do you have a list of 10 tuples of 3 non-breaking space html escapes? They also aren't the whole thing you need since you should have a semicolon at the end if I remember correctly <code>&amp;nbsp;</code></p>
<div class="sourceCode" id="cb4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>command <span class="op">=</span> <span class="st">&quot;value = &quot;</span> <span class="op">+</span> match.groups(<span class="dv">1</span>)[<span class="dv">0</span>]</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="bu">print</span>(command)</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="bu">exec</span>(command, {}, enviormentVariablesInFile)</span></code></pre></div>
<p>I think you see this coming, but it is worth pointing out anyways.</p>
<p><code>exec</code> is never what you want.</p>
<p>Part of what is going wrong here is that, beyond using exec as a shorthand for a calculator basically, is that you are assigning to a variable.</p>
<p>If anything, at least put the value assignment outside of the command you want to run.</p>
<p>But let's look a bit closer at what you are using it for</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>    pattern <span class="op">=</span> re.<span class="bu">compile</span>(<span class="st">&quot;</span><span class="ch">\\</span><span class="st">${(.*?)}&quot;</span>)</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    enviormentVariablesInFile <span class="op">=</span> {<span class="st">&quot;data&quot;</span>: data, <span class="st">&quot;imageList&quot;</span>: imageList, <span class="st">&quot;value&quot;</span>: <span class="va">None</span>}</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> match <span class="kw">in</span> <span class="bu">reversed</span>(<span class="bu">list</span>(pattern.finditer(output))):</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>        span <span class="op">=</span> match.span()</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>        command <span class="op">=</span> <span class="st">&quot;value = &quot;</span> <span class="op">+</span> match.groups(<span class="dv">1</span>)[<span class="dv">0</span>]</span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>        <span class="bu">print</span>(command)</span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>        <span class="bu">exec</span>(command, {}, enviormentVariablesInFile)</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>        value <span class="op">=</span> enviormentVariablesInFile[<span class="st">&quot;value&quot;</span>]</span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> value <span class="kw">is</span> <span class="va">None</span>:</span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>            value <span class="op">=</span> <span class="st">&quot;&quot;</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>        i <span class="op">+=</span> <span class="dv">1</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a>        output <span class="op">=</span> output[:span[<span class="dv">0</span>]] <span class="op">+</span> value <span class="op">+</span> output[span[<span class="dv">1</span>]:]</span></code></pre></div>
<p>The first issue here is <code>pattern</code>. Regular expressions are not readable. You need to pick a name for that thing that describes what it does.</p>
<p>I can't reverse engineer it, so lets pretend it finds unicorns.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>    unicornPattern <span class="op">=</span> re.<span class="bu">compile</span>(<span class="st">&quot;</span><span class="ch">\\</span><span class="st">${(.*?)}&quot;</span>)</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    unicornsInOutput <span class="op">=</span> <span class="bu">list</span>(unicornPattern.finditer(output))</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>    enviormentVariablesInFile <span class="op">=</span> {<span class="st">&quot;data&quot;</span>: data, <span class="st">&quot;imageList&quot;</span>: imageList, <span class="st">&quot;value&quot;</span>: <span class="va">None</span>}</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> unicornMatch <span class="kw">in</span> <span class="bu">reversed</span>(unicornsInOutput):</span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>        span <span class="op">=</span> match.span()</span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>        command <span class="op">=</span> <span class="st">&quot;value = &quot;</span> <span class="op">+</span> unicornMatch.groups(<span class="dv">1</span>)[<span class="dv">0</span>]</span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>        <span class="bu">print</span>(command)</span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>        <span class="bu">exec</span>(command, {}, enviormentVariablesInFile)</span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>        value <span class="op">=</span> enviormentVariablesInFile[<span class="st">&quot;value&quot;</span>]</span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> value <span class="kw">is</span> <span class="va">None</span>:</span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>            value <span class="op">=</span> <span class="st">&quot;&quot;</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a>        i <span class="op">+=</span> <span class="dv">1</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a>        output <span class="op">=</span> output[:span[<span class="dv">0</span>]] <span class="op">+</span> value <span class="op">+</span> output[span[<span class="dv">1</span>]:]</span></code></pre></div>
<p>Now at least there is a name to the thing.</p>
<p>Also, I guess I get the idea. Your output starts as the html file and then you raw exec code in there that you delimited with <code>${}</code> and insert it as you go.</p>
<p>Because you scan the whole document every time you end up with <code>n^2</code> behaviour, but that is fine for your project.</p>
<p>But - there has to be a better way (and there is, even sans libraries) If you think of python as only good for you to write in a scripting way you should really be asking yourself: "how exactly would I do things differently in C#?".</p>
<p>In this case the main thing c# is going to prevent you from doing is evaluating arbitrary code since "eval"-ing c# is far less easy to do.</p>
<p>You even use this eval behaviour to define helper functions within your template</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>${None; getImageFiles = lambda l: list(map(lambda i: &#39;<span class="kw">&lt;img</span> <span class="er">class</span><span class="ot">=</span><span class="st">&quot;SlideshowImage fade&quot;</span> <span class="er">src</span><span class="ot">=</span><span class="st">&quot;&#39; + str(i) + &#39;&quot;</span> <span class="kw">/&gt;</span>&#39;, l))}</span></code></pre></div>
<p>The key thing here that sucks - which is made more sucky but for a good reason by python requiring whitespace in syntax - is embedding code in templates.</p>
<p>Tools like JSP, java server pages, allow for basically arbitrary access to the context of the code around them.</p>
<p>This is why, even if you manage things well at the start, projects using things that are that permissive tend to get off the rails.</p>
<p>Down a step are things like Jinja (the templating engine flask uses). They allow for you to embed logic - with the conceit that it is sometimes required or helpful for formatting some html or similar , but they do not allow you arbitrary access to the outside scope.</p>
<p>This is what I think you are trying to accomplish with your code since you specify exactly the environment for exec and want to then write code to generate stuff using that environment.</p>
<p>This works except for the facts that</p>
<ol type="1">
<li>Python is probably too powerful a language to be embedded in a template and</li>
<li>Python is a bad fit syntactically for being embedded in html</li>
</ol>
<p>The most simple kind of templating, and what I suggest you use for your project instead of what you are doing, is find and replace.</p>
<p>So instead of having your logic be in your template, you compute what you want to put outside of that context and jam it in after the fact without any logic.</p>
<p>So for your html that you want to generate - first things first - lets sub out the variable bits.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;html&gt;</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;head&gt;</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">&lt;link</span> <span class="er">href</span><span class="ot">=</span><span class="st">&quot;index.css&quot;</span> <span class="er">rel</span><span class="ot">=</span><span class="st">&quot;stylesheet&quot;</span> <span class="er">type</span><span class="ot">=</span><span class="st">&quot;text/css&quot;</span> <span class="kw">/&gt;</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">&lt;script</span> <span class="er">src</span><span class="ot">=</span><span class="st">&quot;index.js&quot;</span><span class="kw">&gt;&lt;/script&gt;</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;/head&gt;</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;body&gt;</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">&lt;div</span> <span class="er">id</span><span class="ot">=</span><span class="st">&quot;Container&quot;</span><span class="kw">&gt;</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">&lt;div</span> <span class="er">id</span><span class="ot">=</span><span class="st">&quot;ScheduleContainer&quot;</span><span class="kw">&gt;</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>            <span class="kw">&lt;table</span> <span class="er">id</span><span class="ot">=</span><span class="st">&quot;ScheduleTable&quot;</span><span class="kw">&gt;</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>                <span class="kw">&lt;tr</span> <span class="er">class</span><span class="ot">=</span><span class="st">&quot;ScheduleRow&quot;</span><span class="kw">&gt;</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">&lt;th</span> <span class="er">id</span><span class="ot">=</span><span class="st">&quot;ScheduleHeader&quot;</span> <span class="er">colspan</span><span class="ot">=</span><span class="st">&quot;5&quot;</span><span class="kw">&gt;</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">&lt;h1&gt;</span>Schedule<span class="kw">&lt;/h1&gt;</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">&lt;/th&gt;</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>                <span class="kw">&lt;/tr&gt;</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a>                <span class="kw">&lt;tr</span> <span class="er">class</span><span class="ot">=</span><span class="st">&quot;ScheduleRow&quot;</span><span class="kw">&gt;</span></span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">&lt;th</span> <span class="er">colspan</span><span class="ot">=</span><span class="st">&quot;3&quot;</span><span class="kw">&gt;</span>Name<span class="kw">&lt;/th&gt;</span></span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">&lt;th&gt;</span>Time<span class="kw">&lt;/th&gt;</span></span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">&lt;th&gt;</span>Room<span class="kw">&lt;/th&gt;</span></span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true" tabindex="-1"></a>                <span class="kw">&lt;/tr&gt;</span></span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true" tabindex="-1"></a>                <span class="co">&lt;!--</span></span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true" tabindex="-1"></a><span class="co">                for scheadule in all_scheadules:</span></span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true" tabindex="-1"></a><span class="co">                     make a table row for that scheadule.</span></span>
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true" tabindex="-1"></a><span class="co">                --&gt;</span></span>
<span id="cb8-26"><a href="#cb8-26" aria-hidden="true" tabindex="-1"></a>            <span class="kw">&lt;/table&gt;</span></span>
<span id="cb8-27"><a href="#cb8-27" aria-hidden="true" tabindex="-1"></a>        <span class="kw">&lt;/div&gt;</span></span>
<span id="cb8-28"><a href="#cb8-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-29"><a href="#cb8-29" aria-hidden="true" tabindex="-1"></a>        <span class="kw">&lt;div</span> <span class="er">id</span><span class="ot">=</span><span class="st">&quot;SlideshowContainer&quot;</span><span class="kw">&gt;</span></span>
<span id="cb8-30"><a href="#cb8-30" aria-hidden="true" tabindex="-1"></a>            <span class="co">&lt;!--</span></span>
<span id="cb8-31"><a href="#cb8-31" aria-hidden="true" tabindex="-1"></a><span class="co">            for image in imageList:</span></span>
<span id="cb8-32"><a href="#cb8-32" aria-hidden="true" tabindex="-1"></a><span class="co">                make an image on the page for that image</span></span>
<span id="cb8-33"><a href="#cb8-33" aria-hidden="true" tabindex="-1"></a><span class="co">            --&gt;</span></span>
<span id="cb8-34"><a href="#cb8-34" aria-hidden="true" tabindex="-1"></a>        <span class="kw">&lt;/div&gt;</span></span>
<span id="cb8-35"><a href="#cb8-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-36"><a href="#cb8-36" aria-hidden="true" tabindex="-1"></a>        <span class="kw">&lt;div</span> <span class="er">id</span><span class="ot">=</span><span class="st">&quot;LogoBox&quot;</span><span class="kw">&gt;</span></span>
<span id="cb8-37"><a href="#cb8-37" aria-hidden="true" tabindex="-1"></a>            <span class="kw">&lt;img</span> <span class="er">id</span><span class="ot">=</span><span class="st">&quot;LogoImage&quot;</span> <span class="er">src</span><span class="ot">=</span><span class="st">&quot;logo.png&quot;</span> <span class="kw">/&gt;</span></span>
<span id="cb8-38"><a href="#cb8-38" aria-hidden="true" tabindex="-1"></a>        <span class="kw">&lt;/div&gt;</span></span>
<span id="cb8-39"><a href="#cb8-39" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-40"><a href="#cb8-40" aria-hidden="true" tabindex="-1"></a>        <span class="kw">&lt;div</span> <span class="er">id</span><span class="ot">=</span><span class="st">&quot;Footer&quot;</span><span class="kw">&gt;</span></span>
<span id="cb8-41"><a href="#cb8-41" aria-hidden="true" tabindex="-1"></a>            <span class="kw">&lt;p</span> <span class="er">style</span><span class="ot">=</span><span class="st">&quot;display: inline&quot;</span> <span class="er">id</span><span class="ot">=</span><span class="st">&quot;DateTimeTime&quot;</span> <span class="kw">/&gt;</span></span>
<span id="cb8-42"><a href="#cb8-42" aria-hidden="true" tabindex="-1"></a>            <span class="kw">&lt;p</span> <span class="er">style</span><span class="ot">=</span><span class="st">&quot;display: inline&quot;</span> <span class="er">id</span><span class="ot">=</span><span class="st">&quot;DateTimeDate&quot;</span> <span class="kw">/&gt;</span></span>
<span id="cb8-43"><a href="#cb8-43" aria-hidden="true" tabindex="-1"></a>        <span class="kw">&lt;/div&gt;</span></span>
<span id="cb8-44"><a href="#cb8-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-45"><a href="#cb8-45" aria-hidden="true" tabindex="-1"></a>    <span class="kw">&lt;/div&gt;</span></span>
<span id="cb8-46"><a href="#cb8-46" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;/body&gt;</span></span>
<span id="cb8-47"><a href="#cb8-47" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;/html&gt;</span></span></code></pre></div>
<p>That's all you want to do. Now the question is "how do I fill in the comment blocks without barfing eval-able python code.</p>
<p>Your first option is the Jinja approach where your templating language has support for basic looping constructs. You can give it the info and it will format that on the html page.</p>
<p>But you are rolling your own, so we will go with the second approach - find and replace.</p>
<p>First, lets handle the rows</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> schedule_row_html(row):</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="st">&quot;&quot;&quot;</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="st">        &lt;tr class=&quot;ScheduleRow&quot;&gt;</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="st">            &lt;td colspan=&quot;3&quot; class=&quot;ScheduleName&quot;&gt;</span><span class="sc">{name}</span><span class="st">&lt;/td&gt;</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a><span class="st">            &lt;td class=&quot;ScheduleTime&quot;&gt;</span><span class="sc">{time}</span><span class="st">&lt;/td&gt;</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a><span class="st">            &lt;td class=&quot;ScheduleRoomNumber&quot;&gt;$</span><span class="sc">{room_number}</span><span class="st">&lt;/td&gt;</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a><span class="st">        &lt;/tr&gt;&quot;&quot;&quot;</span>.<span class="bu">format</span>(name<span class="op">=</span>row[<span class="st">&quot;name&quot;</span>], time<span class="op">=</span>row[<span class="st">&quot;time&quot;</span>], room_number<span class="op">=</span>row[<span class="st">&quot;room_number&quot;</span>])</span></code></pre></div>
<div class="sourceCode" id="cb10"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>all_schedule_html <span class="op">=</span> <span class="st">&quot;&quot;</span>.join([ schedule_row_html(row)</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>                              <span class="cf">for</span> row <span class="kw">in</span> schedules ])</span></code></pre></div>
<p>Now we are in a position where we can fill in the rows</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>pageHtml <span class="op">=</span> <span class="st">&quot;&quot;&quot;</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="st">&lt;html&gt;</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a><span class="st">&lt;head&gt;</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a><span class="st">    &lt;link href=&quot;index.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&gt;</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a><span class="st">    &lt;script src=&quot;index.js&quot;&gt;&lt;/script&gt;</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a><span class="st">&lt;/head&gt;</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a><span class="st">&lt;body&gt;</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a><span class="st">    &lt;div id=&quot;Container&quot;&gt;</span></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a><span class="st">        &lt;div id=&quot;ScheduleContainer&quot;&gt;</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a><span class="st">            &lt;table id=&quot;ScheduleTable&quot;&gt;</span></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a><span class="st">                &lt;tr class=&quot;ScheduleRow&quot;&gt;</span></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a><span class="st">                    &lt;th id=&quot;ScheduleHeader&quot; colspan=&quot;5&quot;&gt;</span></span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a><span class="st">                        &lt;h1&gt;Schedule&lt;/h1&gt;</span></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true" tabindex="-1"></a><span class="st">                    &lt;/th&gt;</span></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true" tabindex="-1"></a><span class="st">                &lt;/tr&gt;</span></span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true" tabindex="-1"></a><span class="st">                &lt;tr class=&quot;ScheduleRow&quot;&gt;</span></span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true" tabindex="-1"></a><span class="st">                    &lt;th colspan=&quot;3&quot;&gt;Name&lt;/th&gt;</span></span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true" tabindex="-1"></a><span class="st">                    &lt;th&gt;Time&lt;/th&gt;</span></span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true" tabindex="-1"></a><span class="st">                    &lt;th&gt;Room&lt;/th&gt;</span></span>
<span id="cb11-22"><a href="#cb11-22" aria-hidden="true" tabindex="-1"></a><span class="st">                &lt;/tr&gt;</span></span>
<span id="cb11-23"><a href="#cb11-23" aria-hidden="true" tabindex="-1"></a><span class="st">                </span><span class="sc">{schedules}</span></span>
<span id="cb11-24"><a href="#cb11-24" aria-hidden="true" tabindex="-1"></a><span class="st">            &lt;/table&gt;</span></span>
<span id="cb11-25"><a href="#cb11-25" aria-hidden="true" tabindex="-1"></a><span class="st">        &lt;/div&gt;</span></span>
<span id="cb11-26"><a href="#cb11-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-27"><a href="#cb11-27" aria-hidden="true" tabindex="-1"></a><span class="st">        &lt;div id=&quot;SlideshowContainer&quot;&gt;</span></span>
<span id="cb11-28"><a href="#cb11-28" aria-hidden="true" tabindex="-1"></a><span class="st">            { images }</span></span>
<span id="cb11-29"><a href="#cb11-29" aria-hidden="true" tabindex="-1"></a><span class="st">        &lt;/div&gt;</span></span>
<span id="cb11-30"><a href="#cb11-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-31"><a href="#cb11-31" aria-hidden="true" tabindex="-1"></a><span class="st">        &lt;div id=&quot;LogoBox&quot;&gt;</span></span>
<span id="cb11-32"><a href="#cb11-32" aria-hidden="true" tabindex="-1"></a><span class="st">            &lt;img id=&quot;LogoImage&quot; src=&quot;logo.png&quot; /&gt;</span></span>
<span id="cb11-33"><a href="#cb11-33" aria-hidden="true" tabindex="-1"></a><span class="st">        &lt;/div&gt;</span></span>
<span id="cb11-34"><a href="#cb11-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-35"><a href="#cb11-35" aria-hidden="true" tabindex="-1"></a><span class="st">        &lt;div id=&quot;Footer&quot;&gt;</span></span>
<span id="cb11-36"><a href="#cb11-36" aria-hidden="true" tabindex="-1"></a><span class="st">            &lt;p style=&quot;display: inline&quot; id=&quot;DateTimeTime&quot; /&gt;</span></span>
<span id="cb11-37"><a href="#cb11-37" aria-hidden="true" tabindex="-1"></a><span class="st">            &lt;p style=&quot;display: inline&quot; id=&quot;DateTimeDate&quot; /&gt;</span></span>
<span id="cb11-38"><a href="#cb11-38" aria-hidden="true" tabindex="-1"></a><span class="st">        &lt;/div&gt;</span></span>
<span id="cb11-39"><a href="#cb11-39" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-40"><a href="#cb11-40" aria-hidden="true" tabindex="-1"></a><span class="st">    &lt;/div&gt;</span></span>
<span id="cb11-41"><a href="#cb11-41" aria-hidden="true" tabindex="-1"></a><span class="st">&lt;/body&gt;</span></span>
<span id="cb11-42"><a href="#cb11-42" aria-hidden="true" tabindex="-1"></a><span class="st">&lt;/html&gt;</span></span>
<span id="cb11-43"><a href="#cb11-43" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;&quot;&quot;</span></span>
<span id="cb11-44"><a href="#cb11-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-45"><a href="#cb11-45" aria-hidden="true" tabindex="-1"></a>pageHtml.<span class="bu">format</span>(schedules<span class="op">=</span>all_schedule_html, images<span class="op">=</span>TBD)</span></code></pre></div>
<div class="sourceCode" id="cb12"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> images_html(images):</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">&quot;&quot;</span>.join([ <span class="st">&quot;&lt;img class=</span><span class="ch">\&quot;</span><span class="st">SlideshowImage fade</span><span class="ch">\&quot;</span><span class="st"> src=</span><span class="sc">{src}</span><span class="st">&quot;</span>.<span class="bu">format</span>(src<span class="op">=</span>imageUrl)</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>                      <span class="cf">for</span> imageUrl <span class="kw">in</span> images ])</span></code></pre></div>
<p>(This is all pseudocode, so the finer points are up to you)</p>
<p>Now you may be asking yourself "but what if my template becomes more complicated?" "just doing string formatting can't scale!"</p>
<p>And to that I say - yeah no duh.</p>
<p>That's why people spent time writing, improving, and bug-fixing the existing templating libraries.</p>
<p>But if your requirements are as simple as you say - a single page regenerated every day or whatever - just do it inline with strings, who cares.</p>
<p>Also, tiny thing.</p>
<pre><code>ChangeImage</code></pre>
<p>The C#/.NET naming convention of every first letter being capitalized isn't used anywhere else. Most javaish people use the <code>camelCase</code> thing. Python supports that too, but the generally preferred style is <code>snake_case</code>.</p>
<p>Doesn't matter for this, but just keep it in the back of your head so when you finally have to code with other programmers you don't get bogged down in pointless holy wars</p>
<p>moving on from the exec thing finally:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>    i <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> event <span class="kw">in</span> events:</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>        start <span class="op">=</span> event[<span class="st">&#39;start&#39;</span>].get(<span class="st">&#39;dateTime&#39;</span>)</span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span>(start <span class="kw">is</span> <span class="va">None</span>):</span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>            <span class="cf">continue</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>        start <span class="op">=</span> start[<span class="dv">11</span>:<span class="dv">16</span>]</span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>        hour <span class="op">=</span> <span class="bu">int</span>(start[<span class="dv">0</span>:<span class="dv">2</span>])</span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>        suffix <span class="op">=</span> <span class="st">&quot; AM&quot;</span></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> hour <span class="op">&gt;</span> <span class="dv">12</span>:</span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a>            suffix <span class="op">=</span> <span class="st">&quot; PM&quot;</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a>            hour <span class="op">%=</span> <span class="dv">12</span></span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a>        start <span class="op">=</span> <span class="bu">str</span>(hour) <span class="op">+</span> start[<span class="dv">2</span>:<span class="dv">5</span>] <span class="op">+</span> suffix</span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a>        name <span class="op">=</span> event[<span class="st">&#39;summary&#39;</span>]</span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true" tabindex="-1"></a>        location <span class="op">=</span> event[<span class="st">&#39;location&#39;</span>]</span>
<span id="cb14-16"><a href="#cb14-16" aria-hidden="true" tabindex="-1"></a>        <span class="bu">print</span>(name, start, location, sep<span class="op">=</span><span class="st">&quot;, &quot;</span>)</span>
<span id="cb14-17"><a href="#cb14-17" aria-hidden="true" tabindex="-1"></a>        data[i] <span class="op">=</span> (name, start, location)</span>
<span id="cb14-18"><a href="#cb14-18" aria-hidden="true" tabindex="-1"></a>        i <span class="op">+=</span> <span class="dv">1</span></span></code></pre></div>
<p>What is this <code>i</code>?</p>
<p>It seems like you are just counting in step with the data because the way you coded it requires a set number of schedules on the page. Hopefully you know how to fix that now and you can just append to data (or whatever name you give it that actually represents what it is).</p>
<p>The larger problem with using <code>i</code> like this is that it increases the area you need to read over to understand a given chunk of code since you need to track reassignments and changes and uses of <code>i</code> everywhere from its first declaration to its last.</p>
<p>"<code>i</code>", while customary for simple kind of index based for loops from c-ish languages and sometimes when using <code>range(...)</code>, really isn't a good enough name here.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>        start <span class="op">=</span> event[<span class="st">&#39;start&#39;</span>].get(<span class="st">&#39;dateTime&#39;</span>)</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span>(start <span class="kw">is</span> <span class="va">None</span>):</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>            <span class="cf">continue</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>        start <span class="op">=</span> start[<span class="dv">11</span>:<span class="dv">16</span>]</span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>        hour <span class="op">=</span> <span class="bu">int</span>(start[<span class="dv">0</span>:<span class="dv">2</span>])</span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>        suffix <span class="op">=</span> <span class="st">&quot; AM&quot;</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> hour <span class="op">&gt;</span> <span class="dv">12</span>:</span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>            suffix <span class="op">=</span> <span class="st">&quot; PM&quot;</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a>            hour <span class="op">%=</span> <span class="dv">12</span></span></code></pre></div>
<p>Also, date handling logic is always going to be messy. I get that. But try and make it depend on less magic numbers.</p>
<p>Maybe isolate it to its own function (maybe, depending on if that helps or hurts readability in context)</p>
<p>What is <code>start[11:16]</code>? Maybe you know now, but god only knows a year from now.</p>
<p><code>getService</code> you copy-pasted. No problem, but maybe put a link back to where you copy-pasted it from in case you need to change it later.</p>
<p>I would loop back around to tackling your misgivings about python but at this point im tired</p>
<blockquote>
<p>Okay, sorry, I had to go halfway through this, and just got back</p>
<p>Thanks for all the help!</p>
<p>I'll try to fix some of the worse problems in this</p>
<p>You're right, I'm not respecting the language correctly</p>
</blockquote>
<p>I wouldn't use the verb "Respecting" necessarily. You just need to learn how to write code to be read. I think being in python lowers some guardrails, so you are just bumping into stuff more.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Can you explain malloc</title><link>https://mccue.dev/pages/3-8-19-explain-malloc</link><description></description><pubDate>Fri, 08 Mar 0019 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Can you explain malloc</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Can you explain malloc</h1>
</header>
<h2 id="question-from-a-deleted-user">Question from a Deleted User</h2>
<blockquote>
<p>could you explain what's happening here</p>
<pre><code>(char *) malloc(n * sizeof(char));</code></pre>
</blockquote>
<p>The malloc thing allocates the structure on the heap.</p>
<p>Think of it like this:</p>
<p>Anything you declare like char[] without calling malloc is memory that is released as soon as the function returns. Any memory you get by using malloc is never released unless you explicitly call free on it.</p>
<p>I know it's confusing, but you'll figure it out.</p>
<blockquote>
<p>and what does (char *) do here</p>
</blockquote>
<p>The (char *) bit does explicitly casts the pointer in the eyes of the compiler. It is a pointer to the start of memory that contains god knows what.</p>
<p>If you allocated <code>sizeof char</code> then you would have a pointer to a block of memory that is the size of a single <code>char</code>, which would be equivalent to an array of characters of size 1.</p>
<blockquote>
<p>does C have array index oob error? I remember it took me days to find out that I've made a mistake while looping the array</p>
</blockquote>
<p>No and yes.</p>
<p>Yes that can cause your program to segfault or maybe crash in some way.</p>
<p>No you don't get a named error that tells you what you messed up.</p>
<p>If you want to get some output it might be educational to make your own "data structure" and <code>printf</code> or something if an error happens.</p>
<p>If you want C perf and sensible errors try Rust, but my Spidey Senses tell me you are still learning in general so that's not really a productive jump.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>What is the builder pattern for</title><link>https://mccue.dev/pages/3-7-19-what-is-the-builder-pattern-for</link><description></description><pubDate>Thu, 07 Mar 0019 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>What is the builder pattern for</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">What is the builder pattern for</h1>
</header>
<h2 id="question-from-abdul4709">Question from Abdul#4709</h2>
<blockquote>
<p>Stupid assignment requirement for using super method inside constructor</p>
<p>Just wanted to make sure prompt makes sense</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">print</span><span class="op">(</span><span class="st">&quot;Enter &#39;y&#39; or &#39;n&#39; if the triangle is filled: &quot;</span><span class="op">);</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="dt">char</span> e <span class="op">=</span> scanner<span class="op">.</span><span class="fu">next</span><span class="op">().</span><span class="fu">charAt</span><span class="op">(</span><span class="dv">0</span><span class="op">);</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="dt">boolean</span> f <span class="op">=</span> e <span class="op">==</span> <span class="ch">&#39;y&#39;</span> <span class="op">?</span> <span class="kw">true</span> <span class="op">:</span> <span class="kw">false</span><span class="op">;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>Triangle triangle <span class="op">=</span> <span class="kw">new</span> <span class="fu">Triangle</span><span class="op">(</span>a<span class="op">,</span> b<span class="op">,</span> c<span class="op">,</span> d<span class="op">,</span> f<span class="op">);</span></span></code></pre></div>
<p>It's a small class so jus using var names like this</p>
</blockquote>
<p>Once a constructor gets to 5 parameters it is probably time to switch to using the builder pattern.</p>
<p>It's boilerplate code in java, but it is a must for readability.</p>
<p>Can you share your triangle class as it is right now?</p>
<blockquote>
<p>Never seen builder pattern before I will make sure to look it up</p>
<p>&lt; CODE LOST TO TIME &gt;</p>
</blockquote>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>    <span class="kw">protected</span> <span class="bu">Date</span> dateCreated<span class="op">;</span></span></code></pre></div>
<p>Thats...wierd. Why is this info stored?</p>
<blockquote>
<p>I actually didn't make the Geometric object class it was posted by the prof</p>
<p>I made the other Triangle one</p>
</blockquote>
<p>Man your prof is annoying</p>
<blockquote>
<p>His lectures r even worse</p>
</blockquote>
<p>Well, making do with what you have is...workable, but we can revisit that superclass to see how you would design it if you weren't a bored college professor.</p>
<p>Basically, for most uses the builder pattern is just a substitute for a language feature called named optional parameters</p>
<p>Consider this python</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Position:</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>, <span class="op">*</span>, x<span class="op">=</span><span class="dv">0</span>, y<span class="op">=</span><span class="dv">0</span>, z<span class="op">=</span><span class="dv">0</span>):</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>        <span class="va">self</span>.x <span class="op">=</span> x</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>        <span class="va">self</span>.y <span class="op">=</span> y</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>        <span class="va">self</span>.z <span class="op">=</span> z</span></code></pre></div>
<blockquote>
<p>What's the second parameter in that 🤔</p>
</blockquote>
<p>It is a python shorthand saying "these things need to be named". That's not really the focus though.</p>
<p>With the constructor (init method - close enough for now) being written like this you can call it a bunch of different ways.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>Position() <span class="co"># makes a 0, 0, 0</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>Position(x<span class="op">=</span><span class="dv">1</span>) <span class="co"># makes a 1, 0, 0</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>Position(z<span class="op">=</span><span class="dv">4</span>) <span class="co"># makes a 0, 0, 4</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>Position(y<span class="op">=</span><span class="dv">2</span>, z<span class="op">=</span><span class="dv">4</span>) <span class="co"># makes a 0, 2, 4</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>Position(x<span class="op">=</span><span class="dv">1</span>, y<span class="op">=</span><span class="dv">2</span>, z<span class="op">=</span><span class="dv">4</span>) <span class="co"># makes a 1, 2, 3</span></span></code></pre></div>
<p>This has alot of cool benefits</p>
<blockquote>
<p>Oh so you don't have to define different constructors many times unlike in java</p>
</blockquote>
<p>For one, if a field has a sensible default value (like all of these do in the position case) you can just insert that if it isn't specified. Also, the parameters being named means that you can specify them "out of order" with the method/function definition, which is very important if you have more than 3 parameters.</p>
<p>"What does the 6th int mean" is a stupid question to have to ask yourself, not to mention the chance you get it wrong, so having the parameters named puts the name of the thing right next to the value.</p>
<p>And before I get to explaining the builder pattern (your way of hacking this language feature into java), try and consider how you would support the Position example with just overloading methods.</p>
<blockquote>
<p>Aight</p>
<p>Perhaps having one method for just x and y and another one for x, y, z?</p>
</blockquote>
<p>What if I want to specify just y and z?</p>
<blockquote>
<p>That would require you to make another method</p>
<p>Which is repetition</p>
<p>And we just have three fields in a larger class there will be even more</p>
</blockquote>
<p>Not only that, it wouldn't work.</p>
<p>Remember, if you have two methods with the same name (or constructors for that matter) then java needs to be able to tell them apart by the types of their arguments. So you can't have two constructors which both take two ints.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="co">// As far as the compiler can tell, these are identical</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="bu">Position</span><span class="op">(</span><span class="dt">int</span> x<span class="op">,</span> <span class="dt">int</span> y<span class="op">)</span> <span class="op">{</span> <span class="kw">...</span> <span class="op">}</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="bu">Position</span><span class="op">(</span><span class="dt">int</span> y<span class="op">,</span> <span class="dt">int</span> z<span class="op">)</span> <span class="op">{</span> <span class="kw">...</span> <span class="op">}</span></span></code></pre></div>
<p>You would have to start making static factory methods with different names for each case.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="op">.</span><span class="fu">positionYZ</span><span class="op">(</span><span class="kw">...</span><span class="op">)</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="op">.</span><span class="fu">positionXZ</span><span class="op">(</span><span class="kw">...</span><span class="op">)</span></span></code></pre></div>
<blockquote>
<p>Ah shite true</p>
</blockquote>
<p>And, while the default values piece of this is important, there will be times where mandating that the user name out all of the parameters, even if there are no optional parameters, makes it so your code is actually legible in the face of dozens of properties.</p>
<p>So without further ado - the builder pattern.</p>
<p>First, we will start with your triangle code</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Triangle <span class="kw">extends</span> GeometricObject <span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> a<span class="op">;</span> <span class="co">// Side one.</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> b<span class="op">;</span> <span class="co">// Side two.</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> c<span class="op">;</span> <span class="co">// Side three.</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">Triangle</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">setA</span><span class="op">(</span><span class="fl">1.0</span><span class="op">);</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">setB</span><span class="op">(</span><span class="fl">1.0</span><span class="op">);</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">setC</span><span class="op">(</span><span class="fl">1.0</span><span class="op">);</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">Triangle</span><span class="op">(</span><span class="dt">double</span> a<span class="op">,</span> <span class="dt">double</span> b<span class="op">,</span> <span class="dt">double</span> c<span class="op">,</span> <span class="bu">String</span> d<span class="op">,</span> <span class="dt">boolean</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">(</span>d<span class="op">,</span> e<span class="op">);</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">setA</span><span class="op">(</span>a<span class="op">);</span></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">setB</span><span class="op">(</span>b<span class="op">);</span></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">setC</span><span class="op">(</span>c<span class="op">);</span></span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">double</span> <span class="fu">getA</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> a<span class="op">;</span></span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-23"><a href="#cb7-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setA</span><span class="op">(</span><span class="dt">double</span> a<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-24"><a href="#cb7-24" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">a</span> <span class="op">=</span> a<span class="op">;</span></span>
<span id="cb7-25"><a href="#cb7-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-26"><a href="#cb7-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-27"><a href="#cb7-27" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">double</span> <span class="fu">getB</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb7-28"><a href="#cb7-28" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> b<span class="op">;</span></span>
<span id="cb7-29"><a href="#cb7-29" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-30"><a href="#cb7-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-31"><a href="#cb7-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setB</span><span class="op">(</span><span class="dt">double</span> b<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-32"><a href="#cb7-32" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">b</span> <span class="op">=</span> b<span class="op">;</span></span>
<span id="cb7-33"><a href="#cb7-33" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-34"><a href="#cb7-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-35"><a href="#cb7-35" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">double</span> <span class="fu">getC</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb7-36"><a href="#cb7-36" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> c<span class="op">;</span></span>
<span id="cb7-37"><a href="#cb7-37" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-38"><a href="#cb7-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-39"><a href="#cb7-39" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setC</span><span class="op">(</span><span class="dt">double</span> c<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-40"><a href="#cb7-40" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">c</span> <span class="op">=</span> c<span class="op">;</span></span>
<span id="cb7-41"><a href="#cb7-41" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-42"><a href="#cb7-42" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-43"><a href="#cb7-43" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">double</span> <span class="fu">getArea</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb7-44"><a href="#cb7-44" aria-hidden="true" tabindex="-1"></a>        <span class="dt">double</span> p <span class="op">=</span> <span class="op">(</span><span class="kw">this</span><span class="op">.</span><span class="fu">a</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">b</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">c</span><span class="op">)</span> <span class="op">/</span> <span class="dv">2</span><span class="op">;</span></span>
<span id="cb7-45"><a href="#cb7-45" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="bu">Math</span><span class="op">.</span><span class="fu">sqrt</span><span class="op">(</span>p <span class="op">*</span> <span class="op">(</span>p <span class="op">-</span> <span class="kw">this</span><span class="op">.</span><span class="fu">a</span><span class="op">)</span> <span class="op">*</span> <span class="op">(</span>p <span class="op">-</span> <span class="kw">this</span><span class="op">.</span><span class="fu">b</span><span class="op">)</span> <span class="op">*</span> <span class="op">(</span>p <span class="op">-</span> <span class="kw">this</span><span class="op">.</span><span class="fu">c</span><span class="op">));</span></span>
<span id="cb7-46"><a href="#cb7-46" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-47"><a href="#cb7-47" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-48"><a href="#cb7-48" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">double</span> <span class="fu">getPerimeter</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb7-49"><a href="#cb7-49" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">a</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">b</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">c</span><span class="op">;</span></span>
<span id="cb7-50"><a href="#cb7-50" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-51"><a href="#cb7-51" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-52"><a href="#cb7-52" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb7-53"><a href="#cb7-53" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">String</span> <span class="fu">toString</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb7-54"><a href="#cb7-54" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="st">&quot;Triangle{&quot;</span> <span class="op">+</span></span>
<span id="cb7-55"><a href="#cb7-55" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;a=&quot;</span> <span class="op">+</span> a <span class="op">+</span></span>
<span id="cb7-56"><a href="#cb7-56" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, b=&quot;</span> <span class="op">+</span> b <span class="op">+</span></span>
<span id="cb7-57"><a href="#cb7-57" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, c=&quot;</span> <span class="op">+</span> c <span class="op">+</span></span>
<span id="cb7-58"><a href="#cb7-58" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, area=&quot;</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">getArea</span><span class="op">()</span> <span class="op">+</span></span>
<span id="cb7-59"><a href="#cb7-59" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, perimeter=&quot;</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">getPerimeter</span><span class="op">()</span> <span class="op">+</span></span>
<span id="cb7-60"><a href="#cb7-60" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, color=&#39;&quot;</span> <span class="op">+</span> color <span class="op">+</span> <span class="ch">&#39;\&#39;&#39;</span> <span class="op">+</span></span>
<span id="cb7-61"><a href="#cb7-61" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, filled=&quot;</span> <span class="op">+</span> filled <span class="op">+</span></span>
<span id="cb7-62"><a href="#cb7-62" aria-hidden="true" tabindex="-1"></a>                <span class="ch">&#39;}&#39;</span><span class="op">;</span></span>
<span id="cb7-63"><a href="#cb7-63" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb7-64"><a href="#cb7-64" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<blockquote>
<p>(kenndel#7506) Java is a beautiful language</p>
</blockquote>
<div class="sourceCode" id="cb8"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Triangle <span class="kw">extends</span> GeometricObject <span class="op">{</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> a<span class="op">;</span> <span class="co">// Side one.</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> b<span class="op">;</span> <span class="co">// Side two.</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> c<span class="op">;</span> <span class="co">// Side three.</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">Triangle</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">setA</span><span class="op">(</span><span class="fl">1.0</span><span class="op">);</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">setB</span><span class="op">(</span><span class="fl">1.0</span><span class="op">);</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">setC</span><span class="op">(</span><span class="fl">1.0</span><span class="op">);</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">Triangle</span><span class="op">(</span><span class="dt">double</span> a<span class="op">,</span> <span class="dt">double</span> b<span class="op">,</span> <span class="dt">double</span> c<span class="op">,</span> <span class="bu">String</span> d<span class="op">,</span> <span class="dt">boolean</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">(</span>d<span class="op">,</span> e<span class="op">);</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">setA</span><span class="op">(</span>a<span class="op">);</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">setB</span><span class="op">(</span>b<span class="op">);</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">setC</span><span class="op">(</span>c<span class="op">);</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">double</span> <span class="fu">getA</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> a<span class="op">;</span></span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">double</span> <span class="fu">getB</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> b<span class="op">;</span></span>
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-26"><a href="#cb8-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-27"><a href="#cb8-27" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">double</span> <span class="fu">getC</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb8-28"><a href="#cb8-28" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> c<span class="op">;</span></span>
<span id="cb8-29"><a href="#cb8-29" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-30"><a href="#cb8-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-31"><a href="#cb8-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">double</span> <span class="fu">getArea</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb8-32"><a href="#cb8-32" aria-hidden="true" tabindex="-1"></a>        <span class="dt">double</span> p <span class="op">=</span> <span class="op">(</span><span class="kw">this</span><span class="op">.</span><span class="fu">a</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">b</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">c</span><span class="op">)</span> <span class="op">/</span> <span class="dv">2</span><span class="op">;</span></span>
<span id="cb8-33"><a href="#cb8-33" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="bu">Math</span><span class="op">.</span><span class="fu">sqrt</span><span class="op">(</span>p <span class="op">*</span> <span class="op">(</span>p <span class="op">-</span> <span class="kw">this</span><span class="op">.</span><span class="fu">a</span><span class="op">)</span> <span class="op">*</span> <span class="op">(</span>p <span class="op">-</span> <span class="kw">this</span><span class="op">.</span><span class="fu">b</span><span class="op">)</span> <span class="op">*</span> <span class="op">(</span>p <span class="op">-</span> <span class="kw">this</span><span class="op">.</span><span class="fu">c</span><span class="op">));</span></span>
<span id="cb8-34"><a href="#cb8-34" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-35"><a href="#cb8-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-36"><a href="#cb8-36" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">double</span> <span class="fu">getPerimeter</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb8-37"><a href="#cb8-37" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">a</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">b</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">c</span><span class="op">;</span></span>
<span id="cb8-38"><a href="#cb8-38" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-39"><a href="#cb8-39" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-40"><a href="#cb8-40" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb8-41"><a href="#cb8-41" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">String</span> <span class="fu">toString</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb8-42"><a href="#cb8-42" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="st">&quot;Triangle{&quot;</span> <span class="op">+</span></span>
<span id="cb8-43"><a href="#cb8-43" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;a=&quot;</span> <span class="op">+</span> a <span class="op">+</span></span>
<span id="cb8-44"><a href="#cb8-44" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, b=&quot;</span> <span class="op">+</span> b <span class="op">+</span></span>
<span id="cb8-45"><a href="#cb8-45" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, c=&quot;</span> <span class="op">+</span> c <span class="op">+</span></span>
<span id="cb8-46"><a href="#cb8-46" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, area=&quot;</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">getArea</span><span class="op">()</span> <span class="op">+</span></span>
<span id="cb8-47"><a href="#cb8-47" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, perimeter=&quot;</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">getPerimeter</span><span class="op">()</span> <span class="op">+</span></span>
<span id="cb8-48"><a href="#cb8-48" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, color=&#39;&quot;</span> <span class="op">+</span> color <span class="op">+</span> <span class="ch">&#39;\&#39;&#39;</span> <span class="op">+</span></span>
<span id="cb8-49"><a href="#cb8-49" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, filled=&quot;</span> <span class="op">+</span> filled <span class="op">+</span></span>
<span id="cb8-50"><a href="#cb8-50" aria-hidden="true" tabindex="-1"></a>                <span class="ch">&#39;}&#39;</span><span class="op">;</span></span>
<span id="cb8-51"><a href="#cb8-51" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-52"><a href="#cb8-52" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Now lets give things more descriptive names and let's also get rid of that default constructor for now.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Triangle <span class="kw">extends</span> GeometricObject <span class="op">{</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideA<span class="op">;</span> <span class="co">// Side one.</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideB<span class="op">;</span> <span class="co">// Side two.</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideC<span class="op">;</span> <span class="co">// Side three.</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">Triangle</span><span class="op">(</span><span class="dt">double</span> sideA<span class="op">,</span> <span class="dt">double</span> sideB<span class="op">,</span> <span class="dt">double</span> sideC<span class="op">,</span> <span class="bu">String</span> color<span class="op">,</span> <span class="dt">boolean</span> filled<span class="op">)</span> <span class="op">{</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">(</span>color<span class="op">,</span> filled<span class="op">);</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">=</span> sideA<span class="op">;</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">=</span> sideB<span class="op">;</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span> <span class="op">=</span> sideC<span class="op">;</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">double</span> <span class="fu">getSideA</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span><span class="op">;</span></span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">double</span> <span class="fu">getSideB</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span><span class="op">;</span></span>
<span id="cb9-19"><a href="#cb9-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-20"><a href="#cb9-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-21"><a href="#cb9-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">double</span> <span class="fu">getSideC</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb9-22"><a href="#cb9-22" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span><span class="op">;</span></span>
<span id="cb9-23"><a href="#cb9-23" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-24"><a href="#cb9-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-25"><a href="#cb9-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">double</span> <span class="fu">getArea</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb9-26"><a href="#cb9-26" aria-hidden="true" tabindex="-1"></a>        <span class="dt">double</span> p <span class="op">=</span> <span class="op">(</span><span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span><span class="op">)</span> <span class="op">/</span> <span class="dv">2</span><span class="op">;</span></span>
<span id="cb9-27"><a href="#cb9-27" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="bu">Math</span><span class="op">.</span><span class="fu">sqrt</span><span class="op">(</span>p <span class="op">*</span> <span class="op">(</span>p <span class="op">-</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span><span class="op">)</span> <span class="op">*</span> <span class="op">(</span>p <span class="op">-</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span><span class="op">)</span> <span class="op">*</span> <span class="op">(</span>p <span class="op">-</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span><span class="op">));</span></span>
<span id="cb9-28"><a href="#cb9-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-29"><a href="#cb9-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-30"><a href="#cb9-30" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">double</span> <span class="fu">getPerimeter</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb9-31"><a href="#cb9-31" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span><span class="op">;</span></span>
<span id="cb9-32"><a href="#cb9-32" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-33"><a href="#cb9-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-34"><a href="#cb9-34" aria-hidden="true" tabindex="-1"></a>    <span class="at">@Override</span></span>
<span id="cb9-35"><a href="#cb9-35" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">String</span> <span class="fu">toString</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb9-36"><a href="#cb9-36" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="st">&quot;Triangle{&quot;</span> <span class="op">+</span></span>
<span id="cb9-37"><a href="#cb9-37" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;a=&quot;</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">+</span></span>
<span id="cb9-38"><a href="#cb9-38" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, b=&quot;</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">+</span></span>
<span id="cb9-39"><a href="#cb9-39" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, c=&quot;</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span> <span class="op">+</span></span>
<span id="cb9-40"><a href="#cb9-40" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, area=&quot;</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">getArea</span><span class="op">()</span> <span class="op">+</span></span>
<span id="cb9-41"><a href="#cb9-41" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, perimeter=&quot;</span> <span class="op">+</span> <span class="kw">this</span><span class="op">.</span><span class="fu">getPerimeter</span><span class="op">()</span> <span class="op">+</span></span>
<span id="cb9-42"><a href="#cb9-42" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, color=&#39;&quot;</span> <span class="op">+</span> color <span class="op">+</span> <span class="ch">&#39;\&#39;&#39;</span> <span class="op">+</span></span>
<span id="cb9-43"><a href="#cb9-43" aria-hidden="true" tabindex="-1"></a>                <span class="st">&quot;, filled=&quot;</span> <span class="op">+</span> filled <span class="op">+</span></span>
<span id="cb9-44"><a href="#cb9-44" aria-hidden="true" tabindex="-1"></a>                <span class="ch">&#39;}&#39;</span><span class="op">;</span></span>
<span id="cb9-45"><a href="#cb9-45" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-46"><a href="#cb9-46" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And for now on, I am going to leave out all of the methods for space</p>
<p>The first thing we want to do is make the constructor private, since we are going to be replacing the access pattern of "calling the constructor with all the arguments" with our builder.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Triangle <span class="kw">extends</span> GeometricObject <span class="op">{</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideA<span class="op">;</span> <span class="co">// Side one.</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideB<span class="op">;</span> <span class="co">// Side two.</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideC<span class="op">;</span> <span class="co">// Side three.</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Triangle</span><span class="op">(</span><span class="dt">double</span> sideA<span class="op">,</span> <span class="dt">double</span> sideB<span class="op">,</span> <span class="dt">double</span> sideC<span class="op">,</span> <span class="bu">String</span> color<span class="op">,</span> <span class="dt">boolean</span> filled<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">(</span>color<span class="op">,</span> filled<span class="op">);</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">=</span> sideA<span class="op">;</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">=</span> sideB<span class="op">;</span></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span> <span class="op">=</span> sideC<span class="op">;</span></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<blockquote>
<p>Never seen a private constructor before</p>
</blockquote>
<p>A private constructor can only be called from the class it is defined and stuff within that class, So lets make the stuff that goes in the class.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Triangle <span class="kw">extends</span> GeometricObject <span class="op">{</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideA<span class="op">;</span> <span class="co">// Side one.</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideB<span class="op">;</span> <span class="co">// Side two.</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideC<span class="op">;</span> <span class="co">// Side three.</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Triangle</span><span class="op">(</span><span class="dt">double</span> sideA<span class="op">,</span> <span class="dt">double</span> sideB<span class="op">,</span> <span class="dt">double</span> sideC<span class="op">,</span> <span class="bu">String</span> color<span class="op">,</span> <span class="dt">boolean</span> filled<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">(</span>color<span class="op">,</span> filled<span class="op">);</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">=</span> sideA<span class="op">;</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">=</span> sideB<span class="op">;</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span> <span class="op">=</span> sideC<span class="op">;</span></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="kw">class</span> Builder <span class="op">{}</span></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>We add a builder class within the triangle class. This builder can access all of the private methods of the Triangle class because it is in the Triangle class.</p>
<p>Now this builder needs to keep track of all of the information needed to build a triangle. We also want that information to be added one piece at a time - one method call at a time.</p>
<blockquote>
<p>Does it matter if Builder class is static or non static</p>
</blockquote>
<p>Yep. Thats a confusing java specific thing - feel free to google why that is needed.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Triangle <span class="kw">extends</span> GeometricObject <span class="op">{</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideA<span class="op">;</span> <span class="co">// Side one.</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideB<span class="op">;</span> <span class="co">// Side two.</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideC<span class="op">;</span> <span class="co">// Side three.</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Triangle</span><span class="op">(</span><span class="dt">double</span> sideA<span class="op">,</span> <span class="dt">double</span> sideB<span class="op">,</span> <span class="dt">double</span> sideC<span class="op">,</span> <span class="bu">String</span> color<span class="op">,</span> <span class="dt">boolean</span> filled<span class="op">)</span> <span class="op">{</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">(</span>color<span class="op">,</span> filled<span class="op">);</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">=</span> sideA<span class="op">;</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">=</span> sideB<span class="op">;</span></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span> <span class="op">=</span> sideC<span class="op">;</span></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="kw">class</span> Builder <span class="op">{</span></span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">double</span> sideA<span class="op">;</span></span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">double</span> sideB<span class="op">;</span></span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">double</span> sideC<span class="op">;</span></span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="bu">String</span> color<span class="op">;</span></span>
<span id="cb12-18"><a href="#cb12-18" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">boolean</span> filled<span class="op">;</span></span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-20"><a href="#cb12-20" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="fu">Builder</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb12-21"><a href="#cb12-21" aria-hidden="true" tabindex="-1"></a>                <span class="co">// Put any defaults here. If there isn&#39;t any default set it to null and check for that later</span></span>
<span id="cb12-22"><a href="#cb12-22" aria-hidden="true" tabindex="-1"></a>               <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">=</span> <span class="fl">1.0</span><span class="op">;</span></span>
<span id="cb12-23"><a href="#cb12-23" aria-hidden="true" tabindex="-1"></a>               <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">=</span> <span class="fl">1.0</span><span class="op">;</span></span>
<span id="cb12-24"><a href="#cb12-24" aria-hidden="true" tabindex="-1"></a>               <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span> <span class="op">=</span> <span class="fl">1.0</span><span class="op">;</span></span>
<span id="cb12-25"><a href="#cb12-25" aria-hidden="true" tabindex="-1"></a>               <span class="kw">this</span><span class="op">.</span><span class="fu">color</span> <span class="op">=</span> <span class="st">&quot;black&quot;</span><span class="op">;</span></span>
<span id="cb12-26"><a href="#cb12-26" aria-hidden="true" tabindex="-1"></a>               <span class="kw">this</span><span class="op">.</span><span class="fu">filled</span> <span class="op">=</span> <span class="kw">true</span><span class="op">;</span></span>
<span id="cb12-27"><a href="#cb12-27" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb12-28"><a href="#cb12-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-29"><a href="#cb12-29" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setSideA</span><span class="op">(</span><span class="dt">double</span> sideA<span class="op">)</span> <span class="op">{</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">=</span> sideA<span class="op">;</span> <span class="op">}</span></span>
<span id="cb12-30"><a href="#cb12-30" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setSideB</span><span class="op">(</span><span class="dt">double</span> sideB<span class="op">)</span> <span class="op">{</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">=</span> sideB<span class="op">;</span> <span class="op">}</span></span>
<span id="cb12-31"><a href="#cb12-31" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setSideC</span><span class="op">(</span><span class="dt">double</span> sideC<span class="op">)</span> <span class="op">{</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span> <span class="op">=</span> sideC<span class="op">;</span> <span class="op">}</span></span>
<span id="cb12-32"><a href="#cb12-32" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setColor</span><span class="op">(</span><span class="bu">String</span> color<span class="op">)</span> <span class="op">{</span> <span class="kw">this</span><span class="op">.</span><span class="fu">color</span> <span class="op">=</span> color<span class="op">;</span> <span class="op">}</span></span>
<span id="cb12-33"><a href="#cb12-33" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setFilled</span><span class="op">(</span><span class="dt">boolean</span> filled<span class="op">)</span> <span class="op">{</span> <span class="kw">this</span><span class="op">.</span><span class="fu">filled</span> <span class="op">=</span> filled<span class="op">;</span> <span class="op">}</span></span>
<span id="cb12-34"><a href="#cb12-34" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb12-35"><a href="#cb12-35" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Now you have the ability to mutate the builder for whatever you want.</p>
<blockquote>
<p>Wait, you have to redeclare the fields inside builder class?</p>
</blockquote>
<p>usually, yeah. It is far from a perfect system.</p>
<p>It is bad code to write, but it provides the nicest possible outward facing interface.</p>
<blockquote>
<p>So when you're mutating the fields inside builder does it update them in the main class also or just the builder class</p>
</blockquote>
<p>Just the builder class. No instance of the outer class exists yet.</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Triangle <span class="kw">extends</span> GeometricObject <span class="op">{</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideA<span class="op">;</span> <span class="co">// Side one.</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideB<span class="op">;</span> <span class="co">// Side two.</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideC<span class="op">;</span> <span class="co">// Side three.</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Triangle</span><span class="op">(</span><span class="dt">double</span> sideA<span class="op">,</span> <span class="dt">double</span> sideB<span class="op">,</span> <span class="dt">double</span> sideC<span class="op">,</span> <span class="bu">String</span> color<span class="op">,</span> <span class="dt">boolean</span> filled<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">(</span>color<span class="op">,</span> filled<span class="op">);</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">=</span> sideA<span class="op">;</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">=</span> sideB<span class="op">;</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span> <span class="op">=</span> sideC<span class="op">;</span></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="kw">class</span> Builder <span class="op">{</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">double</span> sideA<span class="op">;</span></span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">double</span> sideB<span class="op">;</span></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">double</span> sideC<span class="op">;</span></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="bu">String</span> color<span class="op">;</span></span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">boolean</span> filled<span class="op">;</span></span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="fu">Builder</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true" tabindex="-1"></a>           <span class="co">// Put any defaults here. If there isn&#39;t any default set it to null and check for that later</span></span>
<span id="cb13-22"><a href="#cb13-22" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">=</span> <span class="fl">1.0</span><span class="op">;</span></span>
<span id="cb13-23"><a href="#cb13-23" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">=</span> <span class="fl">1.0</span><span class="op">;</span></span>
<span id="cb13-24"><a href="#cb13-24" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span> <span class="op">=</span> <span class="fl">1.0</span><span class="op">;</span></span>
<span id="cb13-25"><a href="#cb13-25" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">color</span> <span class="op">=</span> <span class="st">&quot;black&quot;</span><span class="op">;</span></span>
<span id="cb13-26"><a href="#cb13-26" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">filled</span> <span class="op">=</span> <span class="kw">true</span><span class="op">;</span></span>
<span id="cb13-27"><a href="#cb13-27" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb13-28"><a href="#cb13-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-29"><a href="#cb13-29" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setSideA</span><span class="op">(</span><span class="dt">double</span> sideA<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-30"><a href="#cb13-30" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">=</span> sideA<span class="op">;</span> </span>
<span id="cb13-31"><a href="#cb13-31" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb13-32"><a href="#cb13-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-33"><a href="#cb13-33" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setSideB</span><span class="op">(</span><span class="dt">double</span> sideB<span class="op">)</span> <span class="op">{</span> </span>
<span id="cb13-34"><a href="#cb13-34" aria-hidden="true" tabindex="-1"></a>             <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">=</span> sideB<span class="op">;</span></span>
<span id="cb13-35"><a href="#cb13-35" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb13-36"><a href="#cb13-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-37"><a href="#cb13-37" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setSideC</span><span class="op">(</span><span class="dt">double</span> sideC<span class="op">)</span> <span class="op">{</span> </span>
<span id="cb13-38"><a href="#cb13-38" aria-hidden="true" tabindex="-1"></a>             <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span> <span class="op">=</span> sideC<span class="op">;</span></span>
<span id="cb13-39"><a href="#cb13-39" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb13-40"><a href="#cb13-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-41"><a href="#cb13-41" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setSideB</span><span class="op">(</span><span class="bu">String</span> color<span class="op">)</span> <span class="op">{</span> </span>
<span id="cb13-42"><a href="#cb13-42" aria-hidden="true" tabindex="-1"></a>             <span class="kw">this</span><span class="op">.</span><span class="fu">color</span> <span class="op">=</span> color<span class="op">;</span></span>
<span id="cb13-43"><a href="#cb13-43" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb13-44"><a href="#cb13-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-45"><a href="#cb13-45" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setFilled</span><span class="op">(</span><span class="dt">boolean</span> filled<span class="op">)</span> <span class="op">{</span> </span>
<span id="cb13-46"><a href="#cb13-46" aria-hidden="true" tabindex="-1"></a>             <span class="kw">this</span><span class="op">.</span><span class="fu">filled</span> <span class="op">=</span> filled<span class="op">;</span></span>
<span id="cb13-47"><a href="#cb13-47" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb13-48"><a href="#cb13-48" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-49"><a href="#cb13-49" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>No change yet, I just cleaned up the above code.</p>
<p>So now that we can set the properties on the builder we have to add a method for actually constructing the Triangle.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Triangle <span class="kw">extends</span> GeometricObject <span class="op">{</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideA<span class="op">;</span> <span class="co">// Side one.</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideB<span class="op">;</span> <span class="co">// Side two.</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideC<span class="op">;</span> <span class="co">// Side three.</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Triangle</span><span class="op">(</span><span class="dt">double</span> sideA<span class="op">,</span> <span class="dt">double</span> sideB<span class="op">,</span> <span class="dt">double</span> sideC<span class="op">,</span> <span class="bu">String</span> color<span class="op">,</span> <span class="dt">boolean</span> filled<span class="op">)</span> <span class="op">{</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">(</span>color<span class="op">,</span> filled<span class="op">);</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">=</span> sideA<span class="op">;</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">=</span> sideB<span class="op">;</span></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span> <span class="op">=</span> sideC<span class="op">;</span></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="kw">class</span> Builder <span class="op">{</span></span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">double</span> sideA<span class="op">;</span></span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">double</span> sideB<span class="op">;</span></span>
<span id="cb14-16"><a href="#cb14-16" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">double</span> sideC<span class="op">;</span></span>
<span id="cb14-17"><a href="#cb14-17" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="bu">String</span> color<span class="op">;</span></span>
<span id="cb14-18"><a href="#cb14-18" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">boolean</span> filled<span class="op">;</span></span>
<span id="cb14-19"><a href="#cb14-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-20"><a href="#cb14-20" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="fu">Builder</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb14-21"><a href="#cb14-21" aria-hidden="true" tabindex="-1"></a>           <span class="co">// Put any defaults here. If there isn&#39;t any default set it to null and check for that later</span></span>
<span id="cb14-22"><a href="#cb14-22" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">=</span> <span class="fl">1.0</span><span class="op">;</span></span>
<span id="cb14-23"><a href="#cb14-23" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">=</span> <span class="fl">1.0</span><span class="op">;</span></span>
<span id="cb14-24"><a href="#cb14-24" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span> <span class="op">=</span> <span class="fl">1.0</span><span class="op">;</span></span>
<span id="cb14-25"><a href="#cb14-25" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">color</span> <span class="op">=</span> <span class="st">&quot;black&quot;</span><span class="op">;</span></span>
<span id="cb14-26"><a href="#cb14-26" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">filled</span> <span class="op">=</span> <span class="kw">true</span><span class="op">;</span></span>
<span id="cb14-27"><a href="#cb14-27" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb14-28"><a href="#cb14-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-29"><a href="#cb14-29" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setSideA</span><span class="op">(</span><span class="dt">double</span> sideA<span class="op">)</span> <span class="op">{</span></span>
<span id="cb14-30"><a href="#cb14-30" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">=</span> sideA<span class="op">;</span> </span>
<span id="cb14-31"><a href="#cb14-31" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb14-32"><a href="#cb14-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-33"><a href="#cb14-33" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setSideB</span><span class="op">(</span><span class="dt">double</span> sideB<span class="op">)</span> <span class="op">{</span> </span>
<span id="cb14-34"><a href="#cb14-34" aria-hidden="true" tabindex="-1"></a>             <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">=</span> sideB<span class="op">;</span></span>
<span id="cb14-35"><a href="#cb14-35" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb14-36"><a href="#cb14-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-37"><a href="#cb14-37" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setSideC</span><span class="op">(</span><span class="dt">double</span> sideC<span class="op">)</span> <span class="op">{</span> </span>
<span id="cb14-38"><a href="#cb14-38" aria-hidden="true" tabindex="-1"></a>             <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span> <span class="op">=</span> sideC<span class="op">;</span></span>
<span id="cb14-39"><a href="#cb14-39" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb14-40"><a href="#cb14-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-41"><a href="#cb14-41" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setColor</span><span class="op">(</span><span class="bu">String</span> color<span class="op">)</span> <span class="op">{</span> </span>
<span id="cb14-42"><a href="#cb14-42" aria-hidden="true" tabindex="-1"></a>             <span class="kw">this</span><span class="op">.</span><span class="fu">color</span> <span class="op">=</span> color<span class="op">;</span></span>
<span id="cb14-43"><a href="#cb14-43" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb14-44"><a href="#cb14-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-45"><a href="#cb14-45" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setFilled</span><span class="op">(</span><span class="dt">boolean</span> filled<span class="op">)</span> <span class="op">{</span> </span>
<span id="cb14-46"><a href="#cb14-46" aria-hidden="true" tabindex="-1"></a>             <span class="kw">this</span><span class="op">.</span><span class="fu">filled</span> <span class="op">=</span> filled<span class="op">;</span></span>
<span id="cb14-47"><a href="#cb14-47" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb14-48"><a href="#cb14-48" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-49"><a href="#cb14-49" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Triangle <span class="fu">build</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb14-50"><a href="#cb14-50" aria-hidden="true" tabindex="-1"></a>             <span class="co">// You still need to remember the order, but it is only in one place at least</span></span>
<span id="cb14-51"><a href="#cb14-51" aria-hidden="true" tabindex="-1"></a>            <span class="co">// This is also the place you should put any validations. Checking if any required properties are not set, things are</span></span>
<span id="cb14-52"><a href="#cb14-52" aria-hidden="true" tabindex="-1"></a>           <span class="co">// set as null that should not be null, etc.</span></span>
<span id="cb14-53"><a href="#cb14-53" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Triangle</span><span class="op">(</span><span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span><span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span><span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span><span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">color</span><span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">filled</span><span class="op">);</span></span>
<span id="cb14-54"><a href="#cb14-54" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb14-55"><a href="#cb14-55" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-56"><a href="#cb14-56" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>now, as it is written now, you would end up using the builder like this</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>Triangle<span class="op">.</span><span class="fu">Builder</span> builder <span class="op">=</span> <span class="kw">new</span> Triangle<span class="op">.</span><span class="fu">Builder</span><span class="op">();</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>builder<span class="op">.</span><span class="fu">setSideA</span><span class="op">(</span><span class="kw">...</span><span class="op">);</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>builder<span class="op">.</span><span class="fu">setSideB</span><span class="op">(</span><span class="kw">...</span><span class="op">);</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>builder<span class="op">.</span><span class="fu">setSideC</span><span class="op">(</span><span class="kw">...</span><span class="op">);</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>builder<span class="op">.</span><span class="fu">setColor</span><span class="op">(</span><span class="kw">...</span><span class="op">);</span></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>builder<span class="op">.</span><span class="fu">setFilled</span><span class="op">(</span><span class="kw">...</span><span class="op">);</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>Triangle triangle <span class="op">=</span> builder<span class="op">.</span><span class="fu">build</span><span class="op">();</span></span></code></pre></div>
<p>One way to make it a bit easier to use the builder is to make each setter return a reference to the builder itself.</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Triangle <span class="kw">extends</span> GeometricObject <span class="op">{</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideA<span class="op">;</span> <span class="co">// Side one.</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideB<span class="op">;</span> <span class="co">// Side two.</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideC<span class="op">;</span> <span class="co">// Side three.</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Triangle</span><span class="op">(</span><span class="dt">double</span> sideA<span class="op">,</span> <span class="dt">double</span> sideB<span class="op">,</span> <span class="dt">double</span> sideC<span class="op">,</span> <span class="bu">String</span> color<span class="op">,</span> <span class="dt">boolean</span> filled<span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">(</span>color<span class="op">,</span> filled<span class="op">);</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">=</span> sideA<span class="op">;</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">=</span> sideB<span class="op">;</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span> <span class="op">=</span> sideC<span class="op">;</span></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="kw">class</span> Builder <span class="op">{</span></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">double</span> sideA<span class="op">;</span></span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">double</span> sideB<span class="op">;</span></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">double</span> sideC<span class="op">;</span></span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="bu">String</span> color<span class="op">;</span></span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">boolean</span> filled<span class="op">;</span></span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-20"><a href="#cb16-20" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="fu">Builder</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb16-21"><a href="#cb16-21" aria-hidden="true" tabindex="-1"></a>           <span class="co">// Put any defaults here. If there isn&#39;t any default set it to null and check for that later</span></span>
<span id="cb16-22"><a href="#cb16-22" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">=</span> <span class="fl">1.0</span><span class="op">;</span></span>
<span id="cb16-23"><a href="#cb16-23" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">=</span> <span class="fl">1.0</span><span class="op">;</span></span>
<span id="cb16-24"><a href="#cb16-24" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span> <span class="op">=</span> <span class="fl">1.0</span><span class="op">;</span></span>
<span id="cb16-25"><a href="#cb16-25" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">color</span> <span class="op">=</span> <span class="st">&quot;black&quot;</span><span class="op">;</span></span>
<span id="cb16-26"><a href="#cb16-26" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">filled</span> <span class="op">=</span> <span class="kw">true</span><span class="op">;</span></span>
<span id="cb16-27"><a href="#cb16-27" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb16-28"><a href="#cb16-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-29"><a href="#cb16-29" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Builder <span class="fu">setSideA</span><span class="op">(</span><span class="dt">double</span> sideA<span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-30"><a href="#cb16-30" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">=</span> sideA<span class="op">;</span> </span>
<span id="cb16-31"><a href="#cb16-31" aria-hidden="true" tabindex="-1"></a>             <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb16-32"><a href="#cb16-32" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb16-33"><a href="#cb16-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-34"><a href="#cb16-34" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Builder <span class="fu">setSideB</span><span class="op">(</span><span class="dt">double</span> sideB<span class="op">)</span> <span class="op">{</span> </span>
<span id="cb16-35"><a href="#cb16-35" aria-hidden="true" tabindex="-1"></a>             <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">=</span> sideB<span class="op">;</span></span>
<span id="cb16-36"><a href="#cb16-36" aria-hidden="true" tabindex="-1"></a>             <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb16-37"><a href="#cb16-37" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb16-38"><a href="#cb16-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-39"><a href="#cb16-39" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Builder <span class="fu">setSideC</span><span class="op">(</span><span class="dt">double</span> sideC<span class="op">)</span> <span class="op">{</span> </span>
<span id="cb16-40"><a href="#cb16-40" aria-hidden="true" tabindex="-1"></a>             <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span> <span class="op">=</span> sideC<span class="op">;</span></span>
<span id="cb16-41"><a href="#cb16-41" aria-hidden="true" tabindex="-1"></a>             <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb16-42"><a href="#cb16-42" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb16-43"><a href="#cb16-43" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-44"><a href="#cb16-44" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Builder <span class="fu">setColor</span><span class="op">(</span><span class="bu">String</span> color<span class="op">)</span> <span class="op">{</span> </span>
<span id="cb16-45"><a href="#cb16-45" aria-hidden="true" tabindex="-1"></a>             <span class="kw">this</span><span class="op">.</span><span class="fu">color</span> <span class="op">=</span> color<span class="op">;</span></span>
<span id="cb16-46"><a href="#cb16-46" aria-hidden="true" tabindex="-1"></a>             <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb16-47"><a href="#cb16-47" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb16-48"><a href="#cb16-48" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-49"><a href="#cb16-49" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Builder <span class="fu">setFilled</span><span class="op">(</span><span class="dt">boolean</span> filled<span class="op">)</span> <span class="op">{</span> </span>
<span id="cb16-50"><a href="#cb16-50" aria-hidden="true" tabindex="-1"></a>             <span class="kw">this</span><span class="op">.</span><span class="fu">filled</span> <span class="op">=</span> filled<span class="op">;</span></span>
<span id="cb16-51"><a href="#cb16-51" aria-hidden="true" tabindex="-1"></a>             <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb16-52"><a href="#cb16-52" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb16-53"><a href="#cb16-53" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-54"><a href="#cb16-54" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Triangle <span class="fu">build</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb16-55"><a href="#cb16-55" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Triangle</span><span class="op">(</span><span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span><span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span><span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span><span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">color</span><span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">filled</span><span class="op">);</span></span>
<span id="cb16-56"><a href="#cb16-56" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb16-57"><a href="#cb16-57" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-58"><a href="#cb16-58" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This lets you "chain" the method calls like this</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>Triangle triangle <span class="op">=</span> <span class="kw">new</span> Triangle<span class="op">.</span><span class="fu">Builder</span><span class="op">()</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">setSideA</span><span class="op">(</span><span class="kw">...</span><span class="op">)</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">setSideB</span><span class="op">(</span><span class="kw">...</span><span class="op">)</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">setSideC</span><span class="op">(</span><span class="kw">...</span><span class="op">)</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">setColor</span><span class="op">(</span><span class="kw">...</span><span class="op">)</span></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">setFilled</span><span class="op">(</span><span class="kw">...</span><span class="op">)</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">build</span><span class="op">();</span></span></code></pre></div>
<p>So that is the basic "pattern". From here on out its kinda all preference and style.</p>
<p>Personally, I don't like the <code>setThing</code> naming with builders, so I usually choose to just use the field name. In a builder its kinda understood that you are setting things.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Triangle <span class="kw">extends</span> GeometricObject <span class="op">{</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideA<span class="op">;</span> <span class="co">// Side one.</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideB<span class="op">;</span> <span class="co">// Side two.</span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideC<span class="op">;</span> <span class="co">// Side three.</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Triangle</span><span class="op">(</span><span class="dt">double</span> sideA<span class="op">,</span> <span class="dt">double</span> sideB<span class="op">,</span> <span class="dt">double</span> sideC<span class="op">,</span> <span class="bu">String</span> color<span class="op">,</span> <span class="dt">boolean</span> filled<span class="op">)</span> <span class="op">{</span></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">(</span>color<span class="op">,</span> filled<span class="op">);</span></span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">=</span> sideA<span class="op">;</span></span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">=</span> sideB<span class="op">;</span></span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span> <span class="op">=</span> sideC<span class="op">;</span></span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-13"><a href="#cb18-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="kw">class</span> Builder <span class="op">{</span></span>
<span id="cb18-14"><a href="#cb18-14" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">double</span> sideA<span class="op">;</span></span>
<span id="cb18-15"><a href="#cb18-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">double</span> sideB<span class="op">;</span></span>
<span id="cb18-16"><a href="#cb18-16" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">double</span> sideC<span class="op">;</span></span>
<span id="cb18-17"><a href="#cb18-17" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="bu">String</span> color<span class="op">;</span></span>
<span id="cb18-18"><a href="#cb18-18" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">boolean</span> filled<span class="op">;</span></span>
<span id="cb18-19"><a href="#cb18-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-20"><a href="#cb18-20" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> <span class="fu">Builder</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb18-21"><a href="#cb18-21" aria-hidden="true" tabindex="-1"></a>           <span class="co">// Put any defaults here. If there isn&#39;t any default set it to null and check for that later</span></span>
<span id="cb18-22"><a href="#cb18-22" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">=</span> <span class="fl">1.0</span><span class="op">;</span></span>
<span id="cb18-23"><a href="#cb18-23" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">=</span> <span class="fl">1.0</span><span class="op">;</span></span>
<span id="cb18-24"><a href="#cb18-24" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span> <span class="op">=</span> <span class="fl">1.0</span><span class="op">;</span></span>
<span id="cb18-25"><a href="#cb18-25" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">color</span> <span class="op">=</span> <span class="st">&quot;black&quot;</span><span class="op">;</span></span>
<span id="cb18-26"><a href="#cb18-26" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">filled</span> <span class="op">=</span> <span class="kw">true</span><span class="op">;</span></span>
<span id="cb18-27"><a href="#cb18-27" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb18-28"><a href="#cb18-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-29"><a href="#cb18-29" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Builder <span class="fu">sideA</span><span class="op">(</span><span class="dt">double</span> sideA<span class="op">)</span> <span class="op">{</span></span>
<span id="cb18-30"><a href="#cb18-30" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">=</span> sideA<span class="op">;</span> </span>
<span id="cb18-31"><a href="#cb18-31" aria-hidden="true" tabindex="-1"></a>             <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb18-32"><a href="#cb18-32" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb18-33"><a href="#cb18-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-34"><a href="#cb18-34" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Builder <span class="fu">sideB</span><span class="op">(</span><span class="dt">double</span> sideB<span class="op">)</span> <span class="op">{</span> </span>
<span id="cb18-35"><a href="#cb18-35" aria-hidden="true" tabindex="-1"></a>             <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">=</span> sideB<span class="op">;</span></span>
<span id="cb18-36"><a href="#cb18-36" aria-hidden="true" tabindex="-1"></a>             <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb18-37"><a href="#cb18-37" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb18-38"><a href="#cb18-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-39"><a href="#cb18-39" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Builder <span class="fu">sideC</span><span class="op">(</span><span class="dt">double</span> sideC<span class="op">)</span> <span class="op">{</span> </span>
<span id="cb18-40"><a href="#cb18-40" aria-hidden="true" tabindex="-1"></a>             <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span> <span class="op">=</span> sideC<span class="op">;</span></span>
<span id="cb18-41"><a href="#cb18-41" aria-hidden="true" tabindex="-1"></a>             <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb18-42"><a href="#cb18-42" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb18-43"><a href="#cb18-43" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-44"><a href="#cb18-44" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Builder <span class="fu">color</span><span class="op">(</span><span class="bu">String</span> color<span class="op">)</span> <span class="op">{</span> </span>
<span id="cb18-45"><a href="#cb18-45" aria-hidden="true" tabindex="-1"></a>             <span class="kw">this</span><span class="op">.</span><span class="fu">color</span> <span class="op">=</span> color<span class="op">;</span></span>
<span id="cb18-46"><a href="#cb18-46" aria-hidden="true" tabindex="-1"></a>             <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb18-47"><a href="#cb18-47" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb18-48"><a href="#cb18-48" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-49"><a href="#cb18-49" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Builder <span class="fu">filled</span><span class="op">(</span><span class="dt">boolean</span> filled<span class="op">)</span> <span class="op">{</span> </span>
<span id="cb18-50"><a href="#cb18-50" aria-hidden="true" tabindex="-1"></a>             <span class="kw">this</span><span class="op">.</span><span class="fu">filled</span> <span class="op">=</span> filled<span class="op">;</span></span>
<span id="cb18-51"><a href="#cb18-51" aria-hidden="true" tabindex="-1"></a>             <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb18-52"><a href="#cb18-52" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb18-53"><a href="#cb18-53" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-54"><a href="#cb18-54" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Triangle <span class="fu">build</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb18-55"><a href="#cb18-55" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Triangle</span><span class="op">(</span><span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span><span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span><span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span><span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">color</span><span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">filled</span><span class="op">);</span></span>
<span id="cb18-56"><a href="#cb18-56" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb18-57"><a href="#cb18-57" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb18-58"><a href="#cb18-58" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb19"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>Triangle triangle <span class="op">=</span> <span class="kw">new</span> Triangle<span class="op">.</span><span class="fu">Builder</span><span class="op">()</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">sideA</span><span class="op">(</span><span class="kw">...</span><span class="op">)</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">sideB</span><span class="op">(</span><span class="kw">...</span><span class="op">)</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">sideC</span><span class="op">(</span><span class="kw">...</span><span class="op">)</span></span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">color</span><span class="op">(</span><span class="kw">...</span><span class="op">)</span></span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">filled</span><span class="op">(</span><span class="kw">...</span><span class="op">)</span></span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">build</span><span class="op">();</span></span></code></pre></div>
<p>The other thing that is useful is to make the actual builder not constructable but instead give out an instance via a static method.</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> Triangle <span class="kw">extends</span> GeometricObject <span class="op">{</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideA<span class="op">;</span> <span class="co">// Side one.</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideB<span class="op">;</span> <span class="co">// Side two.</span></span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="dt">double</span> sideC<span class="op">;</span> <span class="co">// Side three.</span></span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Triangle</span><span class="op">(</span><span class="dt">double</span> sideA<span class="op">,</span> <span class="dt">double</span> sideB<span class="op">,</span> <span class="dt">double</span> sideC<span class="op">,</span> <span class="bu">String</span> color<span class="op">,</span> <span class="dt">boolean</span> filled<span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">super</span><span class="op">(</span>color<span class="op">,</span> filled<span class="op">);</span></span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">=</span> sideA<span class="op">;</span></span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">=</span> sideB<span class="op">;</span></span>
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span> <span class="op">=</span> sideC<span class="op">;</span></span>
<span id="cb20-11"><a href="#cb20-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-12"><a href="#cb20-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-13"><a href="#cb20-13" aria-hidden="true" tabindex="-1"></a>    <span class="co">// You get a new builder via Triangle.builder()</span></span>
<span id="cb20-14"><a href="#cb20-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> Builder <span class="fu">builder</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb20-15"><a href="#cb20-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Builder</span><span class="op">();</span></span>
<span id="cb20-16"><a href="#cb20-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-17"><a href="#cb20-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-18"><a href="#cb20-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="kw">class</span> Builder <span class="op">{</span></span>
<span id="cb20-19"><a href="#cb20-19" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">double</span> sideA<span class="op">;</span></span>
<span id="cb20-20"><a href="#cb20-20" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">double</span> sideB<span class="op">;</span></span>
<span id="cb20-21"><a href="#cb20-21" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">double</span> sideC<span class="op">;</span></span>
<span id="cb20-22"><a href="#cb20-22" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="bu">String</span> color<span class="op">;</span></span>
<span id="cb20-23"><a href="#cb20-23" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="dt">boolean</span> filled<span class="op">;</span></span>
<span id="cb20-24"><a href="#cb20-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-25"><a href="#cb20-25" aria-hidden="true" tabindex="-1"></a>        <span class="co">// And now this is private so your users don&#39;t construct it directly</span></span>
<span id="cb20-26"><a href="#cb20-26" aria-hidden="true" tabindex="-1"></a>        <span class="kw">private</span> <span class="fu">Builder</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb20-27"><a href="#cb20-27" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">=</span> <span class="fl">1.0</span><span class="op">;</span></span>
<span id="cb20-28"><a href="#cb20-28" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">=</span> <span class="fl">1.0</span><span class="op">;</span></span>
<span id="cb20-29"><a href="#cb20-29" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span> <span class="op">=</span> <span class="fl">1.0</span><span class="op">;</span></span>
<span id="cb20-30"><a href="#cb20-30" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">color</span> <span class="op">=</span> <span class="st">&quot;black&quot;</span><span class="op">;</span></span>
<span id="cb20-31"><a href="#cb20-31" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">filled</span> <span class="op">=</span> <span class="kw">true</span><span class="op">;</span></span>
<span id="cb20-32"><a href="#cb20-32" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb20-33"><a href="#cb20-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-34"><a href="#cb20-34" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Builder <span class="fu">sideA</span><span class="op">(</span><span class="dt">double</span> sideA<span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-35"><a href="#cb20-35" aria-hidden="true" tabindex="-1"></a>            <span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span> <span class="op">=</span> sideA<span class="op">;</span> </span>
<span id="cb20-36"><a href="#cb20-36" aria-hidden="true" tabindex="-1"></a>             <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb20-37"><a href="#cb20-37" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb20-38"><a href="#cb20-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-39"><a href="#cb20-39" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Builder <span class="fu">sideB</span><span class="op">(</span><span class="dt">double</span> sideB<span class="op">)</span> <span class="op">{</span> </span>
<span id="cb20-40"><a href="#cb20-40" aria-hidden="true" tabindex="-1"></a>             <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span> <span class="op">=</span> sideB<span class="op">;</span></span>
<span id="cb20-41"><a href="#cb20-41" aria-hidden="true" tabindex="-1"></a>             <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb20-42"><a href="#cb20-42" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb20-43"><a href="#cb20-43" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-44"><a href="#cb20-44" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Builder <span class="fu">sideC</span><span class="op">(</span><span class="dt">double</span> sideC<span class="op">)</span> <span class="op">{</span> </span>
<span id="cb20-45"><a href="#cb20-45" aria-hidden="true" tabindex="-1"></a>             <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span> <span class="op">=</span> sideC<span class="op">;</span></span>
<span id="cb20-46"><a href="#cb20-46" aria-hidden="true" tabindex="-1"></a>             <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb20-47"><a href="#cb20-47" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb20-48"><a href="#cb20-48" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-49"><a href="#cb20-49" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Builder <span class="fu">color</span><span class="op">(</span><span class="bu">String</span> color<span class="op">)</span> <span class="op">{</span> </span>
<span id="cb20-50"><a href="#cb20-50" aria-hidden="true" tabindex="-1"></a>             <span class="kw">this</span><span class="op">.</span><span class="fu">color</span> <span class="op">=</span> color<span class="op">;</span></span>
<span id="cb20-51"><a href="#cb20-51" aria-hidden="true" tabindex="-1"></a>             <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb20-52"><a href="#cb20-52" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb20-53"><a href="#cb20-53" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-54"><a href="#cb20-54" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Builder <span class="fu">filled</span><span class="op">(</span><span class="dt">boolean</span> filled<span class="op">)</span> <span class="op">{</span> </span>
<span id="cb20-55"><a href="#cb20-55" aria-hidden="true" tabindex="-1"></a>             <span class="kw">this</span><span class="op">.</span><span class="fu">filled</span> <span class="op">=</span> filled<span class="op">;</span></span>
<span id="cb20-56"><a href="#cb20-56" aria-hidden="true" tabindex="-1"></a>             <span class="cf">return</span> <span class="kw">this</span><span class="op">;</span></span>
<span id="cb20-57"><a href="#cb20-57" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb20-58"><a href="#cb20-58" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-59"><a href="#cb20-59" aria-hidden="true" tabindex="-1"></a>        <span class="kw">public</span> Triangle <span class="fu">build</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb20-60"><a href="#cb20-60" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="kw">new</span> <span class="fu">Triangle</span><span class="op">(</span><span class="kw">this</span><span class="op">.</span><span class="fu">sideA</span><span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideB</span><span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">sideC</span><span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">color</span><span class="op">,</span> <span class="kw">this</span><span class="op">.</span><span class="fu">filled</span><span class="op">);</span></span>
<span id="cb20-61"><a href="#cb20-61" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb20-62"><a href="#cb20-62" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb20-63"><a href="#cb20-63" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb21"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>Triangle triangle <span class="op">=</span> Triangle<span class="op">.</span><span class="fu">builder</span><span class="op">()</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">sideA</span><span class="op">(</span><span class="kw">...</span><span class="op">)</span></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">sideB</span><span class="op">(</span><span class="kw">...</span><span class="op">)</span></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">sideC</span><span class="op">(</span><span class="kw">...</span><span class="op">)</span></span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">color</span><span class="op">(</span><span class="kw">...</span><span class="op">)</span></span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">filled</span><span class="op">(</span><span class="kw">...</span><span class="op">)</span></span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">.</span><span class="fu">build</span><span class="op">();</span></span></code></pre></div>
<p>I don't have a real rock solid argument for the <code>.builder()</code> static method other than it looks better, but I think I might have in the past.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How to print every item in a list</title><link>https://mccue.dev/pages/3-7-19-how-to-print-elements-of-list</link><description></description><pubDate>Thu, 07 Mar 0019 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How to print every item in a list</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How to print every item in a list</h1>
</header>
<blockquote>
<p>How can I get items inside a list to print into the terminal individually in Python</p>
<p>List = ["cat", "dog", "snake"]</p>
<p>I want them to print to the terminal on a separate line like</p>
<p>Cat</p>
<p>Dog</p>
<p>Snake</p>
<p>Oh I googled it</p>
<p>I did google it before but I didn't phrase it correctly</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> x <span class="kw">in</span> <span class="bu">list</span>:</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="bu">print</span>(x)</span></code></pre></div>
</blockquote>
<p>I will save you some time in the future then for other data structures</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="co"># list</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>x <span class="op">=</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>]</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> thing <span class="kw">in</span> x:</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="bu">print</span>(thing)</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="co"># dictionary</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>x <span class="op">=</span> { <span class="st">&quot;a&quot;</span>: <span class="st">&quot;apple&quot;</span>, <span class="st">&quot;b&quot;</span>: <span class="st">&quot;banana&quot;</span> }</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="co">## For everything here, don&#39;t rely on the order you get them in being the same always</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> key <span class="kw">in</span> x:</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>    <span class="bu">print</span>(key) <span class="co"># will give you &quot;a&quot; and &quot;b&quot;</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> key <span class="kw">in</span> x.keys():</span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>    <span class="bu">print</span>(key) <span class="co"># identical behaviour to the above, but a bit more explicit</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> value <span class="kw">in</span> x.values():</span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a>    <span class="bu">print</span>(value) <span class="co"># Will give you &quot;apple&quot; and &quot;banana&quot;</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> key, value <span class="kw">in</span> x.items():</span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a>    <span class="bu">print</span>(key) <span class="co"># Will give you the pairs (&quot;a&quot;, &quot;apple&quot;) and (&quot;b&quot;, &quot;banana&quot;)</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a>    <span class="bu">print</span>(value)</span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a><span class="co">&quot;a&quot;</span> <span class="kw">in</span> x <span class="co"># Will evaluate to True</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a><span class="co">&quot;apple&quot;</span> <span class="kw">in</span> x <span class="co"># Will evaluate to False. &quot;in&quot; with a dictionary checks keys.</span></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a><span class="co"># sets</span></span>
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a>x <span class="op">=</span> { <span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span> }</span>
<span id="cb2-29"><a href="#cb2-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-30"><a href="#cb2-30" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> thing <span class="kw">in</span> x:</span>
<span id="cb2-31"><a href="#cb2-31" aria-hidden="true" tabindex="-1"></a>    <span class="bu">print</span>(thing) <span class="co"># Will give you 1, 2, and 3, but just like dicts dont rely on the order</span></span>
<span id="cb2-32"><a href="#cb2-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-33"><a href="#cb2-33" aria-hidden="true" tabindex="-1"></a><span class="co">## A set is the data structure you should use if you want a list of things where it wouldn&#39;t matter</span></span>
<span id="cb2-34"><a href="#cb2-34" aria-hidden="true" tabindex="-1"></a><span class="co">## how many times something is in the list and you don&#39;t care about the ordering of those things</span></span>
<span id="cb2-35"><a href="#cb2-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-36"><a href="#cb2-36" aria-hidden="true" tabindex="-1"></a><span class="dv">1</span> <span class="kw">in</span> x <span class="co"># Will evaluate to True</span></span>
<span id="cb2-37"><a href="#cb2-37" aria-hidden="true" tabindex="-1"></a><span class="dv">4</span> <span class="kw">in</span> x <span class="co"># Will evaluate to False</span></span>
<span id="cb2-38"><a href="#cb2-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-39"><a href="#cb2-39" aria-hidden="true" tabindex="-1"></a><span class="co">## Small note, make an empty set by calling set(), not by using empty braces {} - That will create an empty dictionary</span></span></code></pre></div>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Bad reasons to avoid NodeJS</title><link>https://mccue.dev/pages/3-6-19-you-shouldnt-avoid-node-because-of-speed</link><description></description><pubDate>Wed, 06 Mar 0019 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Bad reasons to avoid NodeJS</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Bad reasons to avoid NodeJS</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
## Conversation with _diamondburned_#4507

<blockquote>
<p>you shouldn't ever use nodejs anyway</p>
<p>dependencies</p>
<p>slow performance</p>
<p>shit language was never designed for backend anywa</p>
<p>3.00000000000000000000000003</p>
<p>shit libraries</p>
<p>bloated</p>
<p>each line is a reason btw</p>
<p>even when not activating, it's still slower than compiled languages</p>
</blockquote>
<p>Speed is a nonsensical reason to not use node. JS vms are pretty fast and the kind of applications that use node are mostly IO bound, which V8's async system is pretty good at.</p>
<blockquote>
<p>It is for me when it comes to restarting a service for maintenance reason or for complex code</p>
</blockquote>
<p>Thats not how you should be running servers to be honest.</p>
<p>"I won't get downtime because I can restart a server ultra fast" really isn't a sensible plan, even if your server is the fastest thing in the world written in rust</p>
<p>Either you architect your devops to allow zero downtime (multiple nodes, cycling restarts, multi DC maybe) or you live with having to do maintenance on/off hours.</p>
<p>Startup time of node has no impact on that.</p>
<p>As always basically everything has an exception at Google scale and it's not like there aren't valid potshots to take at Node and Javascript, but as a platform it really does excel at IO heavy tasks.</p>
<blockquote>
<p>wdym heavy IO tasks?</p>
</blockquote>
<p>Well, for example, the majority of the time a webserver spends handling a request is spent in IO. Waiting for a database to respond, sending data to the user, receiving a request.</p>
<p>Maybe it's a websocket thing and you receive from one user and broadcast to others. Either way, the time spent handling that almost always dominates the amount of time spent actually running code in the js thread.</p>
<p>The model of "okay, here is this IO task - give it to another thread and tell me what the results are when it's done" works out pretty well performance wise.</p>
<p>Also, the cold startup for node is only really bad if you compare it to Rust, C, and C++ which isn't really fair.</p>
<p><a href="https://medium.com/@nathan.malishev/lambda-cold-starts-language-comparison-%EF%B8%8F-a4f4b5f16a62">https://medium.com/@nathan.malishev/lambda-cold-starts-language-comparison-%EF%B8%8F-a4f4b5f16a62</a></p>
<p>C and C++ require pretty huge tradeoffs in terms of developer speed and possibility of errors, so they really aren't targeted at the same users as node and rust - well rust is a lot better but being super statically typed still has tradeoffs with how quick you can change things which means it won't be the right choice for every "webserver" use case.</p>
<blockquote>
<blockquote>
<p>okay, here is this IO task - give it to another thread and tell me what the results are when it's done</p>
</blockquote>
<p>so bringing go into the equation, go routine workers</p>
</blockquote>
<p>Yeah I think go's async model is better too.</p>
<p>But go isn't that monumentally faster than node that you can say "forget node it's too slow" because it really isn't.</p>
<p>Neither is python for that matter. Though python's async and package management story are a lot worse , it is still the reigning king of glue languages.</p>
<p>Some critical path too slow?</p>
<p>Rewrite it in Rust, join the meme.</p>
<p>Python will keep on chugging.</p>
<p>I mean, the GIL stinks, but it's still not "painfully" slow.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How to display execution times</title><link>https://mccue.dev/pages/3-1-19-how-to-display-execution-times</link><description></description><pubDate>Fri, 01 Mar 0019 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How to display execution times</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How to display execution times</h1>
</header>
<h2 id="question-from-abdul4709">Question from Abdul#4709</h2>
<blockquote>
<p>Stuck on LinkedLists</p>
<p>Anyone knows how to display execution times</p>
</blockquote>
<p>Probably out of scope for your assignment, but you can always use something like this</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span> <span class="dt">void</span> <span class="fu">timeProcedure</span><span class="op">(</span><span class="bu">Runnable</span> procedure<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">long</span> start <span class="op">=</span> <span class="bu">System</span><span class="op">.</span><span class="fu">currentTimeMillis</span><span class="op">();</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    procedure<span class="op">.</span><span class="fu">run</span><span class="op">();</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">long</span> end <span class="op">=</span> <span class="bu">System</span><span class="op">.</span><span class="fu">currentTimeMillis</span><span class="op">();</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">long</span> duration <span class="op">=</span> end <span class="op">-</span> start<span class="op">;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>duration <span class="op">+</span> <span class="st">&quot; milliseconds.&quot;</span><span class="op">);</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>and then you can do something like</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="fu">timeProcedure</span><span class="op">(()</span> <span class="op">-&gt;</span> linkedList<span class="op">.</span><span class="fu">get</span><span class="op">(</span><span class="dv">1000000</span> <span class="op">/</span> <span class="dv">2</span><span class="op">);</span></span></code></pre></div>
<p>You can also add the name to have better debugging</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span> <span class="dt">void</span> <span class="fu">timeProcedure</span><span class="op">(</span><span class="bu">String</span> procedureName<span class="op">,</span> <span class="bu">Runnable</span> procedure<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">long</span> start <span class="op">=</span> <span class="bu">System</span><span class="op">.</span><span class="fu">currentTimeMillis</span><span class="op">();</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    procedure<span class="op">.</span><span class="fu">run</span><span class="op">();</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">long</span> end <span class="op">=</span> <span class="bu">System</span><span class="op">.</span><span class="fu">currentTimeMillis</span><span class="op">();</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">long</span> duration <span class="op">=</span> end <span class="op">-</span> start<span class="op">;</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    <span class="bu">System</span><span class="op">.</span><span class="fu">out</span><span class="op">.</span><span class="fu">println</span><span class="op">(</span>procedureName <span class="op">+</span> <span class="st">&quot; took &quot;</span> <span class="op">+</span> duration <span class="op">+</span> <span class="st">&quot; milliseconds.&quot;</span><span class="op">);</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="fu">timeProcedure</span><span class="op">(</span><span class="st">&quot;Accessing an element in the middle of a linked list&quot;</span><span class="op">,</span> <span class="op">()</span> <span class="op">-&gt;</span> linkedList<span class="op">.</span><span class="fu">get</span><span class="op">(</span><span class="dv">100000</span> <span class="op">/</span> <span class="dv">2</span><span class="op">))</span></span></code></pre></div>
<p>which would output something like</p>
<pre><code>Accessing an element in the middle of a linked list took 33 milliseconds</code></pre>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>MVC Origin</title><link>https://mccue.dev/pages/2-17-19-mvc-origin</link><description></description><pubDate>Sun, 17 Feb 0019 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>MVC Origin</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">MVC Origin</h1>
</header>
<div style="display: inline"> by:  <b style="display: inline"> Ethan McCue</b></div>
 <br/><script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script><script type='text/javascript'>kofiwidget2.init('Support me on Ko-fi', '#72a4f2', 'R6R71Z2ESQ');kofiwidget2.draw();</script><br/><br/> 
So, tiny history lesson.
The phrase and acronym "MVC" came out of this:

<p><a href="http://heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html">http://heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html</a></p>
<p>I don't think that's the original memo, but it was just one person in the late 70s who hypothesised that it would be a good model.</p>
<p>And it turns out that yes, separating your concerns like this does in fact make your code easier to write and maintain generally.</p>
<p>but for a web server beyond a small project I think you will find that it all doesn't fit so cleanly into exactly 3 buckets M, V, and C.</p>
<p>The django project uses MV* and I think that gets to the heart of it.</p>
<p>Yes, there is a part of your code involved with storing and modeling your data and yes, there is a part of your code involved with displaying a view but beyond that its... fuzzy.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>Is it okay to have a class with just methods</title><link>https://mccue.dev/pages/2-16-19-is-it-okay-to-have-a-class-with-just-methods</link><description></description><pubDate>Sat, 16 Feb 0019 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Is it okay to have a class with just methods</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Is it okay to have a class with just methods</h1>
</header>
<h2 id="question-from-davidv72315">Question from davidv7#2315</h2>
<blockquote>
<p>would it be ok to just have a class with methods, no class parameters?</p>
<p>aka</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Thing<span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">Thing</span><span class="op">(){</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="fu">method1</span><span class="op">(</span>args<span class="op">..)</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="fu">method2</span><span class="op">(</span>args<span class="kw">...</span><span class="op">)</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>in java</p>
</blockquote>
<p>So specifically if you want to do that you have a few considerations.</p>
<p>Java kinda obscures this, but first consider "Does this method perform a side effect" meaning, does it read from a db, write to a db, print something out, load a file, etc.</p>
<p>If the answer is NO then you can make a "Utils" class</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Utils <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">private</span> <span class="fu">Utils</span><span class="op">()</span> <span class="op">{}</span> <span class="co">// We don&#39;t need to construct this class so just disallow it</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">// This is a pure function so it is perfectly fine to put it into a helper method like this</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="dt">static</span> <span class="fu">absoluteValuePlusOne</span><span class="op">(</span><span class="dt">int</span> num<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="bu">Math</span><span class="op">.</span><span class="fu">abs</span><span class="op">(</span>num<span class="op">)</span> <span class="op">+</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>If the answer is YES then there is some value in a class with no parameters. Namely, that class can implement an interface.</p>
<p>Lets say this was your behaviour</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>MyDataSource dataSource <span class="op">=</span> <span class="kw">new</span> <span class="fu">MyDataSource</span><span class="op">();</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="bu">List</span><span class="op">&lt;</span>OrderItem<span class="op">&gt;</span> items <span class="op">=</span> dataSource<span class="op">.</span><span class="fu">getItems</span><span class="op">();</span></span></code></pre></div>
<p>If you wanted to make that behaviour customizable you can put that in an interface.</p>
<p>(IF being a word I want you to notice: When you "abstract" you make code a little harder to understand so always consider if you actually want that)</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">interface</span> <span class="bu">DataSource</span> <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Does a thing</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>    <span class="bu">List</span><span class="op">&lt;</span>OrderItem<span class="op">&gt;</span> <span class="fu">getItems</span><span class="op">();</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And use a class with an empty constructor to implement it</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="kw">class</span> MyDataSource <span class="kw">implements</span> <span class="bu">DataSource</span> <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="fu">MyDataSource</span><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span> <span class="bu">List</span><span class="op">&lt;</span>OrderItem<span class="op">&gt;</span> <span class="fu">getItems</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>        <span class="co">// ... Some implementation goes here ...</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Which provides you the benefit of being able to swap in how that behaviour is done later on or in different places in your code</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="bu">DataSource</span> dataSource <span class="op">=</span> <span class="kw">new</span> <span class="fu">MyDataSource</span><span class="op">();</span> <span class="co">// Can be any implementation</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="bu">List</span><span class="op">&lt;</span>OrderItem<span class="op">&gt;</span> items <span class="op">=</span> dataSource<span class="op">.</span><span class="fu">getItems</span><span class="op">();</span></span></code></pre></div>
<div class="sourceCode" id="cb7"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="fu">someMethodInSomeClass</span><span class="op">(</span><span class="bu">DataSource</span> dataSource<span class="op">,</span> <span class="bu">String</span> userId<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ... can do some hoopla and not have to be changed if your method of retrieving data changes</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// (the example is kinda contrived, I know, but basically every programming example is)</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Using an interface in key places also has implications for how you test your code, but I won't get into that now.</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item><item><title>How do you make a fixed size circular buffer</title><link>https://mccue.dev/pages/1-28-19-circular-buffer</link><description></description><pubDate>Mon, 28 Jan 0019 05:18:08 +0000</pubDate><content:encoded><![CDATA[<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>How do you make a fixed size circular buffer</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
      }
    pre.numberSource { margin-left: 3em;  padding-left: 4px; }
    div.sourceCode
      { color: #cccccc; background-color: #303030; }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ffcfaf; } /* Alert */
    code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
    code span.at { } /* Attribute */
    code span.bn { color: #dca3a3; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #f0dfaf; } /* ControlFlow */
    code span.ch { color: #dca3a3; } /* Char */
    code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
    code span.co { color: #7f9f7f; } /* Comment */
    code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
    code span.do { color: #7f9f7f; } /* Documentation */
    code span.dt { color: #dfdfbf; } /* DataType */
    code span.dv { color: #dcdccc; } /* DecVal */
    code span.er { color: #c3bf9f; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #c0bed1; } /* Float */
    code span.fu { color: #efef8f; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
    code span.kw { color: #f0dfaf; } /* Keyword */
    code span.op { color: #f0efd0; } /* Operator */
    code span.ot { color: #efef8f; } /* Other */
    code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
    code span.sc { color: #dca3a3; } /* SpecialChar */
    code span.ss { color: #cc9393; } /* SpecialString */
    code span.st { color: #cc9393; } /* String */
    code span.va { } /* Variable */
    code span.vs { color: #cc9393; } /* VerbatimString */
    code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">How do you make a fixed size circular buffer</h1>
</header>
<h2 id="question-from-johndoe9991">Question from JohnDoe#9991</h2>
<blockquote>
<p>How would you have an object with 2 values that'd work like this</p>
<p>&gt;(0,1)</p>
<p>&gt;add(2)</p>
<p>(1,2)</p>
<p>&gt;add(3)</p>
<p>(2,3)</p>
<p>&gt;add(10)</p>
<p>(3,10)</p>
<p>&gt;add(50)</p>
<p>(10, 50)</p>
<p>etc</p>
<p>ie replacing the oldest value</p>
<p>An ordered array with unlimited size and removing the oldest value when something is added would do but that'd be ugly</p>
</blockquote>
<p>In general you can do that with a "circular buffer"</p>
<p>Here you go.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> CircularBuffer:</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>, size<span class="op">=</span><span class="dv">2</span>):</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>        <span class="va">self</span>._buffer <span class="op">=</span> []</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>        <span class="va">self</span>._size <span class="op">=</span> size</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>        <span class="va">self</span>._index <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">def</span> add(<span class="va">self</span>, item):</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>        <span class="co"># This follows your &quot;add&quot;</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="bu">len</span>(<span class="va">self</span>._buffer) <span class="op">&lt;</span> <span class="va">self</span>._size:</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>            <span class="va">self</span>._buffer.append(item)</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">else</span>:</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>            <span class="va">self</span>._buffer[<span class="va">self</span>._index] <span class="op">=</span> item</span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>        <span class="va">self</span>._index <span class="op">=</span> (<span class="va">self</span>._index <span class="op">+</span> <span class="dv">1</span>) <span class="op">%</span> <span class="va">self</span>._size</span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">def</span> <span class="fu">__len__</span>(<span class="va">self</span>):</span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="bu">len</span>(<span class="va">self</span>._buffer)</span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">def</span> <span class="fu">__iter__</span>(<span class="va">self</span>):</span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>        <span class="cf">for</span> item <span class="kw">in</span> <span class="va">self</span>._buffer:</span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>            <span class="cf">yield</span> item</span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>            </span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">def</span> <span class="fu">__getitem__</span>(<span class="va">self</span>, key):</span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="va">self</span>._buffer[key]</span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">def</span> <span class="fu">__repr__</span>(<span class="va">self</span>):</span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="ss">f&quot;CircularBuffer (buffer=</span><span class="sc">{</span><span class="va">self</span><span class="sc">.</span>_buffer<span class="sc">}</span><span class="ss">, size=</span><span class="sc">{</span><span class="va">self</span><span class="sc">.</span>_size<span class="sc">}</span><span class="ss">, index=</span><span class="sc">{</span><span class="va">self</span><span class="sc">.</span>_index<span class="sc">}</span><span class="ss">)&quot;</span> </span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a>        </span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a>c <span class="op">=</span> CircularBuffer(size<span class="op">=</span><span class="dv">2</span>)</span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a><span class="bu">print</span>(c)</span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a>c.add(<span class="dv">0</span>)</span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a><span class="bu">print</span>(c)</span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a>c.add(<span class="dv">1</span>)</span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a><span class="bu">print</span>(c)</span>
<span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a>c.add(<span class="dv">2</span>)</span>
<span id="cb1-37"><a href="#cb1-37" aria-hidden="true" tabindex="-1"></a><span class="bu">print</span>(c)</span>
<span id="cb1-38"><a href="#cb1-38" aria-hidden="true" tabindex="-1"></a>c.add(<span class="dv">3</span>)</span>
<span id="cb1-39"><a href="#cb1-39" aria-hidden="true" tabindex="-1"></a><span class="bu">print</span>(c)</span>
<span id="cb1-40"><a href="#cb1-40" aria-hidden="true" tabindex="-1"></a>c.add(<span class="dv">10</span>)</span>
<span id="cb1-41"><a href="#cb1-41" aria-hidden="true" tabindex="-1"></a><span class="bu">print</span>(c)</span>
<span id="cb1-42"><a href="#cb1-42" aria-hidden="true" tabindex="-1"></a>c.add(<span class="dv">50</span>)</span>
<span id="cb1-43"><a href="#cb1-43" aria-hidden="true" tabindex="-1"></a><span class="bu">print</span>(c)</span>
<span id="cb1-44"><a href="#cb1-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-45"><a href="#cb1-45" aria-hidden="true" tabindex="-1"></a><span class="bu">print</span>(c[<span class="dv">0</span>])</span>
<span id="cb1-46"><a href="#cb1-46" aria-hidden="true" tabindex="-1"></a><span class="bu">print</span>(c[<span class="dv">1</span>])</span>
<span id="cb1-47"><a href="#cb1-47" aria-hidden="true" tabindex="-1"></a><span class="bu">print</span>(<span class="bu">len</span>(c))</span>
<span id="cb1-48"><a href="#cb1-48" aria-hidden="true" tabindex="-1"></a><span class="bu">print</span>(<span class="bu">list</span>(c))</span></code></pre></div>
<pre><code>CircularBuffer (buffer=[], size=2, index=0)
CircularBuffer (buffer=[0], size=2, index=1)
CircularBuffer (buffer=[0, 1], size=2, index=0)
CircularBuffer (buffer=[2, 1], size=2, index=1)
CircularBuffer (buffer=[2, 3], size=2, index=0)
CircularBuffer (buffer=[10, 3], size=2, index=1)
CircularBuffer (buffer=[10, 50], size=2, index=0)
10
50
2
[10, 50]</code></pre>
<p>This is a mutable implementation. If you want an immutable implementation I can write that up as well, but it will take a bit more time.</p>
<p>The key is the modulo operator.</p>
<p>We track the "last inserted element" by always storing it to the right of the last element we stored, meaning if I last inserted something at index 0, the next thing i will insert at index 1.</p>
<p>If I reach the "end" of the list or array then I need to "circle" around back to the first element at index 0.</p>
<p>To keep track of this information we remember an integer representing the last index we inserted at, then each time we add something to the list we increment the integer to "move to the right" and to make it "loop around" we use the modulo operator.</p>
<p>"modulo" just means the remainder you would get when dividing two numbers. For example</p>
<p><code>15 % 4</code> is <code>3</code></p>
<p>This is because we can fit three <code>4</code>s into <code>15</code> (<code>4 * 3 = 12</code>), but we don't have enough to fit another four so we have a "remainder" of <code>3</code> (<code>15 - 12 = 3</code>)</p>
<p>When you repeatedly do <code>n = (n + 1) % some_limit</code> then the value of <code>n</code> will go up to <code>1</code> minus the limit before looping back around to zero.</p>
<p>Try these on paper to get a better idea of why</p>
<pre><code>0 % 3 = ?
1 % 3 = ?
2 % 3 = ?
3 % 3 = ?
4 % 3 = ?
5 % 3 = ?
6 % 3 = ?
7 % 3 = ?</code></pre>
<p>For your specific case of just 2 items the modulo stuff is kinda overkill (from a cognitive load standpoint) so just do whatever solves your problem the simplest.</p>
<p>But if you wanted an object that holds max n elements that works like you described (where old elements are replaced in place) this is probably the cleanest way to do that.</p>
<p>If the "where" in the list doesn't matter then maybe consider using a deque with a size cap</p>
<hr />
<h4 id="--index"><a href="/">&lt;- Index</a></h4>
<script src="https://utteranc.es/client.js"
        repo="bowbahdoe/mccue.dev-comments"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script><style>div.sourceCode { padding:10px; } code { font-size:85%; } code.sourceCode > span { -webkit-text-size-adjust: none; }
</body>
</html>
]]></content:encoded></item></channel></rss>