<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="3.9.5">Jekyll</generator><link href="https://yaacoub.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://yaacoub.github.io/" rel="alternate" type="text/html" hreflang="en" /><updated>2026-04-17T10:51:26+00:00</updated><id>https://yaacoub.github.io/feed.xml</id><title type="html">Yaacoub</title><entry><title type="html">Measuring Core Data and SwiftData</title><link href="https://yaacoub.github.io/articles/swift-tip/measuring-core-data-and-swiftdata/" rel="alternate" type="text/html" title="Measuring Core Data and SwiftData" /><published>2026-02-16T00:00:00+00:00</published><updated>2026-02-16T00:00:00+00:00</updated><id>https://yaacoub.github.io/articles/swift-tip/measuring-core-data-and-swiftdata</id><content type="html" xml:base="https://yaacoub.github.io/articles/swift-tip/measuring-core-data-and-swiftdata/"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>I originally set out with a simple challenge: build the same SwiftUI app four times, each using a different persistence method: Core Data, SwiftData, UserDefaults, and JSON files. The plan quickly shifted. As I dug deeper, the question stopped being which tool is best, because deep down, I knew that the answer was simpler than how I was trying to make it seem.</p>

<p>Instead, I became more interested in sharing what I actually found along the way: poll results, measurements, and a clearer understanding of both Core Data and SwiftData.</p>

<p>But first, let’s rewind.</p>

<h2 id="what-is-data-persistence">What is data persistence?</h2>

<p>When you create an app, you typically want to preserve information from one launch to the next. In general, this capability is not implicit because storage and efficiency are sacred, so your runtime environment is always stored in volatile memory. Therefore, you actually need a way to tell the machine to store the data in mass storage. That’s data persistence:</p>

<blockquote>
  <p>The capability of an application to save data so that it can be retrieved [in its latest version] and used later, even after the application has closed or the system has been restarted [<a href="https://www.mongodb.com/resources/basics/databases/data-persistence">1</a>].</p>
</blockquote>

<p>In this broader sense, there are multiple ways to achieve this goal in Swift, but these methods don’t solve the same problem or operate at the same abstraction level.</p>

<h2 id="industry-standards">Industry Standards</h2>

<p>In my personal projects, I exclusively use UserDefaults and SwiftData, two Apple-native technologies that feel safe, modern, and well integrated. Core Data always seemed intimidating, and rolling my own file storage felt niche. The basis of my thinking remains: if Apple provides frameworks, why not use them?</p>

<p>I assumed most developers shared this mindset, but I wasn’t sure. To test that assumption, I conducted a quick 24-hour poll in two Swift-focused Slack communities, gathering roughly 35 responses in each.</p>

<p><img src="/-assets/images/articles/swift-tip/measuring-core-data-and-swiftdata/poll-results.webp" alt="Poll results" /></p>

<p>The results were more nuanced than expected. No single method dominated. UserDefaults led with just over a third of responses, while non-native solutions in the “Other” category (SQLite, SQLiteData, GRDB, FMDB, etc.) followed closely with nearly a quarter.</p>

<p>So why focus this article primarily on Core Data and SwiftData?</p>

<p>Partly curiosity. Partly relevance. And partly because persistence is not about popularity, it’s about trade-offs. UserDefaults shines for simple key-value storage but quickly reaches its limits. Third-party tools offer power and flexibility that Apple’s native frameworks can often match, but at the cost of added dependencies and maintenance. That, however, is a broader debate.</p>

<h2 id="experiment-setup">Experiment Setup</h2>

<p>This experiment builds on the MVVM task app from my article <a href="https://yaacoub.github.io/articles/swift-tip/one-swiftui-app-six-architectures/">One SwiftUI App, Six Architectures</a>. The app focuses on the four core principles of data persistence: Create, Read, Update, and Delete (CRUD). Using the same functionality across implementations ensures consistency and makes differences in structure, complexity, and performance easier to observe.</p>

<p>To fairly compare both methods, the View layer always remains unchanged, and I avoid framework-specific functionality that would disrupt my architecture. The goal is to see how each tool adapts to the app, not the other way around.</p>

<p>The full source code is available below this article.</p>

<h2 id="performance-curiosity">Performance Curiosity</h2>

<p>Beyond architecture, I was also curious about real-world performance, or, actually, simulator-world performance. For both frameworks, I measure the duration it takes to launch the app by inserting and then reading 0, 1, 1,000, or an extreme 1,000,000 entities on an iPhone 17 Pro simulator running iOS 26.2 on an M1 MacBook Air.</p>

<p>Using Xcode’s debug navigator, I observed:</p>
<ul>
  <li>CPU usage</li>
  <li>Memory consumption</li>
  <li>Disk activity</li>
  <li>Estimated launch time</li>
</ul>

<p>I considered comparing lines of code, but code style varies too much for that metric to be of meaningful relevance.</p>

<h2 id="core-data">Core Data</h2>

<p>Core Data is Apple’s first full-featured data persistence framework for its operating systems. Originally built for Objective-C and later ported to Swift, it has always divided opinions. Some developers say they “had very bad experiences with Core Data,” while others praise it enthusiastically: “Core Data is so good […] it’s so often misunderstood.”</p>

<p>Technically, Core Data is backed by SQLite, “the most used database engine in the world” [<a href="https://sqlite.org">2</a>], but it is not merely a relational database wrapper. As Krys Jurgowski explains in a Stack Overflow response:</p>

<blockquote>
  <blockquote>
    <p>Core Data does some serious optimizations under the hood that make accessing data much easier without having to dive deep into SQL [<a href="https://stackoverflow.com/a/26600398/8811661">3</a>].</p>
  </blockquote>
</blockquote>

<p>Although Core Data can also handle undo/redo, background tasks, synchronization, versioning, and migration [<a href="https://developer.apple.com/documentation/coredata">4</a>], persistence is the focus of this article, in its most basic and naïve implementation.</p>

<h3 id="code">Code</h3>

<p>Tasks.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">CoreData</span>
<span class="kd">import</span> <span class="kt">Foundation</span>

<span class="kd">@objc</span><span class="p">(</span><span class="kt">Task</span><span class="p">)</span>
<span class="kd">final</span> <span class="kd">class</span> <span class="kt">Task</span><span class="p">:</span> <span class="kt">NSManagedObject</span><span class="p">,</span> <span class="kt">Identifiable</span> <span class="p">{</span>
    <span class="kd">@NSManaged</span> <span class="k">var</span> <span class="nv">id</span><span class="p">:</span> <span class="kt">UUID</span>
    <span class="kd">@NSManaged</span> <span class="k">var</span> <span class="nv">title</span><span class="p">:</span> <span class="kt">String</span>
    <span class="kd">@NSManaged</span> <span class="k">var</span> <span class="nv">isDone</span><span class="p">:</span> <span class="kt">Bool</span>
    <span class="kd">@NSManaged</span> <span class="k">var</span> <span class="nv">creationDate</span><span class="p">:</span> <span class="kt">Date</span>

    <span class="k">override</span> <span class="kd">func</span> <span class="nf">awakeFromInsert</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">super</span><span class="o">.</span><span class="nf">awakeFromInsert</span><span class="p">()</span>
        <span class="k">self</span><span class="o">.</span><span class="n">id</span> <span class="o">=</span> <span class="kt">UUID</span><span class="p">()</span>
        <span class="k">self</span><span class="o">.</span><span class="n">isDone</span> <span class="o">=</span> <span class="kc">false</span>
        <span class="k">self</span><span class="o">.</span><span class="n">creationDate</span> <span class="o">=</span> <span class="kt">Date</span><span class="p">()</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>TaskModel.xcdatamodel:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;</span>
<span class="nt">&lt;model</span> <span class="na">type=</span><span class="s">"com.apple.IDECoreDataModeler.DataModel"</span> <span class="na">documentVersion=</span><span class="s">"1.0"</span> <span class="na">lastSavedToolsVersion=</span><span class="s">"24512"</span> <span class="na">systemVersion=</span><span class="s">"25C56"</span> <span class="na">minimumToolsVersion=</span><span class="s">"Automatic"</span> <span class="na">sourceLanguage=</span><span class="s">"Swift"</span> <span class="na">userDefinedModelVersionIdentifier=</span><span class="s">""</span><span class="nt">&gt;</span>
    <span class="nt">&lt;entity</span> <span class="na">name=</span><span class="s">"Task"</span> <span class="na">representedClassName=</span><span class="s">"Task"</span> <span class="na">syncable=</span><span class="s">"YES"</span><span class="nt">&gt;</span>
        <span class="nt">&lt;attribute</span> <span class="na">name=</span><span class="s">"creationDate"</span> <span class="na">attributeType=</span><span class="s">"Date"</span> <span class="na">usesScalarValueType=</span><span class="s">"NO"</span><span class="nt">/&gt;</span>
        <span class="nt">&lt;attribute</span> <span class="na">name=</span><span class="s">"id"</span> <span class="na">attributeType=</span><span class="s">"UUID"</span> <span class="na">usesScalarValueType=</span><span class="s">"NO"</span><span class="nt">/&gt;</span>
        <span class="nt">&lt;attribute</span> <span class="na">name=</span><span class="s">"isDone"</span> <span class="na">attributeType=</span><span class="s">"Boolean"</span> <span class="na">defaultValueString=</span><span class="s">"NO"</span> <span class="na">usesScalarValueType=</span><span class="s">"YES"</span><span class="nt">/&gt;</span>
        <span class="nt">&lt;attribute</span> <span class="na">name=</span><span class="s">"title"</span> <span class="na">attributeType=</span><span class="s">"String"</span> <span class="na">defaultValueString=</span><span class="s">"Untitled"</span><span class="nt">/&gt;</span>
    <span class="nt">&lt;/entity&gt;</span>
<span class="nt">&lt;/model&gt;</span>
</code></pre></div></div>

<p>TaskListViewModel.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">Combine</span>
<span class="kd">import</span> <span class="kt">CoreData</span>
<span class="kd">import</span> <span class="kt">Foundation</span>

<span class="kd">@MainActor</span>
<span class="kd">final</span> <span class="kd">class</span> <span class="kt">TaskListViewModel</span><span class="p">:</span> <span class="kt">ObservableObject</span> <span class="p">{</span>
    <span class="kd">private</span> <span class="k">let</span> <span class="nv">context</span><span class="p">:</span> <span class="kt">NSManagedObjectContext</span>
    
    <span class="kd">@Published</span> <span class="kd">private(set)</span> <span class="k">var</span> <span class="nv">tasks</span><span class="p">:</span> <span class="p">[</span><span class="kt">Task</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="kd">@Published</span> <span class="k">var</span> <span class="nv">taskTitle</span><span class="p">:</span> <span class="kt">String</span> <span class="o">=</span> <span class="s">""</span>
    
    <span class="nf">init</span><span class="p">(</span><span class="nv">context</span><span class="p">:</span> <span class="kt">NSManagedObjectContext</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">self</span><span class="o">.</span><span class="n">context</span> <span class="o">=</span> <span class="n">context</span>
        <span class="nf">fetchTasks</span><span class="p">()</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">addTask</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">guard</span> <span class="o">!</span><span class="n">taskTitle</span><span class="o">.</span><span class="nf">trimmingCharacters</span><span class="p">(</span><span class="nv">in</span><span class="p">:</span> <span class="o">.</span><span class="n">whitespacesAndNewlines</span><span class="p">)</span><span class="o">.</span><span class="n">isEmpty</span> <span class="k">else</span> <span class="p">{</span> <span class="k">return</span> <span class="p">}</span>
        <span class="k">let</span> <span class="nv">task</span> <span class="o">=</span> <span class="kt">Task</span><span class="p">(</span><span class="nv">context</span><span class="p">:</span> <span class="n">context</span><span class="p">)</span>
        <span class="n">task</span><span class="o">.</span><span class="n">title</span> <span class="o">=</span> <span class="n">taskTitle</span>
        <span class="n">taskTitle</span> <span class="o">=</span> <span class="s">""</span>
        <span class="nf">saveTasks</span><span class="p">()</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">deleteTask</span><span class="p">(</span><span class="n">_</span> <span class="nv">indexSet</span><span class="p">:</span> <span class="kt">IndexSet</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">for</span> <span class="n">index</span> <span class="k">in</span> <span class="n">indexSet</span> <span class="p">{</span>
            <span class="n">context</span><span class="o">.</span><span class="nf">delete</span><span class="p">(</span><span class="n">tasks</span><span class="p">[</span><span class="n">index</span><span class="p">])</span>
        <span class="p">}</span>
        <span class="nf">saveTasks</span><span class="p">()</span>
    <span class="p">}</span>

    <span class="kd">func</span> <span class="nf">fetchTasks</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">let</span> <span class="nv">request</span> <span class="o">=</span> <span class="kt">NSFetchRequest</span><span class="o">&lt;</span><span class="kt">Task</span><span class="o">&gt;</span><span class="p">(</span><span class="nv">entityName</span><span class="p">:</span> <span class="s">"Task"</span><span class="p">)</span>
        <span class="n">request</span><span class="o">.</span><span class="n">sortDescriptors</span> <span class="o">=</span> <span class="p">[</span><span class="kt">NSSortDescriptor</span><span class="p">(</span><span class="nv">keyPath</span><span class="p">:</span> <span class="p">\</span><span class="kt">Task</span><span class="o">.</span><span class="n">creationDate</span><span class="p">,</span> <span class="nv">ascending</span><span class="p">:</span> <span class="kc">true</span><span class="p">)]</span>
        <span class="k">do</span> <span class="p">{</span>
            <span class="n">tasks</span> <span class="o">=</span> <span class="k">try</span> <span class="n">context</span><span class="o">.</span><span class="nf">fetch</span><span class="p">(</span><span class="n">request</span><span class="p">)</span>
        <span class="p">}</span> <span class="k">catch</span> <span class="k">let</span> <span class="nv">error</span> <span class="p">{</span>
            <span class="nf">fatalError</span><span class="p">(</span><span class="s">"Error fetching tasks: </span><span class="se">\(</span><span class="n">error</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
        <span class="p">}</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">saveTasks</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">do</span> <span class="p">{</span>
            <span class="k">try</span> <span class="n">context</span><span class="o">.</span><span class="nf">save</span><span class="p">()</span>
            <span class="nf">fetchTasks</span><span class="p">()</span>
        <span class="p">}</span> <span class="k">catch</span> <span class="k">let</span> <span class="nv">error</span> <span class="p">{</span>
            <span class="nf">fatalError</span><span class="p">(</span><span class="s">"Error saving tasks: </span><span class="se">\(</span><span class="n">error</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
        <span class="p">}</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">toggleTask</span><span class="p">(</span><span class="n">_</span> <span class="nv">id</span><span class="p">:</span> <span class="kt">UUID</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">guard</span> <span class="k">let</span> <span class="nv">index</span> <span class="o">=</span> <span class="n">tasks</span><span class="o">.</span><span class="nf">firstIndex</span><span class="p">(</span><span class="nv">where</span><span class="p">:</span> <span class="p">{</span> <span class="nv">$0</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">id</span> <span class="p">})</span> <span class="k">else</span> <span class="p">{</span> <span class="k">return</span> <span class="p">}</span>
        <span class="n">tasks</span><span class="p">[</span><span class="n">index</span><span class="p">]</span><span class="o">.</span><span class="n">isDone</span><span class="o">.</span><span class="nf">toggle</span><span class="p">()</span>
        <span class="nf">saveTasks</span><span class="p">()</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Persistence.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">CoreData</span>

<span class="kd">struct</span> <span class="kt">PersistenceController</span> <span class="p">{</span>
    <span class="kd">static</span> <span class="k">let</span> <span class="nv">shared</span> <span class="o">=</span> <span class="kt">PersistenceController</span><span class="p">()</span>

    <span class="kd">@MainActor</span>
    <span class="kd">static</span> <span class="k">let</span> <span class="nv">preview</span><span class="p">:</span> <span class="kt">PersistenceController</span> <span class="o">=</span> <span class="p">{</span>
        <span class="k">let</span> <span class="nv">result</span> <span class="o">=</span> <span class="kt">PersistenceController</span><span class="p">(</span><span class="nv">inMemory</span><span class="p">:</span> <span class="kc">true</span><span class="p">)</span>
        <span class="k">let</span> <span class="nv">viewContext</span> <span class="o">=</span> <span class="n">result</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">viewContext</span>
        <span class="k">let</span> <span class="nv">testingSample</span> <span class="o">=</span> <span class="mi">1</span>
        <span class="k">for</span> <span class="n">i</span> <span class="k">in</span> <span class="mi">0</span><span class="o">..&lt;</span><span class="n">testingSample</span> <span class="p">{</span>
            <span class="k">let</span> <span class="nv">newItem</span> <span class="o">=</span> <span class="kt">Task</span><span class="p">(</span><span class="nv">context</span><span class="p">:</span> <span class="n">viewContext</span><span class="p">)</span>
            <span class="n">newItem</span><span class="o">.</span><span class="n">title</span> <span class="o">=</span> <span class="s">"Sample Task </span><span class="se">\(</span><span class="n">i</span><span class="se">)</span><span class="s">"</span>
        <span class="p">}</span>
        <span class="k">do</span> <span class="p">{</span>
            <span class="k">try</span> <span class="n">viewContext</span><span class="o">.</span><span class="nf">save</span><span class="p">()</span>
        <span class="p">}</span> <span class="k">catch</span> <span class="p">{</span>
            <span class="k">let</span> <span class="nv">nsError</span> <span class="o">=</span> <span class="n">error</span> <span class="k">as</span> <span class="kt">NSError</span>
            <span class="nf">fatalError</span><span class="p">(</span><span class="s">"Unresolved error </span><span class="se">\(</span><span class="n">nsError</span><span class="se">)</span><span class="s">, </span><span class="se">\(</span><span class="n">nsError</span><span class="o">.</span><span class="n">userInfo</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">result</span>
    <span class="p">}()</span>

    <span class="k">let</span> <span class="nv">container</span><span class="p">:</span> <span class="kt">NSPersistentContainer</span>

    <span class="nf">init</span><span class="p">(</span><span class="nv">inMemory</span><span class="p">:</span> <span class="kt">Bool</span> <span class="o">=</span> <span class="kc">false</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">container</span> <span class="o">=</span> <span class="kt">NSPersistentContainer</span><span class="p">(</span><span class="nv">name</span><span class="p">:</span> <span class="s">"TaskModel"</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">inMemory</span> <span class="p">{</span>
            <span class="n">container</span><span class="o">.</span><span class="n">persistentStoreDescriptions</span><span class="o">.</span><span class="n">first</span><span class="o">!.</span><span class="n">url</span> <span class="o">=</span> <span class="kt">URL</span><span class="p">(</span><span class="nv">fileURLWithPath</span><span class="p">:</span> <span class="s">"/dev/null"</span><span class="p">)</span>
        <span class="p">}</span>
        <span class="n">container</span><span class="o">.</span><span class="nf">loadPersistentStores</span><span class="p">(</span><span class="nv">completionHandler</span><span class="p">:</span> <span class="p">{</span> <span class="p">(</span><span class="n">storeDescription</span><span class="p">,</span> <span class="n">error</span><span class="p">)</span> <span class="k">in</span>
            <span class="k">if</span> <span class="k">let</span> <span class="nv">error</span> <span class="o">=</span> <span class="n">error</span> <span class="k">as</span> <span class="kt">NSError</span><span class="p">?</span> <span class="p">{</span>
                <span class="nf">fatalError</span><span class="p">(</span><span class="s">"Unresolved error </span><span class="se">\(</span><span class="n">error</span><span class="se">)</span><span class="s">, </span><span class="se">\(</span><span class="n">error</span><span class="o">.</span><span class="n">userInfo</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
            <span class="p">}</span>
        <span class="p">})</span>
        <span class="n">container</span><span class="o">.</span><span class="n">viewContext</span><span class="o">.</span><span class="n">automaticallyMergesChangesFromParent</span> <span class="o">=</span> <span class="kc">true</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="measurements">Measurements</h3>

<table>
  <thead>
    <tr>
      <th> </th>
      <th><strong>0</strong></th>
      <th><strong>1</strong></th>
      <th><strong>1000</strong></th>
      <th><strong>1000000</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>CPU (max)</td>
      <td>0.89</td>
      <td>0.64</td>
      <td>0.57</td>
      <td>2.04</td>
    </tr>
    <tr>
      <td>Memory (max) (MB)</td>
      <td>42.6</td>
      <td>43.1</td>
      <td>46.2</td>
      <td>740.9</td>
    </tr>
    <tr>
      <td>Memory (stable) (MB)</td>
      <td>42.3</td>
      <td>42.8</td>
      <td>46.0</td>
      <td>488.7</td>
    </tr>
    <tr>
      <td>Disk (max) (MB/s)</td>
      <td>96.4</td>
      <td>87.7</td>
      <td>72.9</td>
      <td>118.8</td>
    </tr>
    <tr>
      <td>Launch time (s)</td>
      <td>2</td>
      <td>2</td>
      <td>2</td>
      <td>14</td>
    </tr>
  </tbody>
</table>

<p><img src="/-assets/images/articles/swift-tip/measuring-core-data-and-swiftdata/core-data-measurements.webp" alt="Core Data Measurements" /></p>

<h3 id="analysis">Analysis</h3>

<p>As we multiply the number of entries by 1,000 each time, we can see that from 1 to 1,000, the measurements remain roughly similar. The jump to 1,000,000 is where things become interesting:</p>
<ul>
  <li>CPU usage almost triples</li>
  <li>Maximum memory consumption increases by ~15×</li>
  <li>Stable memory consumption increases by ~10×</li>
  <li>Disk activity increases by ~2.5×</li>
  <li>Estimated launch time increases by ~6×</li>
</ul>

<p>These numbers may look alarming in absolute terms, but they are far from the 1,000× multiplier applied to the number of entities. Code choices also influence these results: SwiftUI rendering, eager fetching, and storing entities in the view model all contribute to overhead.</p>

<p>Core Data appears to scale <strong>sub-linearly</strong> in several dimensions. Even with naïve SwiftUI integration, it handles large datasets with relatively controlled growth in resource usage. The trade-off lies more in complexity and developer ergonomics than raw performance.</p>

<h2 id="swiftdata">SwiftData</h2>

<p>In Apple’s own words, SwiftData is a combination of:</p>

<blockquote>
  <p>Core Data’s proven persistence technology and Swift’s modern concurrency features [<a href="https://developer.apple.com/documentation/swiftdata">5</a>].</p>
</blockquote>

<p>In other terms, it represents Apple’s attempt to make persistence feel like a natural extension of SwiftUI rather than a separate, heavyweight system. Some evolved concepts include:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">@Model</code> instead of managed object subclasses</li>
  <li>Schema inferred from types rather than <code class="language-plaintext highlighter-rouge">.xcdatamodeld</code> files</li>
  <li><code class="language-plaintext highlighter-rouge">ModelContext</code> instead of <code class="language-plaintext highlighter-rouge">NSManagedObjectContext</code></li>
</ul>

<p>Despite these changes, developers remain mixed. Some view SwiftData as a welcome simplification. Others criticize it as a “black box” that hides important behavior and limits flexibility. Another common observation is that SwiftData feels most at home inside SwiftUI views, whereas layered architectures expose its rough edges.</p>

<h3 id="code-1">Code</h3>

<p>Tasks.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">Foundation</span>
<span class="kd">import</span> <span class="kt">SwiftData</span>

<span class="kd">@Model</span>
<span class="kd">final</span> <span class="kd">class</span> <span class="kt">Task</span><span class="p">:</span> <span class="kt">Identifiable</span> <span class="p">{</span>
    <span class="k">var</span> <span class="nv">id</span><span class="p">:</span> <span class="kt">UUID</span> <span class="o">=</span> <span class="kt">UUID</span><span class="p">()</span>
    <span class="k">var</span> <span class="nv">title</span><span class="p">:</span> <span class="kt">String</span>
    <span class="k">var</span> <span class="nv">isDone</span><span class="p">:</span> <span class="kt">Bool</span> <span class="o">=</span> <span class="kc">false</span>
    <span class="k">var</span> <span class="nv">creationDate</span><span class="p">:</span> <span class="kt">Date</span> <span class="o">=</span> <span class="kt">Date</span><span class="p">()</span>
    
    <span class="nf">init</span><span class="p">(</span><span class="nv">title</span><span class="p">:</span> <span class="kt">String</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">self</span><span class="o">.</span><span class="n">title</span> <span class="o">=</span> <span class="n">title</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>TaskListViewModel.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">Combine</span>
<span class="kd">import</span> <span class="kt">Foundation</span>
<span class="kd">import</span> <span class="kt">SwiftData</span>

<span class="kd">@MainActor</span>
<span class="kd">final</span> <span class="kd">class</span> <span class="kt">TaskListViewModel</span><span class="p">:</span> <span class="kt">ObservableObject</span> <span class="p">{</span>
    <span class="kd">private</span> <span class="k">let</span> <span class="nv">context</span><span class="p">:</span> <span class="kt">ModelContext</span>
    
    <span class="kd">@Published</span> <span class="kd">private(set)</span> <span class="k">var</span> <span class="nv">tasks</span><span class="p">:</span> <span class="p">[</span><span class="kt">Task</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="kd">@Published</span> <span class="k">var</span> <span class="nv">taskTitle</span><span class="p">:</span> <span class="kt">String</span> <span class="o">=</span> <span class="s">""</span>
    
    <span class="nf">init</span><span class="p">(</span><span class="nv">context</span><span class="p">:</span> <span class="kt">ModelContext</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">self</span><span class="o">.</span><span class="n">context</span> <span class="o">=</span> <span class="n">context</span>
        <span class="nf">fetchTasks</span><span class="p">()</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">addTask</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">guard</span> <span class="o">!</span><span class="n">taskTitle</span><span class="o">.</span><span class="nf">trimmingCharacters</span><span class="p">(</span><span class="nv">in</span><span class="p">:</span> <span class="o">.</span><span class="n">whitespacesAndNewlines</span><span class="p">)</span><span class="o">.</span><span class="n">isEmpty</span> <span class="k">else</span> <span class="p">{</span> <span class="k">return</span> <span class="p">}</span>
        <span class="k">let</span> <span class="nv">task</span> <span class="o">=</span> <span class="kt">Task</span><span class="p">(</span><span class="nv">title</span><span class="p">:</span> <span class="n">taskTitle</span><span class="p">)</span>
        <span class="n">context</span><span class="o">.</span><span class="nf">insert</span><span class="p">(</span><span class="n">task</span><span class="p">)</span>
        <span class="n">taskTitle</span> <span class="o">=</span> <span class="s">""</span>
        <span class="nf">saveTasks</span><span class="p">()</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">deleteTask</span><span class="p">(</span><span class="n">_</span> <span class="nv">indexSet</span><span class="p">:</span> <span class="kt">IndexSet</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">for</span> <span class="n">index</span> <span class="k">in</span> <span class="n">indexSet</span> <span class="p">{</span>
            <span class="n">context</span><span class="o">.</span><span class="nf">delete</span><span class="p">(</span><span class="n">tasks</span><span class="p">[</span><span class="n">index</span><span class="p">])</span>
        <span class="p">}</span>
        <span class="nf">saveTasks</span><span class="p">()</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">fetchTasks</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">let</span> <span class="nv">request</span> <span class="o">=</span> <span class="kt">FetchDescriptor</span><span class="o">&lt;</span><span class="kt">Task</span><span class="o">&gt;</span><span class="p">(</span><span class="nv">predicate</span><span class="p">:</span> <span class="kc">nil</span><span class="p">,</span> <span class="nv">sortBy</span><span class="p">:</span> <span class="p">[</span><span class="kt">SortDescriptor</span><span class="p">(\</span><span class="o">.</span><span class="n">creationDate</span><span class="p">)])</span>
        <span class="k">do</span> <span class="p">{</span>
            <span class="n">tasks</span> <span class="o">=</span> <span class="k">try</span> <span class="n">context</span><span class="o">.</span><span class="nf">fetch</span><span class="p">(</span><span class="n">request</span><span class="p">)</span>
        <span class="p">}</span> <span class="k">catch</span> <span class="k">let</span> <span class="nv">error</span> <span class="p">{</span>
            <span class="nf">fatalError</span><span class="p">(</span><span class="s">"Error fetching tasks: </span><span class="se">\(</span><span class="n">error</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
        <span class="p">}</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">saveTasks</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">do</span> <span class="p">{</span>
            <span class="k">try</span> <span class="n">context</span><span class="o">.</span><span class="nf">save</span><span class="p">()</span>
            <span class="nf">fetchTasks</span><span class="p">()</span>
        <span class="p">}</span> <span class="k">catch</span> <span class="k">let</span> <span class="nv">error</span> <span class="p">{</span>
            <span class="nf">fatalError</span><span class="p">(</span><span class="s">"Error saving tasks: </span><span class="se">\(</span><span class="n">error</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
        <span class="p">}</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">toggleTask</span><span class="p">(</span><span class="n">_</span> <span class="nv">id</span><span class="p">:</span> <span class="kt">UUID</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">guard</span> <span class="k">let</span> <span class="nv">index</span> <span class="o">=</span> <span class="n">tasks</span><span class="o">.</span><span class="nf">firstIndex</span><span class="p">(</span><span class="nv">where</span><span class="p">:</span> <span class="p">{</span> <span class="nv">$0</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">id</span> <span class="p">})</span> <span class="k">else</span> <span class="p">{</span> <span class="k">return</span> <span class="p">}</span>
        <span class="n">tasks</span><span class="p">[</span><span class="n">index</span><span class="p">]</span><span class="o">.</span><span class="n">isDone</span><span class="o">.</span><span class="nf">toggle</span><span class="p">()</span>
        <span class="nf">saveTasks</span><span class="p">()</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Persistence.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">SwiftData</span>

<span class="kd">struct</span> <span class="kt">PersistenceController</span> <span class="p">{</span>
    <span class="kd">static</span> <span class="k">let</span> <span class="nv">shared</span> <span class="o">=</span> <span class="kt">PersistenceController</span><span class="p">()</span>

    <span class="kd">@MainActor</span>
    <span class="kd">static</span> <span class="k">let</span> <span class="nv">preview</span><span class="p">:</span> <span class="kt">PersistenceController</span> <span class="o">=</span> <span class="p">{</span>
        <span class="k">let</span> <span class="nv">result</span> <span class="o">=</span> <span class="kt">PersistenceController</span><span class="p">(</span><span class="nv">inMemory</span><span class="p">:</span> <span class="kc">true</span><span class="p">)</span>
        <span class="k">let</span> <span class="nv">context</span> <span class="o">=</span> <span class="n">result</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">mainContext</span>
        <span class="k">let</span> <span class="nv">testingSample</span> <span class="o">=</span> <span class="mi">1</span>
        <span class="k">for</span> <span class="n">i</span> <span class="k">in</span> <span class="mi">0</span><span class="o">..&lt;</span><span class="n">testingSample</span> <span class="p">{</span>
            <span class="k">let</span> <span class="nv">newItem</span> <span class="o">=</span> <span class="kt">Task</span><span class="p">(</span><span class="nv">title</span><span class="p">:</span> <span class="s">"Sample Task </span><span class="se">\(</span><span class="n">i</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
            <span class="n">context</span><span class="o">.</span><span class="nf">insert</span><span class="p">(</span><span class="n">newItem</span><span class="p">)</span>
        <span class="p">}</span>
        <span class="k">do</span> <span class="p">{</span>
            <span class="k">try</span> <span class="n">context</span><span class="o">.</span><span class="nf">save</span><span class="p">()</span>
        <span class="p">}</span> <span class="k">catch</span> <span class="p">{</span>
            <span class="nf">fatalError</span><span class="p">(</span><span class="s">"Unresolved error: </span><span class="se">\(</span><span class="n">error</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">result</span>
    <span class="p">}()</span>

    <span class="k">let</span> <span class="nv">container</span><span class="p">:</span> <span class="kt">ModelContainer</span>

    <span class="nf">init</span><span class="p">(</span><span class="nv">inMemory</span><span class="p">:</span> <span class="kt">Bool</span> <span class="o">=</span> <span class="kc">false</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">let</span> <span class="nv">schema</span> <span class="o">=</span> <span class="kt">Schema</span><span class="p">([</span><span class="kt">Task</span><span class="o">.</span><span class="k">self</span><span class="p">])</span>
        <span class="k">let</span> <span class="nv">configuration</span> <span class="o">=</span> <span class="kt">ModelConfiguration</span><span class="p">(</span><span class="nv">schema</span><span class="p">:</span> <span class="n">schema</span><span class="p">,</span> <span class="nv">isStoredInMemoryOnly</span><span class="p">:</span> <span class="n">inMemory</span><span class="p">)</span>
        <span class="k">do</span> <span class="p">{</span>
            <span class="n">container</span> <span class="o">=</span> <span class="k">try</span> <span class="kt">ModelContainer</span><span class="p">(</span><span class="nv">for</span><span class="p">:</span> <span class="n">schema</span><span class="p">,</span> <span class="nv">configurations</span><span class="p">:</span> <span class="p">[</span><span class="n">configuration</span><span class="p">])</span>
        <span class="p">}</span> <span class="k">catch</span> <span class="p">{</span>
            <span class="nf">fatalError</span><span class="p">(</span><span class="s">"Could not create ModelContainer: </span><span class="se">\(</span><span class="n">error</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="measurements-1">Measurements</h3>

<table>
  <thead>
    <tr>
      <th> </th>
      <th><strong>0</strong></th>
      <th><strong>1</strong></th>
      <th><strong>1000</strong></th>
      <th><strong>1000000</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>CPU (max)</td>
      <td>0.56</td>
      <td>0.49</td>
      <td>0.63</td>
      <td>1.95</td>
    </tr>
    <tr>
      <td>Memory (max) (MB)</td>
      <td>42.8</td>
      <td>43.2</td>
      <td>47.8</td>
      <td><strong>5100</strong></td>
    </tr>
    <tr>
      <td>Memory (stable) (MB)</td>
      <td>42.5</td>
      <td>43.0</td>
      <td>47.6</td>
      <td><strong>1240</strong></td>
    </tr>
    <tr>
      <td>Disk (max) (MB/s)</td>
      <td>78.2</td>
      <td>81.0</td>
      <td>92.5</td>
      <td>117.2</td>
    </tr>
    <tr>
      <td>Launch time (s)</td>
      <td>2</td>
      <td>2</td>
      <td>2</td>
      <td><strong>120</strong></td>
    </tr>
  </tbody>
</table>

<p><img src="/-assets/images/articles/swift-tip/measuring-core-data-and-swiftdata/swift-data-measurements.webp" alt="SwiftData Measurements" /></p>

<h3 id="analysis-1">Analysis</h3>

<p>For small datasets, SwiftData behaves very similarly to Core Data. CPU usage, memory consumption, disk activity, and estimated launch times remain nearly identical from 0 to 1,000 entities.</p>

<p>The divergence appears at 1,000,000 entities:</p>
<ul>
  <li>Maximum memory consumption increases dramatically by ~107×, or ~7× compared with Core Data</li>
  <li>Stable memory usage also significantly increases by ~26×, or ~2.5× compared with Core Data</li>
  <li>Estimated launch time jumps by 60×, or ~8.5× compared with Core Data</li>
</ul>

<p>In this setup, SwiftData appears to materialize more data in memory, possibly due to eager fetching, lack of batching, or current framework optimizations.</p>

<p>Perhaps with careful tuning, results could differ. Still, it seems that <strong>abstraction has a cost</strong>, especially at scale [<a href="https://forums.swift.org/t/creating-instances-of-swiftdata-models-very-slow/68680">6</a>].</p>

<h2 id="core-data-vs-swiftdata-what-actually-matters">Core Data vs. SwiftData. What actually matters?</h2>

<p>Well first, Apple writes <em>Core Data</em> with a space and <em>SwiftData</em> without.</p>

<p>Otherwise, from this experiment, some observations emerge:</p>

<p>SwiftData builds on Core Data, which in turn builds on SQLite. This can lead to more predictable performance characteristics in Core Data, particularly in large datasets and naïve implementations, while SwiftData prioritizes ergonomics and syntax. Indeed, for small to medium datasets, differences are negligible. At extreme scales, Core Data’s mature optimizations provide more appropriate behavior.</p>

<p>Considering architectural compatibility, both SwiftData and Core Data can adapt to diverse architectural patterns. In this case, the newer framework’s syntax looks increasingly similar to its predecessor.</p>

<p>Again, these results reflect a naïve, eager-loading implementation without batching, pagination, or advanced fetch optimizations. Different architectural choices or framework-idiomatic patterns may significantly alter performance characteristics.</p>

<h2 id="conclusion">Conclusion</h2>

<p>This article started as a comparison. It ended as a reminder: persistence is not about choosing the best tool, it’s about choosing the right trade-offs.</p>

<p>If I were starting a new SwiftUI app today:</p>
<ul>
  <li>I would choose <strong>SwiftData</strong> for small to medium apps, rapid prototyping, or projects deeply integrated with SwiftUI.</li>
  <li>I would choose <strong>Core Data</strong> for large datasets, long-lived projects, or architectures requiring fine-grained control.</li>
</ul>

<p>UserDefaults still has its place for trivial settings, and third-party databases remain compelling, notably for cross-platform needs or advanced querying.</p>

<p>Now you can disagree, because there’s no right, and honestly, that’s the point.</p>]]></content><author><name>Peter Yaacoub</name></author><category term="articles" /><category term="swift-tip" /><summary type="html"><![CDATA[Introduction]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://yaacoub.github.io/social.webp" /><media:content medium="image" url="https://yaacoub.github.io/social.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">1 App, 20 Programming Languages (Part 2)</title><link href="https://yaacoub.github.io/articles/code-dome/1-app-20-programming-languages-part-2/" rel="alternate" type="text/html" title="1 App, 20 Programming Languages (Part 2)" /><published>2026-01-05T00:00:00+00:00</published><updated>2026-01-05T00:00:00+00:00</updated><id>https://yaacoub.github.io/articles/code-dome/1-app-20-programming-languages-part-2</id><content type="html" xml:base="https://yaacoub.github.io/articles/code-dome/1-app-20-programming-languages-part-2/"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>If you haven’t read the first part of this challenge, go check it out! (<a href="https://yaacoub.github.io/articles/code-dome/1-app-20-programming-languages-part-1/">1 App, 20 Programming Languages (Part 1)</a>).</p>

<h2 id="go">Go</h2>

<p>Go, like Golang, and not to be confused with the Go game, is a relatively new programming language released in 2009. That’s the first programming language younger than me. It’s funny how the older languages have an oligopoly (a market dominated by a small number of actors), reminds me of real-world politics (oh, part 2 already punches hard!).</p>

<p>To focus back on the code, Go looks clean, like other modern languages, and the differentiation between a definition <code class="language-plaintext highlighter-rouge">:=</code>  and redefinition is interesting <code class="language-plaintext highlighter-rouge">=</code>. However, I found two major inconveniences. First, not unique to Go is the necessity to create other files. In this case, a mod file and an individual main file that would have the code common to both files. Second, Go is the only language in this challenge where I chose to abandon floating-point arithmetic for this implementation, because I couldn’t reliably match Test 7’s precision. So I had to come out with the big guns, and by that I mean the <code class="language-plaintext highlighter-rouge">math/big</code> library. Hence, coding took a little more time than I would’ve expected from that newer language.</p>

<p>calculator.go:</p>
<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">package</span> <span class="n">main</span>

<span class="c">// IMPORTS</span>
<span class="c">// =======</span>

<span class="k">import</span> <span class="p">(</span>
    <span class="s">"math/big"</span>
    <span class="s">"regexp"</span>
    <span class="s">"strconv"</span>
    <span class="s">"strings"</span>
<span class="p">)</span>

<span class="c">// FUNCTIONS</span>
<span class="c">// =========</span>

<span class="k">func</span> <span class="n">GetResult</span><span class="p">(</span><span class="n">calculation</span> <span class="kt">string</span><span class="p">)</span> <span class="kt">string</span> <span class="p">{</span>
    <span class="n">calculation</span> <span class="o">=</span> <span class="n">sanitizeCalculation</span><span class="p">(</span><span class="n">calculation</span><span class="p">)</span>
    <span class="n">result</span> <span class="o">:=</span> <span class="nb">new</span><span class="p">(</span><span class="n">big</span><span class="o">.</span><span class="n">Rat</span><span class="p">)</span>
    <span class="n">result</span><span class="o">.</span><span class="n">SetInt64</span><span class="p">(</span><span class="m">0</span><span class="p">)</span>

    <span class="k">for</span> <span class="n">_</span><span class="p">,</span> <span class="n">i</span> <span class="o">:=</span> <span class="k">range</span> <span class="n">strings</span><span class="o">.</span><span class="n">Split</span><span class="p">(</span><span class="n">calculation</span><span class="p">,</span> <span class="s">"+"</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">subResult</span> <span class="o">:=</span> <span class="n">big</span><span class="o">.</span><span class="n">NewRat</span><span class="p">(</span><span class="m">1</span><span class="p">,</span> <span class="m">1</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">_</span><span class="p">,</span> <span class="n">j</span> <span class="o">:=</span> <span class="k">range</span> <span class="n">strings</span><span class="o">.</span><span class="n">Split</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="s">"*"</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">if</span> <span class="n">strings</span><span class="o">.</span><span class="n">HasPrefix</span><span class="p">(</span><span class="n">j</span><span class="p">,</span> <span class="s">"1/"</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">sanitizedJ</span> <span class="o">:=</span> <span class="n">strings</span><span class="o">.</span><span class="n">TrimPrefix</span><span class="p">(</span><span class="n">j</span><span class="p">,</span> <span class="s">"1/"</span><span class="p">)</span>
				<span class="n">denom</span> <span class="o">:=</span> <span class="nb">new</span><span class="p">(</span><span class="n">big</span><span class="o">.</span><span class="n">Rat</span><span class="p">)</span>
				<span class="n">denom</span><span class="o">.</span><span class="n">SetString</span><span class="p">(</span><span class="n">sanitizedJ</span><span class="p">)</span>
                <span class="k">if</span> <span class="n">denom</span><span class="o">.</span><span class="n">Sign</span><span class="p">()</span> <span class="o">==</span> <span class="m">0</span> <span class="p">{</span> <span class="k">return</span> <span class="s">"Undefined"</span> <span class="p">}</span>
                <span class="n">subResult</span><span class="o">.</span><span class="n">Quo</span><span class="p">(</span><span class="n">subResult</span><span class="p">,</span> <span class="n">denom</span><span class="p">)</span>
            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
				<span class="n">factor</span> <span class="o">:=</span> <span class="nb">new</span><span class="p">(</span><span class="n">big</span><span class="o">.</span><span class="n">Rat</span><span class="p">)</span>
				<span class="n">factor</span><span class="o">.</span><span class="n">SetString</span><span class="p">(</span><span class="n">j</span><span class="p">)</span>
                <span class="n">subResult</span><span class="o">.</span><span class="n">Mul</span><span class="p">(</span><span class="n">subResult</span><span class="p">,</span> <span class="n">factor</span><span class="p">)</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="n">result</span><span class="o">.</span><span class="n">Add</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">subResult</span><span class="p">)</span>
    <span class="p">}</span>

    <span class="n">f</span><span class="p">,</span> <span class="n">_</span> <span class="o">:=</span> <span class="n">result</span><span class="o">.</span><span class="n">Float64</span><span class="p">()</span>
    <span class="k">return</span> <span class="n">strconv</span><span class="o">.</span><span class="n">FormatFloat</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="sc">'f'</span><span class="p">,</span> <span class="o">-</span><span class="m">1</span><span class="p">,</span> <span class="m">64</span><span class="p">)</span>
<span class="p">}</span>

<span class="k">func</span> <span class="n">sanitizeCalculation</span><span class="p">(</span><span class="n">calculation</span> <span class="kt">string</span><span class="p">)</span> <span class="kt">string</span> <span class="p">{</span>
    <span class="n">calc</span> <span class="o">:=</span> <span class="n">regexp</span><span class="o">.</span><span class="n">MustCompile</span><span class="p">(</span><span class="s">`\s+`</span><span class="p">)</span><span class="o">.</span><span class="n">ReplaceAllString</span><span class="p">(</span><span class="n">calculation</span><span class="p">,</span> <span class="s">""</span><span class="p">)</span>			<span class="c">// Remove all spaces</span>
    <span class="n">calc</span> <span class="o">=</span> <span class="n">regexp</span><span class="o">.</span><span class="n">MustCompile</span><span class="p">(</span><span class="s">`\++`</span><span class="p">)</span><span class="o">.</span><span class="n">ReplaceAllString</span><span class="p">(</span><span class="n">calc</span><span class="p">,</span> <span class="s">"+"</span><span class="p">)</span>				<span class="c">// ++ -&gt; +</span>
    <span class="n">calc</span> <span class="o">=</span> <span class="n">regexp</span><span class="o">.</span><span class="n">MustCompile</span><span class="p">(</span><span class="s">`-+`</span><span class="p">)</span><span class="o">.</span><span class="n">ReplaceAllString</span><span class="p">(</span><span class="n">calc</span><span class="p">,</span> <span class="s">"-"</span><span class="p">)</span>					<span class="c">// -- -&gt; -</span>
    <span class="n">calc</span> <span class="o">=</span> <span class="n">regexp</span><span class="o">.</span><span class="n">MustCompile</span><span class="p">(</span><span class="s">`\*\+`</span><span class="p">)</span><span class="o">.</span><span class="n">ReplaceAllString</span><span class="p">(</span><span class="n">calc</span><span class="p">,</span> <span class="s">"*"</span><span class="p">)</span>				<span class="c">// *+ -&gt; *</span>
    <span class="n">calc</span> <span class="o">=</span> <span class="n">regexp</span><span class="o">.</span><span class="n">MustCompile</span><span class="p">(</span><span class="s">`/\+`</span><span class="p">)</span><span class="o">.</span><span class="n">ReplaceAllString</span><span class="p">(</span><span class="n">calc</span><span class="p">,</span> <span class="s">"/"</span><span class="p">)</span>				<span class="c">// /+ -&gt; /</span>
    <span class="n">calc</span> <span class="o">=</span> <span class="n">regexp</span><span class="o">.</span><span class="n">MustCompile</span><span class="p">(</span><span class="s">`\+-`</span><span class="p">)</span><span class="o">.</span><span class="n">ReplaceAllString</span><span class="p">(</span><span class="n">calc</span><span class="p">,</span> <span class="s">"-"</span><span class="p">)</span>				<span class="c">// +- -&gt; -</span>
    <span class="n">calc</span> <span class="o">=</span> <span class="n">regexp</span><span class="o">.</span><span class="n">MustCompile</span><span class="p">(</span><span class="s">`(\d)-(\d)`</span><span class="p">)</span><span class="o">.</span><span class="n">ReplaceAllString</span><span class="p">(</span><span class="n">calc</span><span class="p">,</span> <span class="s">"$1+-$2"</span><span class="p">)</span>		<span class="c">// a-b -&gt; a+-b</span>
    <span class="n">calc</span> <span class="o">=</span> <span class="n">strings</span><span class="o">.</span><span class="n">ReplaceAll</span><span class="p">(</span><span class="n">calc</span><span class="p">,</span> <span class="s">"/"</span><span class="p">,</span> <span class="s">"*1/"</span><span class="p">)</span>									<span class="c">// a/b -&gt; a*1/b</span>
    <span class="k">return</span> <span class="n">calc</span>
<span class="p">}</span>
</code></pre></div></div>

<p>main.go:</p>
<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">//go:build !testmain</span>
<span class="c">// +build !testmain</span>

<span class="k">package</span> <span class="n">main</span>

<span class="c">// IMPORTS§</span>
<span class="c">// =======</span>

<span class="k">import</span> <span class="p">(</span>
    <span class="s">"bufio"</span>
    <span class="s">"fmt"</span>
    <span class="s">"os"</span>
    <span class="s">"strings"</span>
<span class="p">)</span>

<span class="c">// FUNCTIONS</span>
<span class="c">// =========</span>

<span class="k">func</span> <span class="n">askQuestion</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">reader</span> <span class="o">:=</span> <span class="n">bufio</span><span class="o">.</span><span class="n">NewReader</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">Stdin</span><span class="p">)</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Print</span><span class="p">(</span><span class="s">"Your calculation: "</span><span class="p">)</span>
    <span class="n">input</span><span class="p">,</span> <span class="n">_</span> <span class="o">:=</span> <span class="n">reader</span><span class="o">.</span><span class="n">ReadString</span><span class="p">(</span><span class="sc">'\n'</span><span class="p">)</span>
    <span class="n">input</span> <span class="o">=</span> <span class="n">strings</span><span class="o">.</span><span class="n">TrimSpace</span><span class="p">(</span><span class="n">input</span><span class="p">)</span>
    <span class="n">result</span> <span class="o">:=</span> <span class="n">GetResult</span><span class="p">(</span><span class="n">input</span><span class="p">)</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Printf</span><span class="p">(</span><span class="s">" = %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">result</span><span class="p">)</span>
<span class="p">}</span>

<span class="c">// MAIN</span>
<span class="c">// ====</span>

<span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">askQuestion</span><span class="p">()</span>
<span class="p">}</span>
</code></pre></div></div>

<p>tests.go:</p>
<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">//go:build testmain</span>
<span class="c">// +build testmain</span>

<span class="k">package</span> <span class="n">main</span>

<span class="c">// IMPORTS</span>
<span class="c">// =======</span>

<span class="k">import</span> <span class="p">(</span>
    <span class="s">"fmt"</span>
    <span class="s">"strconv"</span>
<span class="p">)</span>

<span class="c">// FUNCTIONS</span>
<span class="c">// =========</span>

<span class="k">func</span> <span class="n">runTests</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Printf</span><span class="p">(</span><span class="s">"Test 01: %v</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">GetResult</span><span class="p">(</span><span class="s">"2 + 3"</span><span class="p">)</span> <span class="o">==</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Sprint</span><span class="p">(</span><span class="m">2</span> <span class="o">+</span> <span class="m">3</span><span class="p">))</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Printf</span><span class="p">(</span><span class="s">"Test 02: %v</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">GetResult</span><span class="p">(</span><span class="s">"2 - 3"</span><span class="p">)</span> <span class="o">==</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Sprint</span><span class="p">(</span><span class="m">2</span> <span class="o">-</span> <span class="m">3</span><span class="p">))</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Printf</span><span class="p">(</span><span class="s">"Test 03: %v</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">GetResult</span><span class="p">(</span><span class="s">"2 * 3"</span><span class="p">)</span> <span class="o">==</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Sprint</span><span class="p">(</span><span class="m">2</span> <span class="o">*</span> <span class="m">3</span><span class="p">))</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Printf</span><span class="p">(</span><span class="s">"Test 04: %v</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">GetResult</span><span class="p">(</span><span class="s">"2 / 3"</span><span class="p">)</span> <span class="o">==</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Sprint</span><span class="p">(</span><span class="m">2.0</span> <span class="o">/</span> <span class="m">3.0</span><span class="p">))</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Printf</span><span class="p">(</span><span class="s">"Test 05: %v</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">GetResult</span><span class="p">(</span><span class="s">"2 / 0"</span><span class="p">)</span> <span class="o">==</span> <span class="s">"Undefined"</span><span class="p">)</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Printf</span><span class="p">(</span><span class="s">"Test 06: %v</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">GetResult</span><span class="p">(</span><span class="s">"  7 +   2 * 3 - 4 / -2 "</span><span class="p">)</span> <span class="o">==</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Sprint</span><span class="p">(</span>  <span class="m">7</span> <span class="o">+</span>   <span class="m">2</span> <span class="o">*</span> <span class="m">3</span> <span class="o">-</span> <span class="m">4</span> <span class="o">/</span> <span class="o">-</span><span class="m">2</span> <span class="p">))</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Printf</span><span class="p">(</span><span class="s">"Test 07: %v</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">GetResult</span><span class="p">(</span><span class="s">"  7 +   2 / 3 - 4 * +-2 "</span><span class="p">)</span> <span class="o">==</span> <span class="n">strconv</span><span class="o">.</span><span class="n">FormatFloat</span><span class="p">(</span>  <span class="m">7</span> <span class="o">+</span>   <span class="m">2.0</span> <span class="o">/</span> <span class="m">3</span> <span class="o">-</span> <span class="m">4</span> <span class="o">*</span> <span class="o">+-</span><span class="m">2</span> <span class="p">,</span> <span class="sc">'f'</span><span class="p">,</span> <span class="o">-</span><span class="m">1</span><span class="p">,</span> <span class="m">64</span><span class="p">))</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Printf</span><span class="p">(</span><span class="s">"Test 08: %v</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">GetResult</span><span class="p">(</span><span class="s">"2.0 + 3.0"</span><span class="p">)</span> <span class="o">==</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Sprint</span><span class="p">(</span><span class="m">2.0</span> <span class="o">+</span> <span class="m">3.0</span><span class="p">))</span>
<span class="p">}</span>

<span class="c">// MAIN</span>
<span class="c">// ====</span>

<span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="n">runTests</span><span class="p">()</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="rust">Rust</h2>

<p>I was wondering if Rust was much older than Go. Surprisingly, it’s even more recent! It first appeared in 2012, and I never would’ve thought. Then again, when doing the tests, it seemed intentionally strict about arithmetic between integer and floating-point types. Of course, this doesn’t mean anything on its own, but it tingled my spidey sense.</p>

<p>This time, I only had one new file to add, a Cargo.toml. Also, it was more conventional to use folders to separate the files, so I did so. Also-also, I used true tests this time instead of printing the results to the console, because why not? It was easy. One interesting discovery that relates to the mentioned arithmetic problem is the strict, and I mean very strict, difference between a string and a static string. In practice, this means that I should convert a string literal, which is static, to a string type in order to return it from a function that only returns string types and not static strings, which include string literals. Clear? In short, it seems to me that this is always the case: string ≠ static string.</p>

<p>Rust originated at Mozilla to address performance and memory-safety issues common in C and C++, and today it is used in parts of Firefox and many other systems projects.</p>

<p>calculator.rs:</p>
<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// IMPORTS</span>
<span class="c1">// =======</span>

<span class="k">use</span> <span class="nn">regex</span><span class="p">::</span><span class="n">Regex</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">io</span><span class="p">::{</span><span class="k">self</span><span class="p">,</span> <span class="n">Write</span><span class="p">};</span>

<span class="c1">// FUNCTIONS</span>
<span class="c1">// =========</span>

<span class="nd">#[allow(dead_code)]</span>
<span class="k">fn</span> <span class="nf">ask_question</span><span class="p">()</span> <span class="p">{</span>
    <span class="nd">print!</span><span class="p">(</span><span class="s">"Your calculation: "</span><span class="p">);</span>
    <span class="nn">io</span><span class="p">::</span><span class="nf">stdout</span><span class="p">()</span><span class="nf">.flush</span><span class="p">()</span><span class="nf">.ok</span><span class="p">();</span>
    <span class="k">let</span> <span class="k">mut</span> <span class="n">input</span> <span class="o">=</span> <span class="nn">String</span><span class="p">::</span><span class="nf">new</span><span class="p">();</span>
    <span class="k">if</span> <span class="nn">io</span><span class="p">::</span><span class="nf">stdin</span><span class="p">()</span><span class="nf">.read_line</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="n">input</span><span class="p">)</span><span class="nf">.is_ok</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">let</span> <span class="n">result</span> <span class="o">=</span> <span class="nf">get_result</span><span class="p">(</span><span class="o">&amp;</span><span class="n">input</span><span class="p">);</span>
        <span class="nd">println!</span><span class="p">(</span><span class="s">" = {}"</span><span class="p">,</span> <span class="n">result</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="k">pub</span> <span class="k">fn</span> <span class="nf">get_result</span><span class="p">(</span><span class="n">calculation</span><span class="p">:</span> <span class="o">&amp;</span><span class="nb">str</span><span class="p">)</span> <span class="k">-&gt;</span> <span class="nb">String</span> <span class="p">{</span>
    <span class="k">let</span> <span class="n">calculation</span> <span class="o">=</span> <span class="nf">sanitize_calculation</span><span class="p">(</span><span class="n">calculation</span><span class="p">);</span>
    <span class="k">let</span> <span class="k">mut</span> <span class="n">result</span> <span class="o">=</span> <span class="mf">0.0f64</span><span class="p">;</span>

    <span class="k">for</span> <span class="n">i</span> <span class="k">in</span> <span class="n">calculation</span><span class="nf">.split</span><span class="p">(</span><span class="sc">'+'</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">let</span> <span class="k">mut</span> <span class="n">sub_result</span> <span class="o">=</span> <span class="mf">1.0f64</span><span class="p">;</span>
        <span class="k">for</span> <span class="n">j</span> <span class="k">in</span> <span class="n">i</span><span class="nf">.split</span><span class="p">(</span><span class="sc">'*'</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">if</span> <span class="k">let</span> <span class="nf">Some</span><span class="p">(</span><span class="n">sanitized_j</span><span class="p">)</span> <span class="o">=</span> <span class="n">j</span><span class="nf">.strip_prefix</span><span class="p">(</span><span class="s">"1/"</span><span class="p">)</span> <span class="p">{</span>
                <span class="k">if</span> <span class="n">sanitized_j</span><span class="nf">.parse</span><span class="p">()</span><span class="nf">.unwrap_or</span><span class="p">(</span><span class="nn">f64</span><span class="p">::</span><span class="n">NAN</span><span class="p">)</span> <span class="o">==</span> <span class="mf">0.0</span> <span class="p">{</span> <span class="k">return</span> <span class="s">"Undefined"</span><span class="nf">.to_string</span><span class="p">();</span> <span class="p">}</span>
                <span class="n">sub_result</span> <span class="o">/=</span> <span class="n">sanitized_j</span><span class="nf">.parse</span><span class="p">()</span><span class="nf">.unwrap_or</span><span class="p">(</span><span class="nn">f64</span><span class="p">::</span><span class="n">NAN</span><span class="p">);</span>
            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                <span class="n">sub_result</span> <span class="o">*=</span> <span class="n">j</span><span class="nf">.parse</span><span class="p">()</span><span class="nf">.unwrap_or</span><span class="p">(</span><span class="nn">f64</span><span class="p">::</span><span class="n">NAN</span><span class="p">);</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="n">result</span> <span class="o">+=</span> <span class="n">sub_result</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="nd">format!</span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span> <span class="n">result</span><span class="p">)</span>
<span class="p">}</span>

<span class="k">fn</span> <span class="nf">sanitize_calculation</span><span class="p">(</span><span class="n">calculation</span><span class="p">:</span> <span class="o">&amp;</span><span class="nb">str</span><span class="p">)</span> <span class="k">-&gt;</span> <span class="nb">String</span> <span class="p">{</span>
    <span class="k">let</span> <span class="k">mut</span> <span class="n">calc</span> <span class="o">=</span> <span class="nn">Regex</span><span class="p">::</span><span class="nf">new</span><span class="p">(</span><span class="s">r"\s+"</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">()</span><span class="nf">.replace_all</span><span class="p">(</span><span class="n">calculation</span><span class="p">,</span> <span class="s">""</span><span class="p">)</span><span class="nf">.into_owned</span><span class="p">();</span>   <span class="c1">// Remove all spaces</span>
    <span class="n">calc</span> <span class="o">=</span> <span class="nn">Regex</span><span class="p">::</span><span class="nf">new</span><span class="p">(</span><span class="s">r"\++"</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">()</span><span class="nf">.replace_all</span><span class="p">(</span><span class="o">&amp;</span><span class="n">calc</span><span class="p">,</span> <span class="s">"+"</span><span class="p">)</span><span class="nf">.into_owned</span><span class="p">();</span>                <span class="c1">// ++ -&gt; +</span>
    <span class="n">calc</span> <span class="o">=</span> <span class="nn">Regex</span><span class="p">::</span><span class="nf">new</span><span class="p">(</span><span class="s">r"-+"</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">()</span><span class="nf">.replace_all</span><span class="p">(</span><span class="o">&amp;</span><span class="n">calc</span><span class="p">,</span> <span class="s">"-"</span><span class="p">)</span><span class="nf">.into_owned</span><span class="p">();</span>                 <span class="c1">// -- -&gt; -</span>
    <span class="n">calc</span> <span class="o">=</span> <span class="nn">Regex</span><span class="p">::</span><span class="nf">new</span><span class="p">(</span><span class="s">r"\*\+"</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">()</span><span class="nf">.replace_all</span><span class="p">(</span><span class="o">&amp;</span><span class="n">calc</span><span class="p">,</span> <span class="s">"*"</span><span class="p">)</span><span class="nf">.into_owned</span><span class="p">();</span>               <span class="c1">// *+ -&gt; *</span>
    <span class="n">calc</span> <span class="o">=</span> <span class="nn">Regex</span><span class="p">::</span><span class="nf">new</span><span class="p">(</span><span class="s">r"/\+"</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">()</span><span class="nf">.replace_all</span><span class="p">(</span><span class="o">&amp;</span><span class="n">calc</span><span class="p">,</span> <span class="s">"/"</span><span class="p">)</span><span class="nf">.into_owned</span><span class="p">();</span>                <span class="c1">// /+ -&gt; /</span>
    <span class="n">calc</span> <span class="o">=</span> <span class="nn">Regex</span><span class="p">::</span><span class="nf">new</span><span class="p">(</span><span class="s">r"\+-"</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">()</span><span class="nf">.replace_all</span><span class="p">(</span><span class="o">&amp;</span><span class="n">calc</span><span class="p">,</span> <span class="s">"-"</span><span class="p">)</span><span class="nf">.into_owned</span><span class="p">();</span>                <span class="c1">// +- -&gt; -</span>
    <span class="n">calc</span> <span class="o">=</span> <span class="nn">Regex</span><span class="p">::</span><span class="nf">new</span><span class="p">(</span><span class="s">r"(\d)-(\d)"</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">()</span><span class="nf">.replace_all</span><span class="p">(</span><span class="o">&amp;</span><span class="n">calc</span><span class="p">,</span> <span class="s">"$1+-$2"</span><span class="p">)</span><span class="nf">.into_owned</span><span class="p">();</span>     <span class="c1">// a-b -&gt; a+-b</span>
    <span class="n">calc</span> <span class="o">=</span> <span class="nn">Regex</span><span class="p">::</span><span class="nf">new</span><span class="p">(</span><span class="s">r"\/"</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">()</span><span class="nf">.replace_all</span><span class="p">(</span><span class="o">&amp;</span><span class="n">calc</span><span class="p">,</span> <span class="s">"*1/"</span><span class="p">)</span><span class="nf">.into_owned</span><span class="p">();</span>               <span class="c1">// a/b -&gt; a*1/b</span>
    <span class="n">calc</span>
<span class="p">}</span>

<span class="c1">// MAIN</span>
<span class="c1">// ====</span>

<span class="nd">#[allow(dead_code)]</span>
<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="nf">ask_question</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>tests.rs:</p>
<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// IMPORTS</span>
<span class="c1">// =======</span>

<span class="nd">#[path</span> <span class="nd">=</span> <span class="s">"../src/calculator.rs"</span><span class="nd">]</span>
<span class="k">mod</span> <span class="n">calculator</span><span class="p">;</span>

<span class="k">use</span> <span class="nn">calculator</span><span class="p">::</span><span class="n">get_result</span><span class="p">;</span>

<span class="c1">// FUNCTIONS</span>
<span class="c1">// =========</span>

<span class="nd">#[test]</span>
<span class="k">fn</span> <span class="nf">run_tests</span><span class="p">()</span> <span class="p">{</span>
    <span class="nd">assert_eq!</span><span class="p">(</span><span class="nf">get_result</span><span class="p">(</span><span class="s">"2 + 3"</span><span class="p">),</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span> <span class="mi">2</span> <span class="o">+</span> <span class="mi">3</span><span class="p">));</span>
    <span class="nd">assert_eq!</span><span class="p">(</span><span class="nf">get_result</span><span class="p">(</span><span class="s">"2 - 3"</span><span class="p">),</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span> <span class="mi">2</span> <span class="o">-</span> <span class="mi">3</span><span class="p">));</span>
    <span class="nd">assert_eq!</span><span class="p">(</span><span class="nf">get_result</span><span class="p">(</span><span class="s">"2 * 3"</span><span class="p">),</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span> <span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span><span class="p">));</span>
    <span class="nd">assert_eq!</span><span class="p">(</span><span class="nf">get_result</span><span class="p">(</span><span class="s">"2 / 3"</span><span class="p">),</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span> <span class="mf">2.0</span> <span class="o">/</span> <span class="mf">3.0</span><span class="p">));</span>
    <span class="nd">assert_eq!</span><span class="p">(</span><span class="nf">get_result</span><span class="p">(</span><span class="s">"2 / 0"</span><span class="p">),</span> <span class="s">"Undefined"</span><span class="p">);</span>
    <span class="nd">assert_eq!</span><span class="p">(</span><span class="nf">get_result</span><span class="p">(</span><span class="s">"  7 +   2 * 3 - 4 / -2 "</span><span class="p">),</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span>   <span class="mf">7.0</span> <span class="o">+</span>   <span class="mf">2.0</span> <span class="o">*</span> <span class="mf">3.0</span> <span class="o">-</span> <span class="mf">4.0</span> <span class="o">/</span> <span class="o">-</span><span class="mf">2.0</span> <span class="p">));</span>
    <span class="nd">assert_eq!</span><span class="p">(</span><span class="nf">get_result</span><span class="p">(</span><span class="s">"  7 +   2 / 3 - 4 * +-2 "</span><span class="p">),</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span>   <span class="mf">7.0</span> <span class="o">+</span>   <span class="mf">2.0</span> <span class="o">/</span> <span class="mf">3.0</span> <span class="o">-</span> <span class="mf">4.0</span> <span class="o">*</span> <span class="o">-</span><span class="mf">2.0</span> <span class="p">));</span>
    <span class="nd">assert_eq!</span><span class="p">(</span><span class="nf">get_result</span><span class="p">(</span><span class="s">"2.0 + 3.0"</span><span class="p">),</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span> <span class="mf">2.0</span> <span class="o">+</span> <span class="mf">3.0</span><span class="p">));</span>
<span class="p">}</span>

<span class="c1">// MAIN</span>
<span class="c1">// ====</span>

<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="nf">run_tests</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="kotlin">Kotlin</h2>

<p>I seem to have joined the newbies club because Kotlin is a relatively recent language, first appearing in 2011. I’m an avid Swift developer, so as soon as I started using Kotlin, the similarities were screaming at me: optionals, types, syntax,… Besides, the containerization (which is another subject) and float formatting being tedious, everything else was as smooth as butter.</p>

<p>Oh, and why doesn’t my VS Code have built-in syntax highlighting for it? Am I missing something? I know the language is developed by JetBrains, whose IDEs rival VS Code, so does this explain it? So many questions, so few answers. Yet there seems to be change; JetBrains recently announced that they were working on a Kotlin Language Server and extension for VS Code.</p>

<p>calculator.kt:</p>
<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// IMPORTS</span>
<span class="c1">// =======</span>

<span class="k">import</span> <span class="nn">java.io.BufferedReader</span>
<span class="k">import</span> <span class="nn">java.io.InputStreamReader</span>

<span class="c1">// FUNCTIONS</span>
<span class="c1">// =========</span>

<span class="k">fun</span> <span class="nf">askQuestion</span><span class="p">()</span> <span class="p">{</span>
    <span class="nf">print</span><span class="p">(</span><span class="s">"Your calculation: "</span><span class="p">)</span>
    <span class="kd">val</span> <span class="py">reader</span> <span class="p">=</span> <span class="nc">BufferedReader</span><span class="p">(</span><span class="nc">InputStreamReader</span><span class="p">(</span><span class="nc">System</span><span class="p">.</span><span class="n">`in`</span><span class="p">))</span>
    <span class="kd">val</span> <span class="py">calculation</span> <span class="p">=</span> <span class="n">reader</span><span class="p">.</span><span class="nf">readLine</span><span class="p">()</span>
    <span class="kd">val</span> <span class="py">result</span> <span class="p">=</span> <span class="nf">getResult</span><span class="p">(</span><span class="n">calculation</span><span class="p">)</span>
    <span class="nf">println</span><span class="p">(</span><span class="s">" = $result"</span><span class="p">)</span>
<span class="p">}</span>

<span class="k">fun</span> <span class="nf">getResult</span><span class="p">(</span><span class="n">raw</span><span class="p">:</span> <span class="nc">String</span><span class="p">?):</span> <span class="nc">String</span> <span class="p">{</span>
    <span class="kd">val</span> <span class="py">calculation</span> <span class="p">=</span> <span class="nf">sanitizeCalculation</span><span class="p">(</span><span class="n">raw</span> <span class="o">?:</span> <span class="s">""</span><span class="p">)</span>
    <span class="kd">var</span> <span class="py">result</span> <span class="p">=</span> <span class="mf">0.0</span>

    <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="k">in</span> <span class="n">calculation</span><span class="p">.</span><span class="nf">split</span><span class="p">(</span><span class="s">"+"</span><span class="p">))</span> <span class="p">{</span>
        <span class="kd">var</span> <span class="py">subResult</span> <span class="p">=</span> <span class="mf">1.0</span>
        <span class="k">for</span> <span class="p">(</span><span class="n">j</span> <span class="k">in</span> <span class="n">i</span><span class="p">.</span><span class="nf">split</span><span class="p">(</span><span class="s">"*"</span><span class="p">))</span> <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">j</span><span class="p">.</span><span class="nf">startsWith</span><span class="p">(</span><span class="s">"1/"</span><span class="p">))</span> <span class="p">{</span>
                <span class="kd">val</span> <span class="py">sanitizedJ</span> <span class="p">=</span> <span class="n">j</span><span class="p">.</span><span class="nf">removePrefix</span><span class="p">(</span><span class="s">"1/"</span><span class="p">)</span>
                <span class="kd">val</span> <span class="py">value</span> <span class="p">=</span> <span class="n">sanitizedJ</span><span class="p">.</span><span class="nf">toDoubleOrNull</span><span class="p">()</span> <span class="o">?:</span> <span class="nc">Double</span><span class="p">.</span><span class="nc">NaN</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">value</span> <span class="p">==</span> <span class="mf">0.0</span><span class="p">)</span> <span class="k">return</span> <span class="s">"Undefined"</span>
                <span class="n">subResult</span> <span class="p">/=</span> <span class="n">value</span>
            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                <span class="n">subResult</span> <span class="p">*=</span> <span class="n">j</span><span class="p">.</span><span class="nf">toDoubleOrNull</span><span class="p">()</span> <span class="o">?:</span> <span class="nc">Double</span><span class="p">.</span><span class="nc">NaN</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="n">result</span> <span class="p">+=</span> <span class="n">subResult</span>
    <span class="p">}</span>

    <span class="k">if</span> <span class="p">((</span><span class="n">result</span> <span class="p">==</span> <span class="n">result</span><span class="p">.</span><span class="nf">toInt</span><span class="p">().</span><span class="nf">toDouble</span><span class="p">())</span> <span class="p">&amp;&amp;</span> <span class="p">!</span><span class="n">calculation</span><span class="p">.</span><span class="nf">contains</span><span class="p">(</span><span class="s">"."</span><span class="p">))</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">result</span><span class="p">.</span><span class="nf">toInt</span><span class="p">().</span><span class="nf">toString</span><span class="p">()</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="n">result</span><span class="p">.</span><span class="nf">toString</span><span class="p">()</span>
<span class="p">}</span>

<span class="k">fun</span> <span class="nf">sanitizeCalculation</span><span class="p">(</span><span class="n">calculation</span><span class="p">:</span> <span class="nc">String</span><span class="p">):</span> <span class="nc">String</span> <span class="p">{</span>
    <span class="k">return</span> <span class="n">calculation</span>
        <span class="p">.</span><span class="nf">replace</span><span class="p">(</span><span class="s">"""\s+"""</span><span class="p">.</span><span class="nf">toRegex</span><span class="p">(),</span> <span class="s">""</span><span class="p">)</span>               <span class="c1">// Remove all spaces</span>
        <span class="p">.</span><span class="nf">replace</span><span class="p">(</span><span class="s">"""\++"""</span><span class="p">.</span><span class="nf">toRegex</span><span class="p">(),</span> <span class="s">"+"</span><span class="p">)</span>              <span class="c1">// ++ -&gt; +</span>
        <span class="p">.</span><span class="nf">replace</span><span class="p">(</span><span class="s">"""-+"""</span><span class="p">.</span><span class="nf">toRegex</span><span class="p">(),</span> <span class="s">"-"</span><span class="p">)</span>               <span class="c1">// -- -&gt; -</span>
        <span class="p">.</span><span class="nf">replace</span><span class="p">(</span><span class="s">"""\*\+"""</span><span class="p">.</span><span class="nf">toRegex</span><span class="p">(),</span> <span class="s">"*"</span><span class="p">)</span>             <span class="c1">// *+ -&gt; *</span>
        <span class="p">.</span><span class="nf">replace</span><span class="p">(</span><span class="s">"""/\+"""</span><span class="p">.</span><span class="nf">toRegex</span><span class="p">(),</span> <span class="s">"/"</span><span class="p">)</span>              <span class="c1">// /+ -&gt; /</span>
        <span class="p">.</span><span class="nf">replace</span><span class="p">(</span><span class="s">"""\+-"""</span><span class="p">.</span><span class="nf">toRegex</span><span class="p">(),</span> <span class="s">"-"</span><span class="p">)</span>              <span class="c1">// +- -&gt; -</span>
        <span class="p">.</span><span class="nf">replace</span><span class="p">(</span><span class="s">"""(\d)-(\d)"""</span><span class="p">.</span><span class="nf">toRegex</span><span class="p">(),</span> <span class="s">"$1+-$2"</span><span class="p">)</span>   <span class="c1">// a-b -&gt; a+-b</span>
        <span class="p">.</span><span class="nf">replace</span><span class="p">(</span><span class="s">"/"</span><span class="p">,</span> <span class="s">"*1/"</span><span class="p">)</span>                            <span class="c1">// a/b -&gt; a*1/b</span>
<span class="p">}</span>

<span class="c1">// MAIN</span>
<span class="c1">// ====</span>

<span class="k">fun</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="nf">askQuestion</span><span class="p">()</span>
<span class="p">}</span>
</code></pre></div></div>

<p>tests.kt:</p>
<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// FUNCTIONS</span>
<span class="c1">// =========</span>

<span class="k">fun</span> <span class="nf">runTests</span><span class="p">()</span> <span class="p">{</span>
    <span class="nf">println</span><span class="p">(</span><span class="s">"Test 01: "</span> <span class="p">+</span> <span class="p">(</span><span class="nf">getResult</span><span class="p">(</span><span class="s">"2 + 3"</span><span class="p">)</span> <span class="p">==</span> <span class="s">"${2 + 3}"</span><span class="p">))</span>
    <span class="nf">println</span><span class="p">(</span><span class="s">"Test 02: "</span> <span class="p">+</span> <span class="p">(</span><span class="nf">getResult</span><span class="p">(</span><span class="s">"2 - 3"</span><span class="p">)</span> <span class="p">==</span> <span class="s">"${2 - 3}"</span><span class="p">))</span>
    <span class="nf">println</span><span class="p">(</span><span class="s">"Test 03: "</span> <span class="p">+</span> <span class="p">(</span><span class="nf">getResult</span><span class="p">(</span><span class="s">"2 * 3"</span><span class="p">)</span> <span class="p">==</span> <span class="s">"${2 * 3}"</span><span class="p">))</span>
    <span class="nf">println</span><span class="p">(</span><span class="s">"Test 04: "</span> <span class="p">+</span> <span class="p">(</span><span class="nf">getResult</span><span class="p">(</span><span class="s">"2 / 3"</span><span class="p">)</span> <span class="p">==</span> <span class="s">"${2.0 / 3}"</span><span class="p">))</span>
    <span class="nf">println</span><span class="p">(</span><span class="s">"Test 05: "</span> <span class="p">+</span> <span class="p">(</span><span class="nf">getResult</span><span class="p">(</span><span class="s">"2 / 0"</span><span class="p">)</span> <span class="p">==</span> <span class="s">"Undefined"</span><span class="p">))</span>
    <span class="nf">println</span><span class="p">(</span><span class="s">"Test 06: "</span> <span class="p">+</span> <span class="p">(</span><span class="nf">getResult</span><span class="p">(</span><span class="s">"  7 +   2 * 3 - 4 / -2 "</span><span class="p">)</span> <span class="p">==</span> <span class="s">"${  7 +   2 * 3 - 4 / -2 }"</span><span class="p">))</span>
    <span class="nf">println</span><span class="p">(</span><span class="s">"Test 07: "</span> <span class="p">+</span> <span class="p">(</span><span class="nf">getResult</span><span class="p">(</span><span class="s">"  7 +   2 / 3 - 4 * +-2 "</span><span class="p">)</span> <span class="p">==</span> <span class="s">"${  7 +   2.0 / 3 - 4 * +-2 }"</span><span class="p">))</span>
    <span class="nf">println</span><span class="p">(</span><span class="s">"Test 08: "</span> <span class="p">+</span> <span class="p">(</span><span class="nf">getResult</span><span class="p">(</span><span class="s">"2.0 + 3.0"</span><span class="p">)</span> <span class="p">==</span> <span class="s">"${2.0 + 3.0}"</span><span class="p">))</span>
<span class="p">}</span>

<span class="c1">// MAIN</span>
<span class="c1">// ====</span>

<span class="k">fun</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="nf">runTests</span><span class="p">()</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="lua">Lua</h2>

<p>This, I think, is the first time I have ever heard or been exposed to the Lua programming language. I thought that it would also be part of the younger club, but I was totally wrong. It is actually closer to JavaScript, having been introduced in 1993.</p>

<p>In some ways, the language seems modern, like a blend of JavaScript and Python. In other ways, it has unique quirks. Lua doesn’t use regular expressions, but its own pattern-matching system, which is somewhat annoying. In fact, I lost half an hour to find out that <code class="language-plaintext highlighter-rouge">-</code> is also a special character that should be escaped, not using a backslash but a percentage symbol. It also stems from the rare breed that allows the execution of code outside of any block, essentially meaning that the entire file is the main function.</p>

<p>Also interesting how Lua uses the colon, like other languages use the dot for chaining. Makes me wonder why some like to have a unique syntax from “the norm”. What gives? Well, I looked up the answer, so let me explain. In Lua, the dot is the table-access operator, which allows us to write this: obj.func(obj, arg1, arg2); similarly to other languages. On the other hand, the colon is syntactic sugar that passes the object as the first argument, making the code shorter: obj:func(arg1, arg2); where other languages would implicitly pass self to the function.</p>

<p>calculator.lua:</p>
<div class="language-lua highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">-- FUNCTIONS</span>
<span class="c1">-- =========</span>

<span class="kd">local</span> <span class="k">function</span> <span class="nf">sanitizeCalculation</span><span class="p">(</span><span class="n">calculation</span><span class="p">)</span>
    <span class="n">calculation</span> <span class="o">=</span> <span class="n">calculation</span><span class="p">:</span><span class="nb">gsub</span><span class="p">(</span><span class="sr">"%s+"</span><span class="p">,</span> <span class="sr">""</span><span class="p">)</span>               <span class="c1">-- Remove all spaces</span>
    <span class="n">calculation</span> <span class="o">=</span> <span class="n">calculation</span><span class="p">:</span><span class="nb">gsub</span><span class="p">(</span><span class="sr">"%++"</span><span class="p">,</span> <span class="sr">"+"</span><span class="p">)</span>              <span class="c1">-- ++ -&gt; +</span>
    <span class="n">calculation</span> <span class="o">=</span> <span class="n">calculation</span><span class="p">:</span><span class="nb">gsub</span><span class="p">(</span><span class="sr">"%-+"</span><span class="p">,</span> <span class="sr">"-"</span><span class="p">)</span>              <span class="c1">-- -- -&gt; -</span>
    <span class="n">calculation</span> <span class="o">=</span> <span class="n">calculation</span><span class="p">:</span><span class="nb">gsub</span><span class="p">(</span><span class="sr">"%*%+"</span><span class="p">,</span> <span class="sr">"*"</span><span class="p">)</span>             <span class="c1">-- *+ -&gt; *</span>
    <span class="n">calculation</span> <span class="o">=</span> <span class="n">calculation</span><span class="p">:</span><span class="nb">gsub</span><span class="p">(</span><span class="sr">"/%+"</span><span class="p">,</span> <span class="sr">"/"</span><span class="p">)</span>              <span class="c1">-- /+ -&gt; /</span>
    <span class="n">calculation</span> <span class="o">=</span> <span class="n">calculation</span><span class="p">:</span><span class="nb">gsub</span><span class="p">(</span><span class="sr">"%+%-"</span><span class="p">,</span> <span class="sr">"-"</span><span class="p">)</span>             <span class="c1">-- +- -&gt; -</span>
    <span class="n">calculation</span> <span class="o">=</span> <span class="n">calculation</span><span class="p">:</span><span class="nb">gsub</span><span class="p">(</span><span class="sr">"</span><span class="se">(</span><span class="sr">%d</span><span class="se">)</span><span class="sr">-</span><span class="se">(</span><span class="sr">%d</span><span class="se">)</span><span class="sr">"</span><span class="p">,</span> <span class="sr">"%1+-%2"</span><span class="p">)</span>   <span class="c1">-- a-b -&gt; a+-b</span>
    <span class="n">calculation</span> <span class="o">=</span> <span class="n">calculation</span><span class="p">:</span><span class="nb">gsub</span><span class="p">(</span><span class="sr">"/"</span><span class="p">,</span> <span class="sr">"*1/"</span><span class="p">)</span>              <span class="c1">-- a/b -&gt; a*1/b</span>
    <span class="k">return</span> <span class="n">calculation</span>
<span class="k">end</span>

<span class="kd">local</span> <span class="k">function</span> <span class="nf">getResult</span><span class="p">(</span><span class="n">calculation</span><span class="p">)</span>
    <span class="n">calculation</span> <span class="o">=</span> <span class="n">sanitizeCalculation</span><span class="p">(</span><span class="n">calculation</span> <span class="ow">or</span> <span class="s2">""</span><span class="p">)</span>
    <span class="kd">local</span> <span class="n">result</span> <span class="o">=</span> <span class="mi">0</span><span class="p">.</span><span class="mi">0</span>

    <span class="k">for</span> <span class="n">i</span> <span class="k">in</span> <span class="n">calculation</span><span class="p">:</span><span class="n">gmatch</span><span class="p">(</span><span class="s2">"([^%+]+)"</span><span class="p">)</span> <span class="k">do</span>
        <span class="kd">local</span> <span class="n">subResult</span> <span class="o">=</span> <span class="mi">1</span><span class="p">.</span><span class="mi">0</span>
        <span class="k">for</span> <span class="n">j</span> <span class="k">in</span> <span class="n">i</span><span class="p">:</span><span class="n">gmatch</span><span class="p">(</span><span class="s2">"([^%*]+)"</span><span class="p">)</span> <span class="k">do</span>
            <span class="k">if</span> <span class="n">j</span><span class="p">:</span><span class="n">sub</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="o">==</span> <span class="s2">"1/"</span> <span class="k">then</span>
                <span class="kd">local</span> <span class="n">sanitizedJ</span> <span class="o">=</span> <span class="n">j</span><span class="p">:</span><span class="n">sub</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
                <span class="k">if</span> <span class="nb">tonumber</span><span class="p">(</span><span class="n">sanitizedJ</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span> <span class="k">then</span> <span class="k">return</span> <span class="s2">"Undefined"</span> <span class="k">end</span>
                <span class="n">subResult</span> <span class="o">=</span> <span class="n">subResult</span> <span class="o">/</span> <span class="nb">tonumber</span><span class="p">(</span><span class="n">sanitizedJ</span><span class="p">)</span>
            <span class="k">else</span>
                <span class="n">subResult</span> <span class="o">=</span> <span class="n">subResult</span> <span class="o">*</span> <span class="nb">tonumber</span><span class="p">(</span><span class="n">j</span><span class="p">)</span>
            <span class="k">end</span>
        <span class="k">end</span>
        <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">+</span> <span class="n">subResult</span>
    <span class="k">end</span>

    <span class="k">if</span> <span class="n">result</span> <span class="o">==</span> <span class="nb">math.tointeger</span><span class="p">(</span><span class="n">result</span><span class="p">)</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">calculation</span><span class="p">:</span><span class="n">find</span><span class="p">(</span><span class="s2">"/"</span><span class="p">)</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">calculation</span><span class="p">:</span><span class="n">find</span><span class="p">(</span><span class="s2">"%."</span><span class="p">)</span> <span class="k">then</span>
        <span class="k">return</span> <span class="nb">tostring</span><span class="p">(</span><span class="nb">math.tointeger</span><span class="p">(</span><span class="n">result</span><span class="p">))</span>
    <span class="k">end</span>
    <span class="k">return</span> <span class="nb">tostring</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
<span class="k">end</span>

<span class="kd">local</span> <span class="k">function</span> <span class="nf">askQuestion</span><span class="p">()</span>
    <span class="nb">io.write</span><span class="p">(</span><span class="s2">"Your calculation: "</span><span class="p">)</span>
    <span class="kd">local</span> <span class="n">calculation</span> <span class="o">=</span> <span class="nb">io.read</span><span class="p">(</span><span class="s2">"*l"</span><span class="p">)</span> <span class="ow">or</span> <span class="s2">""</span>
    <span class="kd">local</span> <span class="n">result</span> <span class="o">=</span> <span class="n">getResult</span><span class="p">(</span><span class="n">calculation</span><span class="p">)</span>
    <span class="nb">print</span><span class="p">(</span><span class="s2">" = "</span> <span class="o">..</span> <span class="n">result</span><span class="p">)</span>
<span class="k">end</span>

<span class="c1">-- MAIN</span>
<span class="c1">-- ====</span>

<span class="c1">-- If required as a module, expose functions; otherwise run CLI</span>
<span class="k">if</span> <span class="nb">pcall</span><span class="p">(</span><span class="nb">debug.getlocal</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="k">then</span>
    <span class="k">return</span> <span class="p">{</span> <span class="n">getResult</span> <span class="o">=</span> <span class="n">getResult</span> <span class="p">}</span>
<span class="k">else</span>
    <span class="n">askQuestion</span><span class="p">()</span>
<span class="k">end</span>
</code></pre></div></div>

<p>tests.lua:</p>
<div class="language-lua highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">-- IMPORTS</span>
<span class="c1">-- =======</span>

<span class="kd">local</span> <span class="n">calc</span> <span class="o">=</span> <span class="nb">require</span><span class="p">(</span><span class="s2">"calculator"</span><span class="p">)</span>
<span class="kd">local</span> <span class="n">getResult</span> <span class="o">=</span> <span class="n">calc</span><span class="p">.</span><span class="n">getResult</span>

<span class="c1">-- FUNCTIONS</span>
<span class="c1">-- =========</span>

<span class="kd">local</span> <span class="k">function</span> <span class="nf">runTests</span><span class="p">()</span>
    <span class="nb">print</span><span class="p">(</span><span class="s2">"Test 01: "</span> <span class="o">..</span> <span class="nb">tostring</span><span class="p">(</span><span class="n">getResult</span><span class="p">(</span><span class="s2">"2 + 3"</span><span class="p">)</span> <span class="o">==</span> <span class="nb">tostring</span><span class="p">(</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">3</span><span class="p">)))</span>
    <span class="nb">print</span><span class="p">(</span><span class="s2">"Test 02: "</span> <span class="o">..</span> <span class="nb">tostring</span><span class="p">(</span><span class="n">getResult</span><span class="p">(</span><span class="s2">"2 - 3"</span><span class="p">)</span> <span class="o">==</span> <span class="nb">tostring</span><span class="p">(</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">3</span><span class="p">)))</span>
    <span class="nb">print</span><span class="p">(</span><span class="s2">"Test 03: "</span> <span class="o">..</span> <span class="nb">tostring</span><span class="p">(</span><span class="n">getResult</span><span class="p">(</span><span class="s2">"2 * 3"</span><span class="p">)</span> <span class="o">==</span> <span class="nb">tostring</span><span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span><span class="p">)))</span>
    <span class="nb">print</span><span class="p">(</span><span class="s2">"Test 04: "</span> <span class="o">..</span> <span class="nb">tostring</span><span class="p">(</span><span class="n">getResult</span><span class="p">(</span><span class="s2">"2 / 3"</span><span class="p">)</span> <span class="o">==</span> <span class="nb">tostring</span><span class="p">(</span><span class="mi">2</span> <span class="o">/</span> <span class="mi">3</span><span class="p">)))</span>
    <span class="nb">print</span><span class="p">(</span><span class="s2">"Test 05: "</span> <span class="o">..</span> <span class="nb">tostring</span><span class="p">(</span><span class="n">getResult</span><span class="p">(</span><span class="s2">"2 / 0"</span><span class="p">)</span> <span class="o">==</span> <span class="s2">"Undefined"</span><span class="p">))</span>
    <span class="nb">print</span><span class="p">(</span><span class="s2">"Test 06: "</span> <span class="o">..</span> <span class="nb">tostring</span><span class="p">(</span><span class="n">getResult</span><span class="p">(</span><span class="s2">"  7 +   2 * 3 - 4 / -2 "</span><span class="p">)</span> <span class="o">==</span> <span class="nb">tostring</span><span class="p">(</span>  <span class="mi">7</span> <span class="o">+</span>   <span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">/</span> <span class="o">-</span><span class="mi">2</span> <span class="p">)))</span>
    <span class="nb">print</span><span class="p">(</span><span class="s2">"Test 07: "</span> <span class="o">..</span> <span class="nb">tostring</span><span class="p">(</span><span class="n">getResult</span><span class="p">(</span><span class="s2">"  7 +   2 / 3 - 4 * +-2 "</span><span class="p">)</span> <span class="o">==</span> <span class="nb">tostring</span><span class="p">(</span>  <span class="mi">7</span> <span class="o">+</span>   <span class="mi">2</span> <span class="o">/</span> <span class="mi">3</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">-</span><span class="mi">2</span> <span class="p">)))</span>
    <span class="nb">print</span><span class="p">(</span><span class="s2">"Test 08: "</span> <span class="o">..</span> <span class="nb">tostring</span><span class="p">(</span><span class="n">getResult</span><span class="p">(</span><span class="s2">"2.0 + 3.0"</span><span class="p">)</span> <span class="o">==</span> <span class="nb">tostring</span><span class="p">(</span><span class="mi">2</span><span class="p">.</span><span class="mi">0</span> <span class="o">+</span> <span class="mi">3</span><span class="p">.</span><span class="mi">0</span><span class="p">)))</span>
<span class="k">end</span>

<span class="c1">-- MAIN</span>
<span class="c1">-- ====</span>

<span class="n">runTests</span><span class="p">()</span>
</code></pre></div></div>

<h2 id="assembly">Assembly</h2>

<p>I tried, and I failed. I’ve been dreading this moment ever since I saw that Assembly was in the top 20, which meant that I had to work with it. I took courses working with Assembly or Assembly-like code on paper, but building anything with it requires not only a deep understanding of the language but also understanding the system on which the language is running. I know neither that well. After attempting with the x86-64 NASM syntax, I gave up.</p>

<p>The files I had were twice as long as others, the commands were less readable, and anything not remotely basic had to be recreated manually. With pure perseverance and more tutorials, maybe I could’ve done it, but I just didn’t want to go down that rabbit hole. Lots of developers didn’t want to, because we wouldn’t have created all those other programming languages that are easier to read, write, and collaborate with.</p>

<h2 id="ruby">Ruby</h2>

<p>Ruby looks like Python and Lua, and was released in the same era: the mid-1990s. I know Ruby mainly from installing the gems that make my website codebase easier to maintain. That said, it’s a very pleasant language and works great as expected.</p>

<p>Now, I know that I’ve been bombarding you with rhetorical questions and answers here and there, so let me give you another one: what’s made Python more popular than Ruby and Lua, for instance? They look and feel the same, but I haven’t dived deep into the lore and the communities surrounding them to know more. Python excels in general-purpose domains, data science, and web development, and it has a wide range of libraries and community support. It also had a couple of years of head start and worked well with scientists and analysts, paving the way for a feedback loop: students learn Python, workforce demands for Python increase, and more projects utilize Python.</p>

<p>calculation.rb:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># FUNCTIONS</span>
<span class="c1"># =========</span>

<span class="k">def</span> <span class="nf">ask_question</span>
    <span class="nb">print</span> <span class="s1">'Your calculation: '</span>
    <span class="n">calculation</span> <span class="o">=</span> <span class="no">STDIN</span><span class="p">.</span><span class="nf">gets</span>
    <span class="k">return</span> <span class="k">unless</span> <span class="n">calculation</span>
    <span class="n">result</span> <span class="o">=</span> <span class="n">get_result</span><span class="p">(</span><span class="n">calculation</span><span class="p">)</span>
    <span class="nb">puts</span> <span class="s2">" = </span><span class="si">#{</span><span class="n">result</span><span class="si">}</span><span class="s2">"</span>
<span class="k">end</span>

<span class="k">def</span> <span class="nf">get_result</span><span class="p">(</span><span class="n">calculation</span><span class="p">)</span>
    <span class="n">calculation</span> <span class="o">=</span> <span class="n">sanitize_calculation</span><span class="p">(</span><span class="n">calculation</span><span class="p">)</span>
    <span class="n">result</span> <span class="o">=</span> <span class="mf">0.0</span>

    <span class="n">calculation</span><span class="p">.</span><span class="nf">split</span><span class="p">(</span><span class="s1">'+'</span><span class="p">).</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">i</span><span class="o">|</span>
        <span class="n">sub_result</span> <span class="o">=</span> <span class="mf">1.0</span>
        <span class="n">i</span><span class="p">.</span><span class="nf">split</span><span class="p">(</span><span class="s1">'*'</span><span class="p">).</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">j</span><span class="o">|</span>
            <span class="k">if</span> <span class="n">j</span><span class="p">.</span><span class="nf">start_with?</span><span class="p">(</span><span class="s1">'1/'</span><span class="p">)</span>
                <span class="n">sanitized_j</span> <span class="o">=</span> <span class="n">j</span><span class="p">.</span><span class="nf">gsub</span><span class="p">(</span><span class="sr">%r{1/}</span><span class="p">,</span> <span class="s1">''</span><span class="p">)</span>
                <span class="k">return</span> <span class="s1">'Undefined'</span> <span class="k">if</span> <span class="n">sanitized_j</span><span class="p">.</span><span class="nf">to_f</span> <span class="o">==</span> <span class="mf">0.0</span>
                <span class="n">sub_result</span> <span class="o">/=</span> <span class="n">sanitized_j</span><span class="p">.</span><span class="nf">to_f</span>
            <span class="k">else</span>
                <span class="n">sub_result</span> <span class="o">*=</span> <span class="n">j</span><span class="p">.</span><span class="nf">to_f</span>
            <span class="k">end</span>
        <span class="k">end</span>
        <span class="n">result</span> <span class="o">+=</span> <span class="n">sub_result</span>
    <span class="k">end</span>

    <span class="k">if</span> <span class="n">result</span> <span class="o">==</span> <span class="n">result</span><span class="p">.</span><span class="nf">to_i</span> <span class="n">and</span> <span class="o">!</span><span class="n">calculation</span><span class="p">.</span><span class="nf">include?</span><span class="p">(</span><span class="s2">"/"</span><span class="p">)</span> <span class="n">and</span> <span class="o">!</span><span class="n">calculation</span><span class="p">.</span><span class="nf">include?</span><span class="p">(</span><span class="s2">"."</span><span class="p">)</span> <span class="k">then</span>
        <span class="k">return</span> <span class="n">result</span><span class="p">.</span><span class="nf">to_i</span><span class="p">.</span><span class="nf">to_s</span>
    <span class="k">end</span>
    <span class="n">result</span><span class="p">.</span><span class="nf">to_s</span>
<span class="k">end</span>

<span class="k">def</span> <span class="nf">sanitize_calculation</span><span class="p">(</span><span class="n">calculation</span><span class="p">)</span>
    <span class="n">calculation</span>
        <span class="p">.</span><span class="nf">gsub</span><span class="p">(</span><span class="sr">/\s+/</span><span class="p">,</span> <span class="s1">''</span><span class="p">)</span>                <span class="c1"># Remove all spaces</span>
        <span class="p">.</span><span class="nf">gsub</span><span class="p">(</span><span class="sr">/\++/</span><span class="p">,</span> <span class="s1">'+'</span><span class="p">)</span>               <span class="c1"># ++ -&gt; +</span>
        <span class="p">.</span><span class="nf">gsub</span><span class="p">(</span><span class="sr">/-+/</span><span class="p">,</span> <span class="s1">'-'</span><span class="p">)</span>                <span class="c1"># -- -&gt; -</span>
        <span class="p">.</span><span class="nf">gsub</span><span class="p">(</span><span class="sr">/\*\+/</span><span class="p">,</span> <span class="s1">'*'</span><span class="p">)</span>              <span class="c1"># *+ -&gt; *</span>
        <span class="p">.</span><span class="nf">gsub</span><span class="p">(</span><span class="sr">/\/\+/</span><span class="p">,</span> <span class="s1">'/'</span><span class="p">)</span>              <span class="c1"># /+ -&gt; /</span>
        <span class="p">.</span><span class="nf">gsub</span><span class="p">(</span><span class="sr">/\+-/</span><span class="p">,</span> <span class="s1">'-'</span><span class="p">)</span>               <span class="c1"># +- -&gt; -</span>
        <span class="p">.</span><span class="nf">gsub</span><span class="p">(</span><span class="sr">/(\d)-(\d)/</span><span class="p">,</span> <span class="s1">'\1+-\2'</span><span class="p">)</span>    <span class="c1"># a-b -&gt; a+-b</span>
        <span class="p">.</span><span class="nf">gsub</span><span class="p">(</span><span class="sr">/\//</span><span class="p">,</span> <span class="s1">'*1/'</span><span class="p">)</span>              <span class="c1"># a/b -&gt; a*1/b</span>
<span class="k">end</span>

<span class="c1"># MAIN</span>
<span class="c1"># ====</span>

<span class="k">if</span> <span class="kp">__FILE__</span> <span class="o">==</span> <span class="vg">$PROGRAM_NAME</span>
    <span class="n">ask_question</span>
<span class="k">end</span>
</code></pre></div></div>

<p>tests.rb:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># IMPORTS</span>
<span class="c1"># =======</span>

<span class="nb">require_relative</span> <span class="s1">'./calculator'</span>

<span class="c1"># FUNCTIONS</span>
<span class="c1"># =========</span>

<span class="k">def</span> <span class="nf">run_tests</span>
  <span class="nb">puts</span> <span class="s2">"Test 01: </span><span class="si">#{</span><span class="n">get_result</span><span class="p">(</span><span class="s1">'2 + 3'</span><span class="p">)</span> <span class="o">==</span> <span class="p">(</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">3</span><span class="p">).</span><span class="nf">to_s</span><span class="si">}</span><span class="s2">"</span>
  <span class="nb">puts</span> <span class="s2">"Test 02: </span><span class="si">#{</span><span class="n">get_result</span><span class="p">(</span><span class="s1">'2 - 3'</span><span class="p">)</span> <span class="o">==</span> <span class="p">(</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">3</span><span class="p">).</span><span class="nf">to_s</span><span class="si">}</span><span class="s2">"</span>
  <span class="nb">puts</span> <span class="s2">"Test 03: </span><span class="si">#{</span><span class="n">get_result</span><span class="p">(</span><span class="s1">'2 * 3'</span><span class="p">)</span> <span class="o">==</span> <span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span><span class="p">).</span><span class="nf">to_s</span><span class="si">}</span><span class="s2">"</span>
  <span class="nb">puts</span> <span class="s2">"Test 04: </span><span class="si">#{</span><span class="n">get_result</span><span class="p">(</span><span class="s1">'2 / 3'</span><span class="p">)</span> <span class="o">==</span> <span class="p">(</span><span class="mi">2</span> <span class="o">/</span> <span class="mf">3.0</span><span class="p">).</span><span class="nf">to_s</span><span class="si">}</span><span class="s2">"</span>
  <span class="nb">puts</span> <span class="s2">"Test 05: </span><span class="si">#{</span><span class="n">get_result</span><span class="p">(</span><span class="s1">'2 / 0'</span><span class="p">)</span> <span class="o">==</span> <span class="s1">'Undefined'</span><span class="si">}</span><span class="s2">"</span>
  <span class="nb">puts</span> <span class="s2">"Test 06: </span><span class="si">#{</span><span class="n">get_result</span><span class="p">(</span><span class="s1">'  7 +   2 * 3 - 4 / -2 '</span><span class="p">)</span> <span class="o">==</span> <span class="p">(</span>  <span class="mi">7</span> <span class="o">+</span>   <span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">/</span> <span class="o">-</span><span class="mf">2.0</span> <span class="p">).</span><span class="nf">to_s</span><span class="si">}</span><span class="s2">"</span>
  <span class="nb">puts</span> <span class="s2">"Test 07: </span><span class="si">#{</span><span class="n">get_result</span><span class="p">(</span><span class="s1">'  7 +   2 / 3 - 4 * +-2 '</span><span class="p">)</span> <span class="o">==</span> <span class="p">(</span>  <span class="mi">7</span> <span class="o">+</span>   <span class="mi">2</span> <span class="o">/</span> <span class="mf">3.0</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">+-</span><span class="mi">2</span> <span class="p">).</span><span class="nf">to_s</span><span class="si">}</span><span class="s2">"</span>
  <span class="nb">puts</span> <span class="s2">"Test 08: </span><span class="si">#{</span><span class="n">get_result</span><span class="p">(</span><span class="s1">'2.0 + 3.0'</span><span class="p">)</span> <span class="o">==</span> <span class="p">(</span><span class="mf">2.0</span> <span class="o">+</span> <span class="mf">3.0</span><span class="p">).</span><span class="nf">to_s</span><span class="si">}</span><span class="s2">"</span>
<span class="k">end</span>

<span class="c1"># MAIN</span>
<span class="c1"># ====</span>

<span class="k">if</span> <span class="kp">__FILE__</span> <span class="o">==</span> <span class="vg">$PROGRAM_NAME</span>
  <span class="n">run_tests</span>
<span class="k">end</span>
</code></pre></div></div>

<h2 id="dart">Dart</h2>

<p>Dart feels like a modern language, very easy to use. Again, it feels like I’m back at home using Swift types and optionals. The only feature that’s not modern is the semicolons. Love them or hate them, I don’t love them (I wouldn’t say I hate them, but I can still live with them; however, they should retire already). Dart was released by Google in 2011. Why do I say that only now? Because it makes a perfect transition to the next language!</p>

<p>calculation.dart:</p>
<div class="language-dart highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// IMPORTS</span>
<span class="c1">// =======</span>

<span class="kn">import</span> <span class="s">'dart:io'</span><span class="o">;</span>

<span class="c1">// FUNCTIONS</span>
<span class="c1">// =========</span>

<span class="kt">void</span> <span class="nf">askQuestion</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">stdout</span><span class="o">.</span><span class="na">write</span><span class="p">(</span><span class="s">"Your calculation: "</span><span class="p">);</span>
    <span class="kd">final</span> <span class="n">calculation</span> <span class="o">=</span> <span class="n">stdin</span><span class="o">.</span><span class="na">readLineSync</span><span class="p">();</span>
    <span class="kd">final</span> <span class="n">result</span> <span class="o">=</span> <span class="n">getResult</span><span class="p">(</span><span class="n">calculation</span><span class="p">);</span>
    <span class="n">stdout</span><span class="o">.</span><span class="na">writeln</span><span class="p">(</span><span class="s">" = </span><span class="si">$result</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>

<span class="kt">String</span> <span class="nf">getResult</span><span class="p">(</span><span class="kt">String</span> <span class="n">calculation</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">calculation</span> <span class="o">=</span> <span class="n">sanitizeCalculation</span><span class="p">(</span><span class="n">calculation</span><span class="p">);</span>
    <span class="kt">double</span> <span class="n">result</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span>

    <span class="k">for</span> <span class="p">(</span><span class="kd">final</span> <span class="n">i</span> <span class="k">in</span> <span class="n">calculation</span><span class="o">.</span><span class="na">split</span><span class="p">(</span><span class="s">"+"</span><span class="p">))</span> <span class="p">{</span>
        <span class="kt">double</span> <span class="n">subResult</span> <span class="o">=</span> <span class="mf">1.0</span><span class="p">;</span>
        <span class="k">for</span> <span class="p">(</span><span class="kd">final</span> <span class="n">j</span> <span class="k">in</span> <span class="n">i</span><span class="o">.</span><span class="na">split</span><span class="p">(</span><span class="s">"*"</span><span class="p">))</span> <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">j</span><span class="o">.</span><span class="na">startsWith</span><span class="p">(</span><span class="s">"1/"</span><span class="p">))</span> <span class="p">{</span>
                <span class="kd">final</span> <span class="n">sanitizedJ</span> <span class="o">=</span> <span class="n">j</span><span class="o">.</span><span class="na">replaceAll</span><span class="p">(</span><span class="n">RegExp</span><span class="p">(</span><span class="sx">r"1/"</span><span class="p">),</span> <span class="s">""</span><span class="p">);</span>
                <span class="kd">final</span> <span class="n">value</span> <span class="o">=</span> <span class="kt">double</span><span class="o">.</span><span class="na">tryParse</span><span class="p">(</span><span class="n">sanitizedJ</span><span class="p">)</span> <span class="o">??</span> <span class="kt">double</span><span class="o">.</span><span class="na">nan</span><span class="p">;</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">value</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="s">"Undefined"</span><span class="p">;</span>
                <span class="n">subResult</span> <span class="o">/=</span> <span class="n">value</span><span class="p">;</span>
            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                <span class="kd">final</span> <span class="n">value</span> <span class="o">=</span> <span class="kt">double</span><span class="o">.</span><span class="na">tryParse</span><span class="p">(</span><span class="n">j</span><span class="p">)</span> <span class="o">??</span> <span class="kt">double</span><span class="o">.</span><span class="na">nan</span><span class="p">;</span>
                <span class="n">subResult</span> <span class="o">*=</span> <span class="n">value</span><span class="p">;</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="n">result</span> <span class="o">+=</span> <span class="n">subResult</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">result</span> <span class="o">==</span> <span class="n">result</span><span class="o">.</span><span class="na">toInt</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">calculation</span><span class="o">.</span><span class="na">contains</span><span class="p">(</span><span class="s">"/"</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">calculation</span><span class="o">.</span><span class="na">contains</span><span class="p">(</span><span class="s">"."</span><span class="p">))</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">result</span><span class="o">.</span><span class="na">toInt</span><span class="p">()</span><span class="o">.</span><span class="na">toString</span><span class="p">();</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="n">result</span><span class="o">.</span><span class="na">toString</span><span class="p">();</span>
<span class="p">}</span>

<span class="kt">String</span> <span class="nf">sanitizeCalculation</span><span class="p">(</span><span class="kt">String</span> <span class="n">calculation</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="n">calculation</span>
        <span class="o">.</span><span class="na">replaceAll</span><span class="p">(</span><span class="n">RegExp</span><span class="p">(</span><span class="sx">r"\s+"</span><span class="p">),</span> <span class="s">""</span><span class="p">)</span>                                                 <span class="c1">// Remove all spaces</span>
        <span class="o">.</span><span class="na">replaceAll</span><span class="p">(</span><span class="n">RegExp</span><span class="p">(</span><span class="sx">r"\++"</span><span class="p">),</span> <span class="s">"+"</span><span class="p">)</span>                                                <span class="c1">// ++ -&gt; +</span>
        <span class="o">.</span><span class="na">replaceAll</span><span class="p">(</span><span class="n">RegExp</span><span class="p">(</span><span class="sx">r"-+"</span><span class="p">),</span> <span class="s">"-"</span><span class="p">)</span>                                                 <span class="c1">// -- -&gt; -</span>
        <span class="o">.</span><span class="na">replaceAll</span><span class="p">(</span><span class="n">RegExp</span><span class="p">(</span><span class="sx">r"\*\+"</span><span class="p">),</span> <span class="s">"*"</span><span class="p">)</span>                                               <span class="c1">// *+ -&gt; *</span>
        <span class="o">.</span><span class="na">replaceAll</span><span class="p">(</span><span class="n">RegExp</span><span class="p">(</span><span class="sx">r"/\+"</span><span class="p">),</span> <span class="s">"/"</span><span class="p">)</span>                                                <span class="c1">// /+ -&gt; /</span>
        <span class="o">.</span><span class="na">replaceAll</span><span class="p">(</span><span class="n">RegExp</span><span class="p">(</span><span class="sx">r"\+-"</span><span class="p">),</span> <span class="s">"-"</span><span class="p">)</span>                                                <span class="c1">// +- -&gt; -</span>
        <span class="o">.</span><span class="na">replaceAllMapped</span><span class="p">(</span><span class="n">RegExp</span><span class="p">(</span><span class="sx">r"(\d)-(\d)"</span><span class="p">),</span> <span class="p">(</span><span class="n">match</span><span class="p">)</span> <span class="o">=</span><span class="p">&gt;</span> <span class="s">"</span><span class="si">${match[1]}</span><span class="s">+-</span><span class="si">${match[2]}</span><span class="s">"</span><span class="p">)</span>  <span class="c1">// a-b -&gt; a+-b</span>
        <span class="o">.</span><span class="na">replaceAll</span><span class="p">(</span><span class="s">"/"</span><span class="p">,</span> <span class="s">"*1/"</span><span class="p">);</span>                                                        <span class="c1">// a/b -&gt; a*1/b</span>
<span class="p">}</span>

<span class="c1">// MAIN</span>
<span class="c1">// ====</span>

<span class="kt">void</span> <span class="nf">main</span><span class="p">(</span><span class="kt">List</span><span class="p">&lt;</span><span class="kt">String</span><span class="p">&gt;</span> <span class="n">args</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">askQuestion</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>tests.dart:</p>
<div class="language-dart highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// IMPORTS</span>
<span class="c1">// =======</span>

<span class="kn">import</span> <span class="s">'calculator.dart'</span><span class="o">;</span>

<span class="c1">// FUNCTIONS</span>
<span class="c1">// =========</span>

<span class="kt">void</span> <span class="nf">runTests</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">print</span><span class="p">(</span><span class="s">'Test 01: </span><span class="si">${getResult("2 + 3") == "${2 + 3}</span><span class="s">"}'</span><span class="p">);</span>
    <span class="n">print</span><span class="p">(</span><span class="s">'Test 02: </span><span class="si">${getResult("2 - 3") == "${2 - 3}</span><span class="s">"}'</span><span class="p">);</span>
    <span class="n">print</span><span class="p">(</span><span class="s">'Test 03: </span><span class="si">${getResult("2 * 3") == "${2 * 3}</span><span class="s">"}'</span><span class="p">);</span>
    <span class="n">print</span><span class="p">(</span><span class="s">'Test 04: </span><span class="si">${getResult("2 / 3") == "${2 / 3}</span><span class="s">"}'</span><span class="p">);</span>
    <span class="n">print</span><span class="p">(</span><span class="s">'Test 05: </span><span class="si">${getResult("2 / 0") == "Undefined"}</span><span class="s">'</span><span class="p">);</span>
    <span class="n">print</span><span class="p">(</span><span class="s">'Test 06: </span><span class="si">${getResult("  7 +   2 * 3 - 4 / -2 ") == "${  7 +   2 * 3 - 4 / -2 }</span><span class="s">"}'</span><span class="p">);</span>
    <span class="n">print</span><span class="p">(</span><span class="s">'Test 07: </span><span class="si">${getResult("  7 +   2 / 3 - 4 * +-2 ") == "${  7 +   2 / 3 - 4 * -2 }</span><span class="s">"}'</span><span class="p">);</span>
    <span class="n">print</span><span class="p">(</span><span class="s">'Test 08: </span><span class="si">${getResult("2.0 + 3.0") == "${2.0 + 3.0}</span><span class="s">"}'</span><span class="p">);</span>
<span class="p">}</span>

<span class="c1">// MAIN</span>
<span class="c1">// ====</span>

<span class="kt">void</span> <span class="nf">main</span><span class="p">(</span><span class="kt">List</span><span class="p">&lt;</span><span class="kt">String</span><span class="p">&gt;</span> <span class="n">args</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">runTests</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="swift">Swift</h2>

<p>Swift is a language released by Apple in 2014 to rival Taylor Swift’s music. I use it to develop my applications on Apple devices. Usually, I develop with Xcode and not the command line. I quickly realized that it was painful. Compilation times are always as long, but compiling multiple files at once is tedious. Now, yes, I use the cat command to combine my two files so that I can run my tests, and I use ugly if-statements to conditionally execute the main functions. Instead, I could use the Swift Package Manager, and it can be more elegant, but I’m doing scripting here, and there’s nothing less tedious than having to create more folders and files for simple code. The Swift developer community also builds tools like swift-sh, which can make scripting easier.</p>

<p>Concerning input sanitization, there are multiple ways to work with regular expressions. This comes after enlightenment from a more experienced member of the Swift community. One way of preventing the redundancy of escaping characters with a backslash is by using raw string literals <code class="language-plaintext highlighter-rouge">#"..."#</code> with the <code class="language-plaintext highlighter-rouge">replacingOccurrences</code> function.  Another newer solution is to let go of the string and use regex literals. So, instead of this: <code class="language-plaintext highlighter-rouge">"(\\d)-(\\d)"</code>, I’d simply write <code class="language-plaintext highlighter-rouge">/(\d)-(\d)/</code> with the <code class="language-plaintext highlighter-rouge">replacing</code> function (the slash still needs to be escaped though!). Finally, there is also the <a href="https://developer.apple.com/documentation/regexbuilder">RegexBuilder</a>, more verbose but more readable. Regex literals didn’t work for me, even with the latest Swift 6.2 version, and it seems that they have to be explicitly enabled somewhere. Hence, I opted for one last solution: extended regex literals <code class="language-plaintext highlighter-rouge">#/.../#</code>!</p>

<p>calculator.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// IMPORTS</span>
<span class="c1">// =======</span>

<span class="kd">import</span> <span class="kt">Foundation</span>

<span class="c1">// FUNCTIONS</span>
<span class="c1">// =========</span>

<span class="kd">func</span> <span class="nf">askQuestion</span><span class="p">()</span> <span class="p">{</span>
    <span class="nf">print</span><span class="p">(</span><span class="s">"Your calculation: "</span><span class="p">,</span> <span class="nv">terminator</span><span class="p">:</span> <span class="s">""</span><span class="p">)</span>
    <span class="k">guard</span> <span class="k">let</span> <span class="nv">calculation</span> <span class="o">=</span> <span class="nf">readLine</span><span class="p">()</span> <span class="k">else</span> <span class="p">{</span> <span class="k">return</span> <span class="p">}</span>
    <span class="k">let</span> <span class="nv">result</span> <span class="o">=</span> <span class="nf">getResult</span><span class="p">(</span><span class="n">calculation</span><span class="p">)</span>
    <span class="nf">print</span><span class="p">(</span><span class="s">" = </span><span class="se">\(</span><span class="n">result</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">getResult</span><span class="p">(</span><span class="n">_</span> <span class="nv">calculation</span><span class="p">:</span> <span class="kt">String</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kt">String</span> <span class="p">{</span>
    <span class="k">let</span> <span class="nv">sanitized</span> <span class="o">=</span> <span class="nf">sanitizeCalculation</span><span class="p">(</span><span class="n">calculation</span><span class="p">)</span>
    <span class="k">var</span> <span class="nv">result</span> <span class="o">=</span> <span class="mf">0.0</span>

    <span class="k">for</span> <span class="n">i</span> <span class="k">in</span> <span class="n">sanitized</span><span class="o">.</span><span class="nf">split</span><span class="p">(</span><span class="nv">separator</span><span class="p">:</span> <span class="s">"+"</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">var</span> <span class="nv">subResult</span> <span class="o">=</span> <span class="mf">1.0</span>
        <span class="k">for</span> <span class="n">j</span> <span class="k">in</span> <span class="n">i</span><span class="o">.</span><span class="nf">split</span><span class="p">(</span><span class="nv">separator</span><span class="p">:</span> <span class="s">"*"</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">if</span> <span class="n">j</span><span class="o">.</span><span class="nf">hasPrefix</span><span class="p">(</span><span class="s">"1/"</span><span class="p">)</span> <span class="p">{</span>
                <span class="k">let</span> <span class="nv">sanitizedJ</span> <span class="o">=</span> <span class="n">j</span><span class="o">.</span><span class="nf">replacingOccurrences</span><span class="p">(</span><span class="nv">of</span><span class="p">:</span> <span class="s">"1/"</span><span class="p">,</span> <span class="nv">with</span><span class="p">:</span> <span class="s">""</span><span class="p">)</span>
                <span class="k">guard</span> <span class="k">let</span> <span class="nv">value</span> <span class="o">=</span> <span class="kt">Double</span><span class="p">(</span><span class="n">sanitizedJ</span><span class="p">)</span> <span class="k">else</span> <span class="p">{</span> <span class="k">continue</span> <span class="p">}</span>
                <span class="k">if</span> <span class="n">value</span> <span class="o">==</span> <span class="mi">0</span> <span class="p">{</span> <span class="k">return</span> <span class="s">"Undefined"</span> <span class="p">}</span>
                <span class="n">subResult</span> <span class="o">/=</span> <span class="n">value</span>
            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                <span class="k">guard</span> <span class="k">let</span> <span class="nv">value</span> <span class="o">=</span> <span class="kt">Double</span><span class="p">(</span><span class="n">j</span><span class="p">)</span> <span class="k">else</span> <span class="p">{</span> <span class="k">continue</span> <span class="p">}</span>
                <span class="n">subResult</span> <span class="o">*=</span> <span class="n">value</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="n">result</span> <span class="o">+=</span> <span class="n">subResult</span>
    <span class="p">}</span>

    <span class="k">if</span> <span class="n">result</span> <span class="o">==</span> <span class="kt">Double</span><span class="p">(</span><span class="kt">Int</span><span class="p">(</span><span class="n">result</span><span class="p">))</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">calculation</span><span class="o">.</span><span class="nf">contains</span><span class="p">(</span><span class="s">"/"</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">calculation</span><span class="o">.</span><span class="nf">contains</span><span class="p">(</span><span class="s">"."</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="kt">String</span><span class="p">(</span><span class="kt">Int</span><span class="p">(</span><span class="n">result</span><span class="p">))</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="kt">String</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">sanitizeCalculation</span><span class="p">(</span><span class="n">_</span> <span class="nv">calculation</span><span class="p">:</span> <span class="kt">String</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kt">String</span> <span class="p">{</span>
    <span class="k">return</span> <span class="n">calculation</span>
        <span class="o">.</span><span class="nf">replacing</span><span class="p">(</span><span class="err">#</span><span class="o">/</span><span class="p">\</span><span class="n">s</span><span class="o">+/</span><span class="err">#</span><span class="p">,</span> <span class="nv">with</span><span class="p">:</span> <span class="s">""</span><span class="p">)</span>                                     <span class="c1">// Remove all spaces</span>
        <span class="o">.</span><span class="nf">replacing</span><span class="p">(</span><span class="err">#</span><span class="o">/</span><span class="p">\</span><span class="o">++/</span><span class="err">#</span><span class="p">,</span> <span class="nv">with</span><span class="p">:</span> <span class="s">"+"</span><span class="p">)</span>                                    <span class="c1">// ++ -&gt; +</span>
        <span class="o">.</span><span class="nf">replacing</span><span class="p">(</span><span class="err">#</span><span class="o">/-+/</span><span class="err">#</span><span class="p">,</span> <span class="nv">with</span><span class="p">:</span> <span class="s">"-"</span><span class="p">)</span>                                     <span class="c1">// -- -&gt; -</span>
        <span class="o">.</span><span class="nf">replacing</span><span class="p">(</span><span class="err">#</span><span class="o">/</span><span class="p">\</span><span class="o">*</span><span class="p">\</span><span class="o">+/</span><span class="err">#</span><span class="p">,</span> <span class="nv">with</span><span class="p">:</span> <span class="s">"*"</span><span class="p">)</span>                                   <span class="c1">// *+ -&gt; *</span>
        <span class="o">.</span><span class="nf">replacing</span><span class="p">(</span><span class="err">#</span><span class="c1">//\+/#, with: "/")                                   // /+ -&gt; /</span>
        <span class="o">.</span><span class="nf">replacing</span><span class="p">(</span><span class="err">#</span><span class="o">/</span><span class="p">\</span><span class="o">+-/</span><span class="err">#</span><span class="p">,</span> <span class="nv">with</span><span class="p">:</span> <span class="s">"-"</span><span class="p">)</span>                                    <span class="c1">// +- -&gt; -</span>
        <span class="o">.</span><span class="nf">replacing</span><span class="p">(</span><span class="err">#</span><span class="o">/</span><span class="p">(\</span><span class="n">d</span><span class="p">)</span><span class="o">-</span><span class="p">(\</span><span class="n">d</span><span class="p">)</span><span class="o">/</span><span class="err">#</span><span class="p">)</span> <span class="p">{</span> <span class="n">match</span> <span class="k">in</span> <span class="s">"</span><span class="se">\(</span><span class="n">match</span><span class="o">.</span><span class="mi">1</span><span class="se">)</span><span class="s">+-</span><span class="se">\(</span><span class="n">match</span><span class="o">.</span><span class="mi">2</span><span class="se">)</span><span class="s">"</span> <span class="p">}</span>   <span class="c1">// a-b -&gt; a+-b</span>
        <span class="o">.</span><span class="nf">replacing</span><span class="p">(</span><span class="err">#</span><span class="c1">///#, with: "*1/")                                   // a/b -&gt; a*1/b</span>
<span class="p">}</span>

<span class="c1">// MAIN</span>
<span class="c1">// ====</span>

<span class="k">let</span> <span class="nv">file</span> <span class="o">=</span> <span class="kt">URL</span><span class="p">(</span><span class="nv">fileURLWithPath</span><span class="p">:</span> <span class="kd">#file</span><span class="p">)</span><span class="o">.</span><span class="n">lastPathComponent</span>
<span class="k">let</span> <span class="nv">isCalculator</span> <span class="o">=</span> <span class="kt">CommandLine</span><span class="o">.</span><span class="n">arguments</span><span class="o">.</span><span class="n">first</span><span class="o">.</span><span class="n">map</span> <span class="p">{</span> <span class="kt">URL</span><span class="p">(</span><span class="nv">fileURLWithPath</span><span class="p">:</span> <span class="nv">$0</span><span class="p">)</span><span class="o">.</span><span class="n">lastPathComponent</span> <span class="o">==</span> <span class="n">file</span> <span class="p">}</span> <span class="p">??</span> <span class="kc">false</span>
<span class="k">let</span> <span class="nv">isRunningTests</span> <span class="o">=</span> <span class="kt">CommandLine</span><span class="o">.</span><span class="n">arguments</span><span class="o">.</span><span class="nf">contains</span><span class="p">(</span><span class="nv">where</span><span class="p">:</span> <span class="p">{</span> <span class="nv">$0</span><span class="o">.</span><span class="nf">hasSuffix</span><span class="p">(</span><span class="s">"tests.swift"</span><span class="p">)</span> <span class="p">})</span>
<span class="k">if</span> <span class="n">isCalculator</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">isRunningTests</span> <span class="p">{</span>
    <span class="nf">askQuestion</span><span class="p">()</span>
<span class="p">}</span>
</code></pre></div></div>

<p>tests.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// IMPORTS</span>
<span class="c1">// =======</span>

<span class="kd">import</span> <span class="kt">Foundation</span>

<span class="c1">// FUNCTIONS</span>
<span class="c1">// =========</span>

<span class="kd">func</span> <span class="nf">runTests</span><span class="p">()</span> <span class="p">{</span>
    <span class="nf">print</span><span class="p">(</span><span class="s">"Test 01: </span><span class="se">\(</span><span class="nf">getResult</span><span class="p">(</span><span class="s">"2 + 3"</span><span class="p">)</span> <span class="o">==</span> <span class="s">"</span><span class="se">\(</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">3</span><span class="se">)</span><span class="s">"</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
    <span class="nf">print</span><span class="p">(</span><span class="s">"Test 02: </span><span class="se">\(</span><span class="nf">getResult</span><span class="p">(</span><span class="s">"2 - 3"</span><span class="p">)</span> <span class="o">==</span> <span class="s">"</span><span class="se">\(</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">3</span><span class="se">)</span><span class="s">"</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
    <span class="nf">print</span><span class="p">(</span><span class="s">"Test 03: </span><span class="se">\(</span><span class="nf">getResult</span><span class="p">(</span><span class="s">"2 * 3"</span><span class="p">)</span> <span class="o">==</span> <span class="s">"</span><span class="se">\(</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span><span class="se">)</span><span class="s">"</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
    <span class="nf">print</span><span class="p">(</span><span class="s">"Test 04: </span><span class="se">\(</span><span class="nf">getResult</span><span class="p">(</span><span class="s">"2 / 3"</span><span class="p">)</span> <span class="o">==</span> <span class="s">"</span><span class="se">\(</span><span class="mf">2.0</span> <span class="o">/</span> <span class="mf">3.0</span><span class="se">)</span><span class="s">"</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
    <span class="nf">print</span><span class="p">(</span><span class="s">"Test 05: </span><span class="se">\(</span><span class="nf">getResult</span><span class="p">(</span><span class="s">"2 / 0"</span><span class="p">)</span> <span class="o">==</span> <span class="s">"Undefined"</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
    <span class="nf">print</span><span class="p">(</span><span class="s">"Test 06: </span><span class="se">\(</span><span class="nf">getResult</span><span class="p">(</span><span class="s">"  7 +   2 * 3 - 4 / -2 "</span><span class="p">)</span> <span class="o">==</span> <span class="s">"</span><span class="se">\(</span>  <span class="mi">7</span> <span class="o">+</span>   <span class="mf">2.0</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">/</span> <span class="o">-</span><span class="mi">2</span> <span class="se">)</span><span class="s">"</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
    <span class="nf">print</span><span class="p">(</span><span class="s">"Test 07: </span><span class="se">\(</span><span class="nf">getResult</span><span class="p">(</span><span class="s">"  7 +   2 / 3 - 4 * +-2 "</span><span class="p">)</span> <span class="o">==</span> <span class="s">"</span><span class="se">\(</span>  <span class="mi">7</span> <span class="o">+</span>   <span class="mf">2.0</span> <span class="o">/</span> <span class="mi">3</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">-</span><span class="mi">2</span> <span class="se">)</span><span class="s">"</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
    <span class="nf">print</span><span class="p">(</span><span class="s">"Test 08: </span><span class="se">\(</span><span class="nf">getResult</span><span class="p">(</span><span class="s">"2.0 + 3.0"</span><span class="p">)</span> <span class="o">==</span> <span class="s">"</span><span class="se">\(</span><span class="mf">2.0</span> <span class="o">+</span> <span class="mf">3.0</span><span class="se">)</span><span class="s">"</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
<span class="p">}</span>

<span class="c1">// MAIN</span>
<span class="c1">// ====</span>

<span class="nf">runTests</span><span class="p">()</span>
</code></pre></div></div>

<h2 id="r">R</h2>

<p>I had never fully understood the extent or power of R. I only learnt to use it for complex calculations, but the language is very capable outside of that.</p>

<p>One confusing thing I stumbled upon is the <code class="language-plaintext highlighter-rouge">readline()</code> function that only works reliably in interactive sessions. So I instead used <code class="language-plaintext highlighter-rouge">readLines</code> on <code class="language-plaintext highlighter-rouge">stdin</code>, which makes it very explicit.</p>

<p>There also seems to be something going on between R and Perl. In fact, the function used to split strings has a parameter called <code class="language-plaintext highlighter-rouge">perl</code>. This intrigued me, so I looked into it, and it turns out that the function uses PCRE, Perl-Compatible Regular Expression Engine.</p>

<p>I’d also like to shed light on the default file extension: an uppercase R. Some systems are case-sensitive, and usually all extensions are in lowercase, so it’s an interesting and weird choice there.</p>

<p>calculator.R:</p>
<div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># FUNCTIONS</span><span class="w">
</span><span class="c1"># =========</span><span class="w">

</span><span class="n">ask_question</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="k">function</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="n">cat</span><span class="p">(</span><span class="s2">"Your calculation: "</span><span class="p">)</span><span class="w">
    </span><span class="n">calculation</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">readLines</span><span class="p">(</span><span class="n">con</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"stdin"</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">1</span><span class="p">)</span><span class="w">
    </span><span class="n">result</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">get_result</span><span class="p">(</span><span class="n">calculation</span><span class="p">)</span><span class="w">
    </span><span class="n">cat</span><span class="p">(</span><span class="s2">" = "</span><span class="p">,</span><span class="w"> </span><span class="n">result</span><span class="p">,</span><span class="w"> </span><span class="s2">"\n"</span><span class="p">,</span><span class="w"> </span><span class="n">sep</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span><span class="p">)</span><span class="w">
</span><span class="p">}</span><span class="w">

</span><span class="n">get_result</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="k">function</span><span class="p">(</span><span class="n">calculation</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="n">calculation</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">sanitize_calculation</span><span class="p">(</span><span class="n">calculation</span><span class="p">)</span><span class="w">
    </span><span class="n">result</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="m">0.0</span><span class="w">

    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">strsplit</span><span class="p">(</span><span class="n">calculation</span><span class="p">,</span><span class="w"> </span><span class="s2">"\\+"</span><span class="p">,</span><span class="w"> </span><span class="n">perl</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">TRUE</span><span class="p">)[[</span><span class="m">1</span><span class="p">]])</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="n">sub_result</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="m">1.0</span><span class="w">
        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">j</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">strsplit</span><span class="p">(</span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="s2">"\\*"</span><span class="p">,</span><span class="w"> </span><span class="n">perl</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">TRUE</span><span class="p">)[[</span><span class="m">1</span><span class="p">]])</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">grepl</span><span class="p">(</span><span class="s2">"^1/"</span><span class="p">,</span><span class="w"> </span><span class="n">j</span><span class="p">))</span><span class="w"> </span><span class="p">{</span><span class="w">
                </span><span class="n">sanitized_j</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">sub</span><span class="p">(</span><span class="s2">"^1/"</span><span class="p">,</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w"> </span><span class="n">j</span><span class="p">)</span><span class="w">
                </span><span class="n">value</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nf">as.numeric</span><span class="p">(</span><span class="n">sanitized_j</span><span class="p">)</span><span class="w">
                </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nf">as.numeric</span><span class="p">(</span><span class="n">sanitized_j</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="m">0</span><span class="p">)</span><span class="w"> </span><span class="nf">return</span><span class="p">(</span><span class="s2">"Undefined"</span><span class="p">)</span><span class="w">
                </span><span class="n">sub_result</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">sub_result</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nf">as.numeric</span><span class="p">(</span><span class="n">sanitized_j</span><span class="p">)</span><span class="w">
            </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w">
                </span><span class="n">sub_result</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">sub_result</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nf">as.numeric</span><span class="p">(</span><span class="n">j</span><span class="p">)</span><span class="w">
            </span><span class="p">}</span><span class="w">
        </span><span class="p">}</span><span class="w">
        </span><span class="n">result</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">sub_result</span><span class="w">
    </span><span class="p">}</span><span class="w">

    </span><span class="nf">as.character</span><span class="p">(</span><span class="n">result</span><span class="p">)</span><span class="w">
</span><span class="p">}</span><span class="w">

</span><span class="n">sanitize_calculation</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="k">function</span><span class="p">(</span><span class="n">calculation</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="n">calculation</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">gsub</span><span class="p">(</span><span class="s2">"\\s+"</span><span class="p">,</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w"> </span><span class="n">calculation</span><span class="p">)</span><span class="w">                </span><span class="c1"># Remove all spaces</span><span class="w">
    </span><span class="n">calculation</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">gsub</span><span class="p">(</span><span class="s2">"\\++"</span><span class="p">,</span><span class="w"> </span><span class="s2">"+"</span><span class="p">,</span><span class="w"> </span><span class="n">calculation</span><span class="p">)</span><span class="w">               </span><span class="c1"># ++ -&gt; +</span><span class="w">
    </span><span class="n">calculation</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">gsub</span><span class="p">(</span><span class="s2">"-+"</span><span class="p">,</span><span class="w"> </span><span class="s2">"-"</span><span class="p">,</span><span class="w"> </span><span class="n">calculation</span><span class="p">)</span><span class="w">                 </span><span class="c1"># -- -&gt; -</span><span class="w">
    </span><span class="n">calculation</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">gsub</span><span class="p">(</span><span class="s2">"\\*\\+"</span><span class="p">,</span><span class="w"> </span><span class="s2">"*"</span><span class="p">,</span><span class="w"> </span><span class="n">calculation</span><span class="p">)</span><span class="w">             </span><span class="c1"># *+ -&gt; *</span><span class="w">
    </span><span class="n">calculation</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">gsub</span><span class="p">(</span><span class="s2">"/\\+"</span><span class="p">,</span><span class="w"> </span><span class="s2">"/"</span><span class="p">,</span><span class="w"> </span><span class="n">calculation</span><span class="p">)</span><span class="w">               </span><span class="c1"># /+ -&gt; /</span><span class="w">
    </span><span class="n">calculation</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">gsub</span><span class="p">(</span><span class="s2">"\\+-"</span><span class="p">,</span><span class="w"> </span><span class="s2">"-"</span><span class="p">,</span><span class="w"> </span><span class="n">calculation</span><span class="p">)</span><span class="w">               </span><span class="c1"># +- -&gt; -</span><span class="w">
    </span><span class="n">calculation</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">gsub</span><span class="p">(</span><span class="s2">"(\\d)-(\\d)"</span><span class="p">,</span><span class="w"> </span><span class="s2">"\\1+-\\2"</span><span class="p">,</span><span class="w"> </span><span class="n">calculation</span><span class="p">)</span><span class="w"> </span><span class="c1"># a-b -&gt; a+-b</span><span class="w">
    </span><span class="n">calculation</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">gsub</span><span class="p">(</span><span class="s2">"/"</span><span class="p">,</span><span class="w"> </span><span class="s2">"*1/"</span><span class="p">,</span><span class="w"> </span><span class="n">calculation</span><span class="p">)</span><span class="w">                </span><span class="c1"># a/b -&gt; a*1/b</span><span class="w">
    </span><span class="n">calculation</span><span class="w">
</span><span class="p">}</span><span class="w">

</span><span class="c1"># MAIN</span><span class="w">
</span><span class="c1"># ====</span><span class="w">

</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">identical</span><span class="p">(</span><span class="n">sys.nframe</span><span class="p">(),</span><span class="w"> </span><span class="m">0L</span><span class="p">))</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="n">ask_question</span><span class="p">()</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>tests.R:</p>
<div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># IMPORTS</span><span class="w">
</span><span class="c1"># =======</span><span class="w">

</span><span class="n">source</span><span class="p">(</span><span class="s2">"calculator.R"</span><span class="p">)</span><span class="w">

</span><span class="c1"># FUNCTIONS</span><span class="w">
</span><span class="c1"># =========</span><span class="w">

</span><span class="n">run_tests</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="k">function</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
  </span><span class="n">cat</span><span class="p">(</span><span class="s2">"Test 01: "</span><span class="p">,</span><span class="w"> </span><span class="n">get_result</span><span class="p">(</span><span class="s2">"2 + 3"</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nf">as.character</span><span class="p">(</span><span class="m">2</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="m">3</span><span class="p">),</span><span class="w"> </span><span class="s2">"\n"</span><span class="p">,</span><span class="w"> </span><span class="n">sep</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span><span class="p">)</span><span class="w">
  </span><span class="n">cat</span><span class="p">(</span><span class="s2">"Test 02: "</span><span class="p">,</span><span class="w"> </span><span class="n">get_result</span><span class="p">(</span><span class="s2">"2 - 3"</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nf">as.character</span><span class="p">(</span><span class="m">2</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">3</span><span class="p">),</span><span class="w"> </span><span class="s2">"\n"</span><span class="p">,</span><span class="w"> </span><span class="n">sep</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span><span class="p">)</span><span class="w">
  </span><span class="n">cat</span><span class="p">(</span><span class="s2">"Test 03: "</span><span class="p">,</span><span class="w"> </span><span class="n">get_result</span><span class="p">(</span><span class="s2">"2 * 3"</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nf">as.character</span><span class="p">(</span><span class="m">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="m">3</span><span class="p">),</span><span class="w"> </span><span class="s2">"\n"</span><span class="p">,</span><span class="w"> </span><span class="n">sep</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span><span class="p">)</span><span class="w">
  </span><span class="n">cat</span><span class="p">(</span><span class="s2">"Test 04: "</span><span class="p">,</span><span class="w"> </span><span class="n">get_result</span><span class="p">(</span><span class="s2">"2 / 3"</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nf">as.character</span><span class="p">(</span><span class="m">2</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="m">3</span><span class="p">),</span><span class="w"> </span><span class="s2">"\n"</span><span class="p">,</span><span class="w"> </span><span class="n">sep</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span><span class="p">)</span><span class="w">
  </span><span class="n">cat</span><span class="p">(</span><span class="s2">"Test 05: "</span><span class="p">,</span><span class="w"> </span><span class="n">get_result</span><span class="p">(</span><span class="s2">"2 / 0"</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="s2">"Undefined"</span><span class="p">,</span><span class="w"> </span><span class="s2">"\n"</span><span class="p">,</span><span class="w"> </span><span class="n">sep</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span><span class="p">)</span><span class="w">
  </span><span class="n">cat</span><span class="p">(</span><span class="s2">"Test 06: "</span><span class="p">,</span><span class="w"> </span><span class="n">get_result</span><span class="p">(</span><span class="s2">"  7 +   2 * 3 - 4 / -2 "</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nf">as.character</span><span class="p">(</span><span class="w">  </span><span class="m">7</span><span class="w"> </span><span class="o">+</span><span class="w">   </span><span class="m">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="m">3</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">4</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="m">-2</span><span class="w"> </span><span class="p">),</span><span class="w"> </span><span class="s2">"\n"</span><span class="p">,</span><span class="w"> </span><span class="n">sep</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span><span class="p">)</span><span class="w">
  </span><span class="n">cat</span><span class="p">(</span><span class="s2">"Test 07: "</span><span class="p">,</span><span class="w"> </span><span class="n">get_result</span><span class="p">(</span><span class="s2">"  7 +   2 / 3 - 4 * +-2 "</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nf">as.character</span><span class="p">(</span><span class="w">  </span><span class="m">7</span><span class="w"> </span><span class="o">+</span><span class="w">   </span><span class="m">2</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="m">3</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">4</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">+</span><span class="m">-2</span><span class="w"> </span><span class="p">),</span><span class="w"> </span><span class="s2">"\n"</span><span class="p">,</span><span class="w"> </span><span class="n">sep</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span><span class="p">)</span><span class="w">
  </span><span class="n">cat</span><span class="p">(</span><span class="s2">"Test 08: "</span><span class="p">,</span><span class="w"> </span><span class="n">get_result</span><span class="p">(</span><span class="s2">"2.0 + 3.0"</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nf">as.character</span><span class="p">(</span><span class="m">2.0</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="m">3.0</span><span class="p">),</span><span class="w"> </span><span class="s2">"\n"</span><span class="p">,</span><span class="w"> </span><span class="n">sep</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span><span class="p">)</span><span class="w">
</span><span class="p">}</span><span class="w">

</span><span class="c1"># MAIN</span><span class="w">
</span><span class="c1"># ====</span><span class="w">

</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">identical</span><span class="p">(</span><span class="n">sys.nframe</span><span class="p">(),</span><span class="w"> </span><span class="m">0L</span><span class="p">))</span><span class="w"> </span><span class="p">{</span><span class="w">
  </span><span class="n">run_tests</span><span class="p">()</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<h2 id="groovy">Groovy</h2>

<p>Let’s end with some grooooove! First time hearing about it, turns out that Groovy is a Java-syntax-compatible language (basically sugar-coated Java). It was immediately clear when I saw the use of <code class="language-plaintext highlighter-rouge">System.out</code>, typical in Java. And next to that, new functions like <code class="language-plaintext highlighter-rouge">print</code> and <code class="language-plaintext highlighter-rouge">println</code>. I also succeeded in using methods outside of a class, unlike with Java. All in all, it’s not the most modern of languages or syntaxes, but it definitely does the job.</p>

<p>If you’re wondering why it isn’t as much or more popular than Java, like TypeScript is with JavaScript, it’s somewhat due to Kotlin, another Java language. Other languages include Scala, and all this fraction dilutes the numbers for each language. Besides, Java is also a fast-evolving language, contrary to common belief, and modern Java incorporates some of the features that made Groovy compelling in the past.</p>

<p>calculator.groovy:</p>
<div class="language-groovy highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// IMPORTS</span>
<span class="c1">// =======</span>

<span class="kn">import</span> <span class="nn">java.io.BufferedReader</span>
<span class="kn">import</span> <span class="nn">java.io.InputStreamReader</span>

<span class="c1">// FUNCTIONS</span>
<span class="c1">// =========</span>

<span class="kt">void</span> <span class="nf">askQuestion</span><span class="o">()</span> <span class="o">{</span>
    <span class="n">print</span> <span class="s2">"Your calculation: "</span>
    <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">flush</span><span class="o">()</span>
    <span class="n">BufferedReader</span> <span class="n">reader</span> <span class="o">=</span> <span class="n">System</span><span class="o">.</span><span class="na">in</span><span class="o">.</span><span class="na">newReader</span><span class="o">()</span>
    <span class="n">String</span> <span class="n">calculation</span> <span class="o">=</span> <span class="n">reader</span><span class="o">.</span><span class="na">readLine</span><span class="o">()</span>
    <span class="n">String</span> <span class="n">result</span> <span class="o">=</span> <span class="n">getResult</span><span class="o">(</span><span class="n">calculation</span><span class="o">)</span>
    <span class="n">println</span> <span class="s2">" = ${result}"</span>
<span class="o">}</span>

<span class="n">String</span> <span class="nf">getResult</span><span class="o">(</span><span class="n">String</span> <span class="n">calculation</span><span class="o">)</span> <span class="o">{</span>
    <span class="n">calculation</span> <span class="o">=</span> <span class="n">sanitizeCalculation</span><span class="o">(</span><span class="n">calculation</span><span class="o">)</span>
    <span class="kt">double</span> <span class="n">result</span> <span class="o">=</span> <span class="mf">0.0d</span>

    <span class="k">for</span> <span class="o">(</span><span class="n">String</span> <span class="n">i</span> <span class="o">:</span> <span class="n">calculation</span><span class="o">.</span><span class="na">split</span><span class="o">(</span><span class="s2">"\\+"</span><span class="o">))</span> <span class="o">{</span>
        <span class="kt">double</span> <span class="n">subResult</span> <span class="o">=</span> <span class="mf">1.0d</span>
        <span class="k">for</span> <span class="o">(</span><span class="n">String</span> <span class="n">j</span> <span class="o">:</span> <span class="n">i</span><span class="o">.</span><span class="na">split</span><span class="o">(</span><span class="s2">"\\*"</span><span class="o">))</span> <span class="o">{</span>
            <span class="k">if</span> <span class="o">(</span><span class="n">j</span><span class="o">.</span><span class="na">startsWith</span><span class="o">(</span><span class="s2">"1/"</span><span class="o">))</span> <span class="o">{</span>
                <span class="n">String</span> <span class="n">sanitizedJ</span> <span class="o">=</span> <span class="n">j</span><span class="o">.</span><span class="na">replaceFirst</span><span class="o">(</span><span class="s2">"1/"</span><span class="o">,</span> <span class="s2">""</span><span class="o">)</span>
                <span class="k">if</span> <span class="o">(!</span><span class="n">sanitizedJ</span><span class="o">.</span><span class="na">isNumber</span><span class="o">())</span> <span class="k">return</span> <span class="s2">"Undefined"</span>
                <span class="k">if</span> <span class="o">(</span><span class="n">sanitizedJ</span><span class="o">.</span><span class="na">toDouble</span><span class="o">()</span> <span class="o">==</span> <span class="mf">0.0d</span><span class="o">)</span> <span class="k">return</span> <span class="s2">"Undefined"</span>
                <span class="n">subResult</span> <span class="o">/=</span> <span class="n">sanitizedJ</span><span class="o">.</span><span class="na">toDouble</span><span class="o">()</span>
            <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
                <span class="n">subResult</span> <span class="o">*=</span> <span class="n">j</span><span class="o">.</span><span class="na">toDouble</span><span class="o">()</span>
            <span class="o">}</span>
        <span class="o">}</span>
        <span class="n">result</span> <span class="o">+=</span> <span class="n">subResult</span>
    <span class="o">}</span>

    <span class="k">if</span> <span class="o">(</span><span class="n">result</span> <span class="o">==</span> <span class="n">result</span><span class="o">.</span><span class="na">toLong</span><span class="o">()</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">calculation</span><span class="o">.</span><span class="na">contains</span><span class="o">(</span><span class="s2">"."</span><span class="o">))</span> <span class="o">{</span>
        <span class="k">return</span> <span class="s2">"${result.toLong()}"</span>
    <span class="o">}</span>
    <span class="k">return</span> <span class="s2">"${result.round(10)}"</span>
<span class="o">}</span>

<span class="n">String</span> <span class="nf">sanitizeCalculation</span><span class="o">(</span><span class="n">String</span> <span class="n">calculation</span><span class="o">)</span> <span class="o">{</span>
    <span class="n">calculation</span>
        <span class="o">.</span><span class="na">replaceAll</span><span class="o">(</span><span class="s1">'\\s+'</span><span class="o">,</span> <span class="s1">''</span><span class="o">)</span>                 <span class="c1">// Remove all spaces</span>
        <span class="o">.</span><span class="na">replaceAll</span><span class="o">(</span><span class="s1">'\\++'</span><span class="o">,</span> <span class="s1">'+'</span><span class="o">)</span>                <span class="c1">// ++ -&gt; +</span>
        <span class="o">.</span><span class="na">replaceAll</span><span class="o">(</span><span class="s1">'-+'</span><span class="o">,</span> <span class="s1">'-'</span><span class="o">)</span>                  <span class="c1">// -- -&gt; -</span>
        <span class="o">.</span><span class="na">replaceAll</span><span class="o">(</span><span class="s1">'\\*\\+'</span><span class="o">,</span> <span class="s1">'*'</span><span class="o">)</span>              <span class="c1">// *+ -&gt; *</span>
        <span class="o">.</span><span class="na">replaceAll</span><span class="o">(</span><span class="s1">'/\\+'</span><span class="o">,</span> <span class="s1">'/'</span><span class="o">)</span>                <span class="c1">// /+ -&gt; /</span>
        <span class="o">.</span><span class="na">replaceAll</span><span class="o">(</span><span class="s1">'\\+-'</span><span class="o">,</span> <span class="s1">'-'</span><span class="o">)</span>                <span class="c1">// +- -&gt; -</span>
        <span class="o">.</span><span class="na">replaceAll</span><span class="o">(</span><span class="s1">'(\\d)-(\\d)'</span><span class="o">,</span> <span class="s1">'$1+-$2'</span><span class="o">)</span>    <span class="c1">// a-b -&gt; a+-b</span>
        <span class="o">.</span><span class="na">replaceAll</span><span class="o">(</span><span class="s1">'/'</span><span class="o">,</span> <span class="s1">'*1/'</span><span class="o">)</span>                 <span class="c1">// a/b -&gt; a*1/b</span>
<span class="o">}</span>

<span class="c1">// MAIN</span>
<span class="c1">// ====</span>

<span class="k">if</span> <span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">class</span><span class="o">.</span><span class="na">name</span> <span class="o">==</span> <span class="s1">'calculator'</span><span class="o">)</span> <span class="o">{</span>
    <span class="n">askQuestion</span><span class="o">()</span>
<span class="o">}</span>
</code></pre></div></div>

<p>tests.groovy:</p>
<div class="language-groovy highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// IMPORTS</span>
<span class="c1">// =======</span>

<span class="kn">import</span> <span class="nn">groovy.transform.Field</span>

<span class="c1">// VARIABLES</span>
<span class="c1">// =========</span>

<span class="nd">@Field</span>
<span class="kt">def</span> <span class="n">calc</span> <span class="o">=</span> <span class="k">new</span> <span class="n">GroovyShell</span><span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">class</span><span class="o">.</span><span class="na">classLoader</span><span class="o">).</span><span class="na">parse</span><span class="o">(</span><span class="k">new</span> <span class="n">File</span><span class="o">(</span><span class="s2">"calculator.groovy"</span><span class="o">))</span>

<span class="c1">// FUNCTIONS</span>
<span class="c1">// =========</span>

<span class="kt">void</span> <span class="nf">runTests</span><span class="o">()</span> <span class="o">{</span>
    <span class="n">println</span> <span class="s2">"Test 01: ${calc.getResult("</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">3</span><span class="s2">") == "</span><span class="n">$</span><span class="o">{</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">3</span><span class="o">}</span><span class="s2">"}"</span>
    <span class="n">println</span> <span class="s2">"Test 02: ${calc.getResult("</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">3</span><span class="s2">") == "</span><span class="n">$</span><span class="o">{</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">3</span><span class="o">}</span><span class="s2">"}"</span>
    <span class="n">println</span> <span class="s2">"Test 03: ${calc.getResult("</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span><span class="s2">") == "</span><span class="n">$</span><span class="o">{</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span><span class="o">}</span><span class="s2">"}"</span>
    <span class="n">println</span> <span class="s2">"Test 04: ${calc.getResult("</span><span class="mi">2</span> <span class="s">/ 3") == "${2 /</span> <span class="mi">3</span><span class="o">}</span><span class="s2">"}"</span>
    <span class="n">println</span> <span class="s2">"Test 05: ${calc.getResult("</span><span class="mi">2</span> <span class="o">/</span> <span class="mi">0</span><span class="s2">") == "</span><span class="n">Undefined</span><span class="s2">"}"</span>
    <span class="n">println</span> <span class="s2">"Test 06: ${calc.getResult("</span>  <span class="mi">7</span> <span class="o">+</span>   <span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">-</span> <span class="mi">4</span> <span class="s">/ -2 ") == "${  7 +   2 * 3 - 4 /</span> <span class="o">-</span><span class="mi">2</span> <span class="o">}</span><span class="s2">"}"</span>
    <span class="n">println</span> <span class="s2">"Test 07: ${calc.getResult("</span>  <span class="mi">7</span> <span class="o">+</span>   <span class="mi">2</span> <span class="s">/ 3 - 4 * +-2 ") == "${  7 +   2 /</span> <span class="mi">3</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">+-</span><span class="mi">2</span> <span class="o">}</span><span class="s2">"}"</span>
    <span class="n">println</span> <span class="s2">"Test 08: ${calc.getResult("</span><span class="mf">2.0</span> <span class="o">+</span> <span class="mf">3.0</span><span class="s2">") == "</span><span class="n">$</span><span class="o">{</span><span class="mf">2.0</span> <span class="o">+</span> <span class="mf">3.0</span><span class="o">}</span><span class="s2">"}"</span>
<span class="o">}</span>

<span class="c1">// MAIN</span>
<span class="c1">// ====</span>

<span class="k">if</span> <span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">class</span><span class="o">.</span><span class="na">name</span> <span class="o">==</span> <span class="s1">'tests'</span><span class="o">)</span> <span class="o">{</span>
    <span class="n">runTests</span><span class="o">()</span>
<span class="o">}</span>
</code></pre></div></div>

<h2 id="conclusion">Conclusion</h2>

<p>I don’t really have a conclusion. I just did the challenge for what it is. I did learn, though, that the most popular languages are the more established ones, and that newer languages are starting to take over the lower half of the top 20. The web is also at full force, and even if I skipped HTML and CSS, it is undeniable that the rise of PWA (Progressive Web Apps) and technologies like Electron or React Native are becoming powerhouses for big corporations.</p>

<p>I shall also add that not all my tests are created equal. I’m comparing my calculator script to each language’s behavior, including floating precision and integer-decimal compatibility. There might also be some errors throughout the files, or things I missed, such as adding a <code class="language-plaintext highlighter-rouge">+</code> after <code class="language-plaintext highlighter-rouge">/d</code> in regular expressions.</p>

<p>All in all, coding is fun, you learn, and make mistakes. Choose the language that you want because it can probably do what you want it to do. If not, there’s a similar language that can probably do what you want it to do. If not, there’ll be a similar language that will do what you want it to do.</p>]]></content><author><name>Peter Yaacoub</name></author><category term="articles" /><category term="code-dome" /><summary type="html"><![CDATA[Introduction]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://yaacoub.github.io/social.webp" /><media:content medium="image" url="https://yaacoub.github.io/social.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">1 App, 20 Programming Languages (Part 1)</title><link href="https://yaacoub.github.io/articles/code-dome/1-app-20-programming-languages-part-1/" rel="alternate" type="text/html" title="1 App, 20 Programming Languages (Part 1)" /><published>2025-12-24T00:00:00+00:00</published><updated>2025-12-24T00:00:00+00:00</updated><id>https://yaacoub.github.io/articles/code-dome/1-app-20-programming-languages-part-1</id><content type="html" xml:base="https://yaacoub.github.io/articles/code-dome/1-app-20-programming-languages-part-1/"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>Similar to my previous article (<a href="https://yaacoub.github.io/articles/swift-tip/one-swiftui-app-six-architectures/">One SwiftUI App, Six Architectures</a>), this time I wanted to challenge myself in creating the same simple app in different programming languages.</p>

<p>To ensure this project is as fair as possible to all candidates and focuses solely on the code, rather than the result, I will turn to the console. Oh yes, that good old friend that rocked you or your parents at the dawn of the computer, just before any mainstream GUI ever hit homes and offices. Therefore, I won’t be using any UI frameworks and will try to resort to vanilla code only.</p>

<p>I’ll be skipping <a href="https://en.wikipedia.org/wiki/List_of_markup_languages">markup</a> (e.g., HTML), <a href="https://en.wikipedia.org/wiki/List_of_style_sheet_languages">stylesheet</a> (e.g., CSS), <a href="https://en.wikipedia.org/wiki/Category:Query_languages">query</a> (e.g., SQL), and <a href="https://en.wikipedia.org/wiki/Esoteric_programming_language">esoteric</a> languages (whatever this means). The following order of languages is from most to least popular, as given by Stack Overflow’s <a href="https://survey.stackoverflow.co/2025/technology">2025 Developer Survey</a>.</p>

<p>Okay, I think the introduction is long enough as it is, and I don’t want to waste any further time. So let’s get to make a calculator that handles simple arithmetic (+, -, *, /) with simple test cases. We’ll suppose that the user always writes valid operators and operands; why wouldn’t he? Remember, the focus of this article is not the final product, but the code. This is the polite way of saying that I couldn’t care less if the calculator wasn’t efficient or accurate, as long as it showcases each language’s core features. I do, however, implement and include unit tests in this article, although not extensively enough.</p>

<h2 id="javascript">JavaScript</h2>

<p>JavaScript, or JS (not to be confused with <a href="https://en.wikipedia.org/wiki/JScript">JScript</a>), is one of the three pillars of the web, and what a whopping <a href="https://w3techs.com/technologies/details/cp-javascript">98.9%</a> of websites rely on, thanks to frameworks like React and Angular. If you’re not too familiar with the language (strange…), you might think that it is only useful for the web, and I think that you’re absolutely right. JavaScript cannot work without a host. Most often, this host is the browser DOM, but in our case, we’ll use Node.js. Don’t be mistaken, JS, like many other languages, needs a host to run.</p>

<p>Fun fact! JavaScript is a: curly-bracket, embeddable, extension, impure functional, imperative, interactive-mode, interpreted, garbage-collected, application-macro, modular, multiparadigm, object-oriented, prototype-based, procedural, reflective query, scripting, and system language. Now that’s what I call an omnipotent language!</p>

<p>calculator.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// IMPORTS</span>
<span class="c1">// =======</span>

<span class="k">import</span> <span class="p">{</span> <span class="nx">createInterface</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">readline</span><span class="dl">"</span><span class="p">;</span>

<span class="c1">// FUNCTIONS</span>
<span class="c1">// =========</span>

<span class="kd">function</span> <span class="nx">askQuestion</span><span class="p">()</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">read</span> <span class="o">=</span> <span class="nx">createInterface</span><span class="p">({</span> <span class="na">input</span><span class="p">:</span> <span class="nx">process</span><span class="p">.</span><span class="nx">stdin</span><span class="p">,</span> <span class="na">output</span><span class="p">:</span> <span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span> <span class="p">});</span>
    <span class="nx">read</span><span class="p">.</span><span class="nx">question</span><span class="p">(</span><span class="dl">"</span><span class="s2">Your calculation: </span><span class="dl">"</span><span class="p">,</span> <span class="p">(</span><span class="nx">calculation</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="kd">const</span> <span class="nx">result</span> <span class="o">=</span> <span class="nx">getResult</span><span class="p">(</span><span class="nx">calculation</span><span class="p">);</span>
        <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">` = </span><span class="p">${</span><span class="nx">result</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
        <span class="nx">read</span><span class="p">.</span><span class="nx">close</span><span class="p">();</span>
    <span class="p">});</span>
<span class="p">}</span>

<span class="k">export</span> <span class="kd">function</span> <span class="nx">getResult</span><span class="p">(</span><span class="nx">calculation</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">calculation</span> <span class="o">=</span> <span class="nx">sanitizeCalculation</span><span class="p">(</span><span class="nx">calculation</span><span class="p">);</span>
    <span class="kd">let</span> <span class="nx">result</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span>
    
    <span class="k">for</span> <span class="p">(</span><span class="kd">const</span> <span class="nx">i</span> <span class="k">of</span> <span class="nx">calculation</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="dl">"</span><span class="s2">+</span><span class="dl">"</span><span class="p">))</span> <span class="p">{</span>
        <span class="kd">let</span> <span class="nx">subResult</span> <span class="o">=</span> <span class="mf">1.0</span><span class="p">;</span>
        <span class="k">for</span> <span class="p">(</span><span class="kd">const</span> <span class="nx">j</span> <span class="k">of</span> <span class="nx">i</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="dl">"</span><span class="s2">*</span><span class="dl">"</span><span class="p">))</span> <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="nx">j</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="dl">"</span><span class="s2">1/</span><span class="dl">"</span><span class="p">))</span> <span class="p">{</span>
                <span class="kd">let</span> <span class="nx">sanitizedJ</span> <span class="o">=</span> <span class="nx">j</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/1</span><span class="se">\/</span><span class="sr">/g</span><span class="p">,</span> <span class="dl">""</span><span class="p">);</span>
                <span class="k">if</span> <span class="p">(</span><span class="nb">parseFloat</span><span class="p">(</span><span class="nx">sanitizedJ</span><span class="p">)</span> <span class="o">===</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="dl">"</span><span class="s2">Undefined</span><span class="dl">"</span><span class="p">;</span>
                <span class="nx">subResult</span> <span class="o">/=</span> <span class="nb">parseFloat</span><span class="p">(</span><span class="nx">sanitizedJ</span><span class="p">);</span>
            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                <span class="nx">subResult</span> <span class="o">*=</span> <span class="nb">parseFloat</span><span class="p">(</span><span class="nx">j</span><span class="p">);</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="nx">result</span> <span class="o">+=</span> <span class="nx">subResult</span><span class="p">;</span>
    <span class="p">}</span>
    
    <span class="k">return</span> <span class="s2">`</span><span class="p">${</span><span class="nx">result</span><span class="p">}</span><span class="s2">`</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">function</span> <span class="nx">sanitizeCalculation</span><span class="p">(</span><span class="nx">calculation</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">calculation</span>
        <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\s</span><span class="sr">+/g</span><span class="p">,</span> <span class="dl">""</span><span class="p">)</span>                <span class="c1">// Remove all spaces</span>
        <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\+</span><span class="sr">+/g</span><span class="p">,</span> <span class="dl">"</span><span class="s2">+</span><span class="dl">"</span><span class="p">)</span>               <span class="c1">// ++ -&gt; +</span>
        <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/-+/g</span><span class="p">,</span> <span class="dl">"</span><span class="s2">-</span><span class="dl">"</span><span class="p">)</span>                <span class="c1">// -- -&gt; -</span>
        <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\*\+</span><span class="sr">/g</span><span class="p">,</span> <span class="dl">"</span><span class="s2">*</span><span class="dl">"</span><span class="p">)</span>              <span class="c1">// *+ -&gt; *</span>
        <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\/\+</span><span class="sr">/g</span><span class="p">,</span> <span class="dl">"</span><span class="s2">/</span><span class="dl">"</span><span class="p">)</span>              <span class="c1">// /+ -&gt; /</span>
        <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\+</span><span class="sr">-/g</span><span class="p">,</span> <span class="dl">"</span><span class="s2">-</span><span class="dl">"</span><span class="p">)</span>               <span class="c1">// +- -&gt; -</span>
        <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">(\d)</span><span class="sr">-</span><span class="se">(\d)</span><span class="sr">/g</span><span class="p">,</span> <span class="dl">"</span><span class="s2">$1+-$2</span><span class="dl">"</span><span class="p">)</span>    <span class="c1">// a-b -&gt; a+-b</span>
        <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\/</span><span class="sr">/g</span><span class="p">,</span> <span class="dl">"</span><span class="s2">*1/</span><span class="dl">"</span><span class="p">);</span>             <span class="c1">// a/b -&gt; a*1/b</span>
<span class="p">}</span>

<span class="c1">// MAIN</span>
<span class="c1">// ====</span>

<span class="k">if</span> <span class="p">(</span><span class="k">import</span><span class="p">.</span><span class="nx">meta</span><span class="p">.</span><span class="nx">url</span> <span class="o">===</span> <span class="k">new</span> <span class="nx">URL</span><span class="p">(</span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="dl">'</span><span class="s1">file:</span><span class="dl">'</span><span class="p">).</span><span class="nx">href</span><span class="p">)</span> <span class="p">{</span>
  <span class="nx">askQuestion</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>tests.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// IMPORTS</span>
<span class="c1">// =======</span>

<span class="k">import</span> <span class="p">{</span> <span class="nx">getResult</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">./calculator.js</span><span class="dl">"</span><span class="p">;</span>

<span class="c1">// FUNCTIONS</span>
<span class="c1">// =========</span>

<span class="kd">function</span> <span class="nx">runTests</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Test 01: </span><span class="dl">"</span> <span class="o">+</span> <span class="p">(</span><span class="nx">getResult</span><span class="p">(</span><span class="dl">"</span><span class="s2">2 + 3</span><span class="dl">"</span><span class="p">)</span> <span class="o">===</span> <span class="s2">`</span><span class="p">${</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">3</span><span class="p">}</span><span class="s2">`</span><span class="p">));</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Test 02: </span><span class="dl">"</span> <span class="o">+</span> <span class="p">(</span><span class="nx">getResult</span><span class="p">(</span><span class="dl">"</span><span class="s2">2 - 3</span><span class="dl">"</span><span class="p">)</span> <span class="o">===</span> <span class="s2">`</span><span class="p">${</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">3</span><span class="p">}</span><span class="s2">`</span><span class="p">));</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Test 03: </span><span class="dl">"</span> <span class="o">+</span> <span class="p">(</span><span class="nx">getResult</span><span class="p">(</span><span class="dl">"</span><span class="s2">2 * 3</span><span class="dl">"</span><span class="p">)</span> <span class="o">===</span> <span class="s2">`</span><span class="p">${</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span><span class="p">}</span><span class="s2">`</span><span class="p">));</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Test 04: </span><span class="dl">"</span> <span class="o">+</span> <span class="p">(</span><span class="nx">getResult</span><span class="p">(</span><span class="dl">"</span><span class="s2">2 / 3</span><span class="dl">"</span><span class="p">)</span> <span class="o">===</span> <span class="s2">`</span><span class="p">${</span><span class="mi">2</span> <span class="o">/</span> <span class="mi">3</span><span class="p">}</span><span class="s2">`</span><span class="p">));</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Test 05: </span><span class="dl">"</span> <span class="o">+</span> <span class="p">(</span><span class="nx">getResult</span><span class="p">(</span><span class="dl">"</span><span class="s2">2 / 0</span><span class="dl">"</span><span class="p">)</span> <span class="o">===</span> <span class="dl">"</span><span class="s2">Undefined</span><span class="dl">"</span><span class="p">));</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Test 06: </span><span class="dl">"</span> <span class="o">+</span> <span class="p">(</span><span class="nx">getResult</span><span class="p">(</span><span class="dl">"</span><span class="s2">  7 +   2 * 3 - 4 / -2 </span><span class="dl">"</span><span class="p">)</span> <span class="o">===</span> <span class="s2">`</span><span class="p">${</span>  <span class="mi">7</span> <span class="o">+</span>   <span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">/</span> <span class="o">-</span><span class="mi">2</span> <span class="p">}</span><span class="s2">`</span><span class="p">));</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Test 07: </span><span class="dl">"</span> <span class="o">+</span> <span class="p">(</span><span class="nx">getResult</span><span class="p">(</span><span class="dl">"</span><span class="s2">  7 +   2 / 3 - 4 * +-2 </span><span class="dl">"</span><span class="p">)</span> <span class="o">===</span> <span class="s2">`</span><span class="p">${</span>  <span class="mi">7</span> <span class="o">+</span>   <span class="mi">2</span> <span class="o">/</span> <span class="mi">3</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">+-</span><span class="mi">2</span> <span class="p">}</span><span class="s2">`</span><span class="p">));</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Test 08: </span><span class="dl">"</span> <span class="o">+</span> <span class="p">(</span><span class="nx">getResult</span><span class="p">(</span><span class="dl">"</span><span class="s2">2.0 + 3.0</span><span class="dl">"</span><span class="p">)</span> <span class="o">===</span> <span class="s2">`</span><span class="p">${</span><span class="mf">2.0</span> <span class="o">+</span> <span class="mf">3.0</span><span class="p">}</span><span class="s2">`</span><span class="p">));</span>
<span class="p">}</span>

<span class="c1">// MAIN</span>
<span class="c1">// ====</span>

<span class="k">if</span> <span class="p">(</span><span class="k">import</span><span class="p">.</span><span class="nx">meta</span><span class="p">.</span><span class="nx">url</span> <span class="o">===</span> <span class="k">new</span> <span class="nx">URL</span><span class="p">(</span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="dl">'</span><span class="s1">file:</span><span class="dl">'</span><span class="p">).</span><span class="nx">href</span><span class="p">)</span> <span class="p">{</span>
  <span class="nx">runTests</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="python">Python</h2>

<p>JavaScript and Python are what I would describe as old-newbies in the programming language scene. I say so because they are far from the first computer languages to ever be typed on a console, or even to be punched on cards. They are also not that old: both appeared in the late 80s and early 90s, a decade after the mythical C language and its precursor, <a href="https://en.wikipedia.org/wiki/B_(programming_language)">B</a> (I kid you not).</p>

<p>Enough said about history. Although from the same generation, Python and JavaScript took different approaches. One small distinction is fewer implicit type coersion. Indeed, Python revealed itself to be stricter with me. Another particularly interesting aspect of Python is that the <code class="language-plaintext highlighter-rouge">float</code> type is actually a <code class="language-plaintext highlighter-rouge">double</code>, like double-precision. That makes it confusing to people coming from other programming languages that use both types distinctly.</p>

<p>calculator.py:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># IMPORTS
# =======
</span>
<span class="kn">import</span> <span class="nn">math</span>
<span class="kn">import</span> <span class="nn">re</span>

<span class="c1"># FUNCTIONS
# =========
</span>
<span class="k">def</span> <span class="nf">ask_question</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="bp">None</span><span class="p">:</span>
    <span class="n">calculation</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"Your calculation: "</span><span class="p">)</span>
    <span class="n">result</span> <span class="o">=</span> <span class="n">get_result</span><span class="p">(</span><span class="n">calculation</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">" = </span><span class="si">{</span><span class="n">result</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>


<span class="k">def</span> <span class="nf">get_result</span><span class="p">(</span><span class="n">calculation</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
    <span class="n">calculation</span> <span class="o">=</span> <span class="n">sanitize_calculation</span><span class="p">(</span><span class="n">calculation</span><span class="p">)</span>
    <span class="n">result</span> <span class="o">=</span> <span class="mf">0.0</span>
    
    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">calculation</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">"+"</span><span class="p">):</span>
        <span class="n">sub_result</span> <span class="o">=</span> <span class="mf">1.0</span>
        <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">i</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">"*"</span><span class="p">):</span>
            <span class="k">if</span> <span class="n">j</span><span class="p">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">"1/"</span><span class="p">):</span>
                <span class="n">sanitized_j</span> <span class="o">=</span> <span class="n">j</span><span class="p">.</span><span class="n">replace</span><span class="p">(</span><span class="s">"1/"</span><span class="p">,</span> <span class="s">""</span><span class="p">)</span>
                <span class="k">if</span> <span class="nb">float</span><span class="p">(</span><span class="n">sanitized_j</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
                    <span class="k">return</span> <span class="s">"Undefined"</span>
                <span class="n">sub_result</span> <span class="o">/=</span> <span class="nb">float</span><span class="p">(</span><span class="n">sanitized_j</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">sub_result</span> <span class="o">*=</span> <span class="nb">float</span><span class="p">(</span><span class="n">j</span><span class="p">)</span>
        <span class="n">result</span> <span class="o">+=</span> <span class="n">sub_result</span>

    <span class="k">if</span> <span class="n">result</span><span class="p">.</span><span class="n">is_integer</span><span class="p">()</span> <span class="ow">and</span> <span class="n">calculation</span><span class="p">.</span><span class="n">count</span><span class="p">(</span><span class="s">"/"</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">calculation</span><span class="p">.</span><span class="n">count</span><span class="p">(</span><span class="s">"."</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">return</span> <span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="nb">int</span><span class="p">(</span><span class="n">result</span><span class="p">)</span><span class="si">}</span><span class="s">"</span>
    <span class="k">return</span> <span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="n">result</span><span class="si">}</span><span class="s">"</span>


<span class="k">def</span> <span class="nf">sanitize_calculation</span><span class="p">(</span><span class="n">calculation</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
    <span class="n">sanitized</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="n">sub</span><span class="p">(</span><span class="sa">r</span><span class="s">"\s+"</span><span class="p">,</span> <span class="s">""</span><span class="p">,</span> <span class="n">calculation</span><span class="p">)</span>             <span class="c1"># Remove all spaces
</span>    <span class="n">sanitized</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="n">sub</span><span class="p">(</span><span class="sa">r</span><span class="s">"\++"</span><span class="p">,</span> <span class="s">"+"</span><span class="p">,</span> <span class="n">sanitized</span><span class="p">)</span>              <span class="c1"># ++ -&gt; +
</span>    <span class="n">sanitized</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="n">sub</span><span class="p">(</span><span class="sa">r</span><span class="s">"-+"</span><span class="p">,</span> <span class="s">"-"</span><span class="p">,</span> <span class="n">sanitized</span><span class="p">)</span>               <span class="c1"># -- -&gt; -
</span>    <span class="n">sanitized</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="n">sub</span><span class="p">(</span><span class="sa">r</span><span class="s">"\*\+"</span><span class="p">,</span> <span class="s">"*"</span><span class="p">,</span> <span class="n">sanitized</span><span class="p">)</span>             <span class="c1"># *+ -&gt; *
</span>    <span class="n">sanitized</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="n">sub</span><span class="p">(</span><span class="sa">r</span><span class="s">"/\+"</span><span class="p">,</span> <span class="s">"/"</span><span class="p">,</span> <span class="n">sanitized</span><span class="p">)</span>              <span class="c1"># /+ -&gt; /
</span>    <span class="n">sanitized</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="n">sub</span><span class="p">(</span><span class="sa">r</span><span class="s">"\+-"</span><span class="p">,</span> <span class="s">"-"</span><span class="p">,</span> <span class="n">sanitized</span><span class="p">)</span>              <span class="c1"># +- -&gt; -
</span>    <span class="n">sanitized</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="n">sub</span><span class="p">(</span><span class="sa">r</span><span class="s">"(\d)-(\d)"</span><span class="p">,</span> <span class="sa">r</span><span class="s">"\1+-\2"</span><span class="p">,</span> <span class="n">sanitized</span><span class="p">)</span>  <span class="c1"># a-b -&gt; a+-b
</span>    <span class="n">sanitized</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="n">sub</span><span class="p">(</span><span class="sa">r</span><span class="s">"/"</span><span class="p">,</span> <span class="s">"*1/"</span><span class="p">,</span> <span class="n">sanitized</span><span class="p">)</span>              <span class="c1"># a/b -&gt; a*1/b
</span>    <span class="k">return</span> <span class="n">sanitized</span>

<span class="c1"># MAIN
# ====
</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">"__main__"</span><span class="p">:</span>
    <span class="n">ask_question</span><span class="p">()</span>
</code></pre></div></div>

<p>tests.py:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># IMPORTS
# =======
</span>
<span class="kn">from</span> <span class="nn">calculator</span> <span class="kn">import</span> <span class="n">get_result</span>

<span class="c1"># FUNCTIONS
# =========
</span>
<span class="k">def</span> <span class="nf">run_tests</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="bp">None</span><span class="p">:</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"Test 01: "</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">get_result</span><span class="p">(</span><span class="s">"2 + 3"</span><span class="p">)</span> <span class="o">==</span> <span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">3</span><span class="si">}</span><span class="s">"</span><span class="p">))</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"Test 02: "</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">get_result</span><span class="p">(</span><span class="s">"2 - 3"</span><span class="p">)</span> <span class="o">==</span> <span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">3</span><span class="si">}</span><span class="s">"</span><span class="p">))</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"Test 03: "</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">get_result</span><span class="p">(</span><span class="s">"2 * 3"</span><span class="p">)</span> <span class="o">==</span> <span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span><span class="si">}</span><span class="s">"</span><span class="p">))</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"Test 04: "</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">get_result</span><span class="p">(</span><span class="s">"2 / 3"</span><span class="p">)</span> <span class="o">==</span> <span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="mi">2</span> <span class="o">/</span> <span class="mi">3</span><span class="si">}</span><span class="s">"</span><span class="p">))</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"Test 05: "</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">get_result</span><span class="p">(</span><span class="s">"2 / 0"</span><span class="p">)</span> <span class="o">==</span> <span class="s">"Undefined"</span><span class="p">))</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"Test 06: "</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">get_result</span><span class="p">(</span><span class="s">"  7 +   2 * 3 - 4 / -2 "</span><span class="p">)</span> <span class="o">==</span> <span class="sa">f</span><span class="s">"</span><span class="si">{</span>  <span class="mi">7</span> <span class="o">+</span>   <span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">/</span> <span class="o">-</span><span class="mi">2</span> <span class="si">}</span><span class="s">"</span><span class="p">))</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"Test 07: "</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">get_result</span><span class="p">(</span><span class="s">"  7 +   2 / 3 - 4 * +-2 "</span><span class="p">)</span> <span class="o">==</span> <span class="sa">f</span><span class="s">"</span><span class="si">{</span>  <span class="mi">7</span> <span class="o">+</span>   <span class="mi">2</span> <span class="o">/</span> <span class="mi">3</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">+-</span><span class="mi">2</span> <span class="si">}</span><span class="s">"</span><span class="p">))</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"Test 08: "</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">get_result</span><span class="p">(</span><span class="s">"2.0 + 3.0"</span><span class="p">)</span> <span class="o">==</span> <span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="mf">2.0</span> <span class="o">+</span> <span class="mf">3.0</span><span class="si">}</span><span class="s">"</span><span class="p">))</span>

<span class="c1"># MAIN
# ====
</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">"__main__"</span><span class="p">:</span>
    <span class="n">run_tests</span><span class="p">()</span>
</code></pre></div></div>

<h2 id="bashshell">Bash/Shell</h2>

<p>What’s the difference between Shell and Bash? Well, I know that Bash stands for Bourne Again SHell, but that doesn’t help. So I tried looking up the difference directly on my macOS terminal:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>% sh <span class="nt">--version</span>
GNU bash, version 3.2.57<span class="o">(</span>1<span class="o">)</span><span class="nt">-release</span> <span class="o">(</span>arm64-apple-darwin25<span class="o">)</span>
Copyright <span class="o">(</span>C<span class="o">)</span> 2007 Free Software Foundation, Inc.
</code></pre></div></div>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>% bash <span class="nt">--version</span>
GNU bash, version 3.2.57<span class="o">(</span>1<span class="o">)</span><span class="nt">-release</span> <span class="o">(</span>arm64-apple-darwin25<span class="o">)</span>
Copyright <span class="o">(</span>C<span class="o">)</span> 2007 Free Software Foundation, Inc.
</code></pre></div></div>

<p>Here again, both are literally the same. That doesn’t help, but maybe it’s just that they’re genuinely the same. However, I persevered in my search for further clarification and found this <a href="https://stackoverflow.com/a/5725402/8811661">explanation</a>: <code class="language-plaintext highlighter-rouge">sh</code>’s a specification, <code class="language-plaintext highlighter-rouge">bash</code>’s an implementation. So, for a linguist, I guess this translates to: <code class="language-plaintext highlighter-rouge">sh</code>’s like Standard Arabic, and <code class="language-plaintext highlighter-rouge">bash</code>’s like the Lebanese/Levantine Dialect, amongst other <a href="https://en.wikipedia.org/wiki/Varieties_of_Arabic">dialects</a>. On my system, <code class="language-plaintext highlighter-rouge">sh</code> is therefore implemented as <code class="language-plaintext highlighter-rouge">bash</code>.</p>

<p>Although shell languages may seem old compared to typical programming languages, the Bash dialect was only published in 1989. Yet, like any Shell dialect, I find it painful to read and understand at a glance, especially due to the one-letter arguments and old methods of splitting text by setting a global variable, the IFS (Internal Field Separator).</p>

<p>On the bright side, shell languages use something called a Shebang (<code class="language-plaintext highlighter-rouge">#!/usr/bin/env bash</code>), and I love the name!</p>

<p>calculator.bash:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/usr/bin/env bash</span>

<span class="c"># Enable strict mode for safer bash script execution</span>
<span class="c"># set -e: Exit immediately if any command exits with a non-zero status</span>
<span class="c"># set -u: Exit if an undefined variable is used</span>
<span class="c"># set -o pipefail: Return the exit status of the last command in a pipeline that failed</span>
<span class="nb">set</span> <span class="nt">-euo</span> pipefail

<span class="c"># FUNCTIONS</span>
<span class="c"># =========</span>

ask_question<span class="o">()</span> <span class="o">{</span>
    <span class="c"># -r : prevent backslash interpretation</span>
    <span class="c"># -p : display the prompt text</span>
	<span class="nb">read</span> <span class="nt">-r</span> <span class="nt">-p</span> <span class="s2">"Your calculation: "</span> calculation
	<span class="nb">local </span><span class="nv">result</span><span class="o">=</span><span class="si">$(</span>get_result <span class="s2">"</span><span class="nv">$calculation</span><span class="s2">"</span><span class="si">)</span>
	<span class="nb">echo</span> <span class="s2">" = </span><span class="nv">$result</span><span class="s2">"</span>
<span class="o">}</span>

get_result<span class="o">()</span> <span class="o">{</span>
	<span class="nb">local </span><span class="nv">calculation</span><span class="o">=</span><span class="si">$(</span>sanitize_calculation <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span><span class="si">)</span>
	<span class="nb">local </span><span class="nv">result</span><span class="o">=</span>0

	<span class="nb">local </span><span class="nv">IFS</span><span class="o">=</span><span class="s1">'+'</span> <span class="c"># Internal Field Separator set to +</span>
	<span class="k">for </span>i <span class="k">in</span> <span class="nv">$calculation</span><span class="p">;</span> <span class="k">do
		</span><span class="nb">local </span><span class="nv">sub_result</span><span class="o">=</span>1
		<span class="nb">local </span><span class="nv">IFS</span><span class="o">=</span><span class="s1">'*'</span> <span class="c"># Internal Field Separator set to *</span>
		<span class="k">for </span>j <span class="k">in</span> <span class="nv">$i</span><span class="p">;</span> <span class="k">do
			if</span> <span class="o">[[</span> <span class="nv">$j</span> <span class="o">==</span> 1/<span class="k">*</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
				</span><span class="nb">local </span><span class="nv">sanitized_j</span><span class="o">=</span><span class="k">${</span><span class="nv">j</span><span class="p">#1/</span><span class="k">}</span>
				<span class="k">if</span> <span class="o">[[</span> <span class="nv">$sanitized_j</span> <span class="o">==</span> 0 <span class="o">]]</span><span class="p">;</span> <span class="k">then
					</span><span class="nb">echo</span> <span class="s2">"Undefined"</span>
					<span class="k">return
				fi
				</span><span class="nv">sub_result</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"</span><span class="nv">$sub_result</span><span class="s2">/</span><span class="nv">$sanitized_j</span><span class="s2">"</span> | bc <span class="nt">-l</span><span class="si">)</span>
			<span class="k">else
				</span><span class="nv">sub_result</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"</span><span class="nv">$sub_result</span><span class="s2">*</span><span class="nv">$j</span><span class="s2">"</span> | bc <span class="nt">-l</span><span class="si">)</span>
			<span class="k">fi
		done
		</span><span class="nv">result</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"</span><span class="nv">$result</span><span class="s2">+</span><span class="nv">$sub_result</span><span class="s2">"</span> | bc <span class="nt">-l</span><span class="si">)</span>
	<span class="k">done
    
	</span><span class="nb">printf</span> <span class="s1">'%s\n'</span> <span class="s2">"</span><span class="nv">$result</span><span class="s2">"</span>
<span class="o">}</span>

sanitize_calculation<span class="o">()</span> <span class="o">{</span>
	<span class="nb">local </span><span class="nv">calculation</span><span class="o">=</span><span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span>
	<span class="nv">calculation</span><span class="o">=</span><span class="si">$(</span><span class="nb">printf</span> <span class="s1">'%s'</span> <span class="s2">"</span><span class="nv">$calculation</span><span class="s2">"</span> | <span class="nb">sed</span> <span class="nt">-E</span> <span class="s1">'
        s/[[:space:]]+//g;
        s/\++/+/g;
        s/-+/-/g;
        s/\*\+/*/g;
        s#/\+#/#g;
        s/\+-/-/g;
        s/([0-9])-([0-9])/\1+-\2/g;
        s#/#*1/#g
    '</span><span class="si">)</span>
	<span class="nb">printf</span> <span class="s1">'%s'</span> <span class="s2">"</span><span class="nv">$calculation</span><span class="s2">"</span>
<span class="o">}</span>

<span class="c"># MAIN</span>
<span class="c"># ====</span>

<span class="k">if</span> <span class="o">[[</span> <span class="s2">"</span><span class="k">${</span><span class="nv">BASH_SOURCE</span><span class="p">[0]</span><span class="k">}</span><span class="s2">"</span> <span class="o">==</span> <span class="s2">"</span><span class="nv">$0</span><span class="s2">"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
	</span>ask_question
<span class="k">fi</span>
</code></pre></div></div>

<p>tests.bash:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/usr/bin/env bash</span>

<span class="c"># Enable strict mode for safer bash script execution</span>
<span class="c"># set -e: Exit immediately if any command exits with a non-zero status</span>
<span class="c"># set -u: Exit if an undefined variable is used</span>
<span class="c"># set -o pipefail: Return the exit status of the last command in a pipeline that failed</span>
<span class="nb">set</span> <span class="nt">-euo</span> pipefail

<span class="c"># IMPORTS</span>
<span class="c"># =======</span>

<span class="nb">source</span> ./calculator.bash

<span class="c"># FUNCTIONS</span>
<span class="c"># =========</span>

run_tests<span class="o">()</span> <span class="o">{</span>
	<span class="nb">echo</span> <span class="s2">"Test 01: </span><span class="si">$(</span> <span class="o">[[</span> <span class="si">$(</span>get_result <span class="s2">"2 + 3"</span><span class="si">)</span> <span class="o">==</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"2+3"</span> | bc <span class="nt">-l</span><span class="si">)</span><span class="s2">"</span><span class="si">)</span><span class="s2">"</span> <span class="o">]]</span> <span class="o">&amp;&amp;</span> <span class="nb">echo true</span> <span class="o">||</span> <span class="nb">echo false</span> <span class="si">)</span><span class="s2">"</span>
	<span class="nb">echo</span> <span class="s2">"Test 02: </span><span class="si">$(</span> <span class="o">[[</span> <span class="si">$(</span>get_result <span class="s2">"2 - 3"</span><span class="si">)</span> <span class="o">==</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"2-3"</span> | bc <span class="nt">-l</span><span class="si">)</span><span class="s2">"</span><span class="si">)</span><span class="s2">"</span> <span class="o">]]</span> <span class="o">&amp;&amp;</span> <span class="nb">echo true</span> <span class="o">||</span> <span class="nb">echo false</span> <span class="si">)</span><span class="s2">"</span>
	<span class="nb">echo</span> <span class="s2">"Test 03: </span><span class="si">$(</span> <span class="o">[[</span> <span class="si">$(</span>get_result <span class="s2">"2 * 3"</span><span class="si">)</span> <span class="o">==</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"2*3"</span> | bc <span class="nt">-l</span><span class="si">)</span><span class="s2">"</span><span class="si">)</span><span class="s2">"</span> <span class="o">]]</span> <span class="o">&amp;&amp;</span> <span class="nb">echo true</span> <span class="o">||</span> <span class="nb">echo false</span> <span class="si">)</span><span class="s2">"</span>
	<span class="nb">echo</span> <span class="s2">"Test 04: </span><span class="si">$(</span> <span class="o">[[</span> <span class="si">$(</span>get_result <span class="s2">"2 / 3"</span><span class="si">)</span> <span class="o">==</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"2/3"</span> | bc <span class="nt">-l</span><span class="si">)</span><span class="s2">"</span><span class="si">)</span><span class="s2">"</span> <span class="o">]]</span> <span class="o">&amp;&amp;</span> <span class="nb">echo true</span> <span class="o">||</span> <span class="nb">echo false</span> <span class="si">)</span><span class="s2">"</span>
	<span class="nb">echo</span> <span class="s2">"Test 05: </span><span class="si">$(</span> <span class="o">[[</span> <span class="si">$(</span>get_result <span class="s2">"2 / 0"</span><span class="si">)</span> <span class="o">==</span> <span class="s2">"Undefined"</span> <span class="o">]]</span> <span class="o">&amp;&amp;</span> <span class="nb">echo true</span> <span class="o">||</span> <span class="nb">echo false</span> <span class="si">)</span><span class="s2">"</span>
	<span class="nb">echo</span> <span class="s2">"Test 06: </span><span class="si">$(</span> <span class="o">[[</span> <span class="si">$(</span>get_result <span class="s2">"  7 +   2 * 3 - 4 / -2 "</span><span class="si">)</span> <span class="o">==</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"  7 +   2 * 3 - 4 / -2 "</span> | bc <span class="nt">-l</span><span class="si">)</span><span class="s2">"</span><span class="si">)</span><span class="s2">"</span> <span class="o">]]</span> <span class="o">&amp;&amp;</span> <span class="nb">echo true</span> <span class="o">||</span> <span class="nb">echo false</span> <span class="si">)</span><span class="s2">"</span>
	<span class="nb">echo</span> <span class="s2">"Test 07: </span><span class="si">$(</span> <span class="o">[[</span> <span class="si">$(</span>get_result <span class="s2">"  7 +   2 / 3 - 4 * +-2 "</span><span class="si">)</span> <span class="o">==</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"  7 +   2 / 3 - 4 * -2 "</span> | bc <span class="nt">-l</span><span class="si">)</span><span class="s2">"</span><span class="si">)</span><span class="s2">"</span> <span class="o">]]</span> <span class="o">&amp;&amp;</span> <span class="nb">echo true</span> <span class="o">||</span> <span class="nb">echo false</span> <span class="si">)</span><span class="s2">"</span>
	<span class="nb">echo</span> <span class="s2">"Test 08: </span><span class="si">$(</span> <span class="o">[[</span> <span class="si">$(</span>get_result <span class="s2">"2.0 + 3.0"</span><span class="si">)</span> <span class="o">==</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"2.0+3.0"</span> | bc <span class="nt">-l</span><span class="si">)</span><span class="s2">"</span><span class="si">)</span><span class="s2">"</span> <span class="o">]]</span> <span class="o">&amp;&amp;</span> <span class="nb">echo true</span> <span class="o">||</span> <span class="nb">echo false</span> <span class="si">)</span><span class="s2">"</span>
<span class="o">}</span>

<span class="c"># MAIN</span>
<span class="c"># ====</span>

<span class="k">if</span> <span class="o">[[</span> <span class="s2">"</span><span class="k">${</span><span class="nv">BASH_SOURCE</span><span class="p">[0]</span><span class="k">}</span><span class="s2">"</span> <span class="o">==</span> <span class="s2">"</span><span class="nv">$0</span><span class="s2">"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
	</span>run_tests
<span class="k">fi</span>
</code></pre></div></div>

<h2 id="typescript">TypeScript</h2>

<p>TypeScript is a JS superset built with static types and safety in mind. Knowing that, I thought that I would have a nicer time writing and compiling the code, but I was surprisingly wrong. I stumbled on unclear errors that were due to the usage of CommonJS and ESM. These two are different JavaScript standards, with ESM being the newer, but not the default: why? Typescript is therefore the first language, and not the last, to necessitate a third file: tsconfig.json (though I think that it can be replaced by arguments in the <code class="language-plaintext highlighter-rouge">ts-node</code> command). I also had deprecation warnings that I couldn’t control, so I just shushed them.</p>

<p>calculator.ts:</p>
<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// IMPORTS</span>
<span class="c1">// =======</span>

<span class="k">import</span> <span class="p">{</span> <span class="nx">createInterface</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">readline</span><span class="dl">"</span><span class="p">;</span>

<span class="c1">// FUNCTIONS</span>
<span class="c1">// =========</span>

<span class="kd">function</span> <span class="nx">askQuestion</span><span class="p">():</span> <span class="k">void</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">read</span> <span class="o">=</span> <span class="nx">createInterface</span><span class="p">({</span> <span class="na">input</span><span class="p">:</span> <span class="nx">process</span><span class="p">.</span><span class="nx">stdin</span><span class="p">,</span> <span class="na">output</span><span class="p">:</span> <span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span> <span class="p">});</span>
    <span class="nx">read</span><span class="p">.</span><span class="nx">question</span><span class="p">(</span><span class="dl">"</span><span class="s2">Your calculation: </span><span class="dl">"</span><span class="p">,</span> <span class="p">(</span><span class="na">calculation</span><span class="p">:</span> <span class="kr">string</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="kd">const</span> <span class="nx">result</span> <span class="o">=</span> <span class="nx">getResult</span><span class="p">(</span><span class="nx">calculation</span><span class="p">);</span>
        <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">` = </span><span class="p">${</span><span class="nx">result</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
        <span class="nx">read</span><span class="p">.</span><span class="nx">close</span><span class="p">();</span>
    <span class="p">});</span>
<span class="p">}</span>

<span class="k">export</span> <span class="kd">function</span> <span class="nx">getResult</span><span class="p">(</span><span class="nx">calculation</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="kr">string</span> <span class="p">{</span>
    <span class="nx">calculation</span> <span class="o">=</span> <span class="nx">sanitizeCalculation</span><span class="p">(</span><span class="nx">calculation</span><span class="p">);</span>
    <span class="kd">let</span> <span class="nx">result</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span>

    <span class="k">for</span> <span class="p">(</span><span class="kd">const</span> <span class="nx">i</span> <span class="k">of</span> <span class="nx">calculation</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="dl">"</span><span class="s2">+</span><span class="dl">"</span><span class="p">))</span> <span class="p">{</span>
        <span class="kd">let</span> <span class="nx">subResult</span> <span class="o">=</span> <span class="mf">1.0</span><span class="p">;</span>
        <span class="k">for</span> <span class="p">(</span><span class="kd">const</span> <span class="nx">j</span> <span class="k">of</span> <span class="nx">i</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="dl">"</span><span class="s2">*</span><span class="dl">"</span><span class="p">))</span> <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="nx">j</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="dl">"</span><span class="s2">1/</span><span class="dl">"</span><span class="p">))</span> <span class="p">{</span>
                <span class="kd">const</span> <span class="nx">sanitizedJ</span> <span class="o">=</span> <span class="nx">j</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/1</span><span class="se">\/</span><span class="sr">/g</span><span class="p">,</span> <span class="dl">""</span><span class="p">);</span>
                <span class="k">if</span> <span class="p">(</span><span class="nb">parseFloat</span><span class="p">(</span><span class="nx">sanitizedJ</span><span class="p">)</span> <span class="o">===</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="dl">"</span><span class="s2">Undefined</span><span class="dl">"</span><span class="p">;</span>
                <span class="nx">subResult</span> <span class="o">/=</span> <span class="nb">parseFloat</span><span class="p">(</span><span class="nx">sanitizedJ</span><span class="p">);</span>
            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                <span class="nx">subResult</span> <span class="o">*=</span> <span class="nb">parseFloat</span><span class="p">(</span><span class="nx">j</span><span class="p">);</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="nx">result</span> <span class="o">+=</span> <span class="nx">subResult</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="s2">`</span><span class="p">${</span><span class="nx">result</span><span class="p">}</span><span class="s2">`</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">function</span> <span class="nx">sanitizeCalculation</span><span class="p">(</span><span class="nx">calculation</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="kr">string</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">calculation</span>
        <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\s</span><span class="sr">+/g</span><span class="p">,</span> <span class="dl">""</span><span class="p">)</span>                <span class="c1">// Remove all spaces</span>
        <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\+</span><span class="sr">+/g</span><span class="p">,</span> <span class="dl">"</span><span class="s2">+</span><span class="dl">"</span><span class="p">)</span>               <span class="c1">// ++ -&gt; +</span>
        <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/-+/g</span><span class="p">,</span> <span class="dl">"</span><span class="s2">-</span><span class="dl">"</span><span class="p">)</span>                <span class="c1">// -- -&gt; -</span>
        <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\*\+</span><span class="sr">/g</span><span class="p">,</span> <span class="dl">"</span><span class="s2">*</span><span class="dl">"</span><span class="p">)</span>              <span class="c1">// *+ -&gt; *</span>
        <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\/\+</span><span class="sr">/g</span><span class="p">,</span> <span class="dl">"</span><span class="s2">/</span><span class="dl">"</span><span class="p">)</span>              <span class="c1">// /+ -&gt; /</span>
        <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\+</span><span class="sr">-/g</span><span class="p">,</span> <span class="dl">"</span><span class="s2">-</span><span class="dl">"</span><span class="p">)</span>               <span class="c1">// +- -&gt; -</span>
        <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">(\d)</span><span class="sr">-</span><span class="se">(\d)</span><span class="sr">/g</span><span class="p">,</span> <span class="dl">"</span><span class="s2">$1+-$2</span><span class="dl">"</span><span class="p">)</span>    <span class="c1">// a-b -&gt; a+-b</span>
        <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\/</span><span class="sr">/g</span><span class="p">,</span> <span class="dl">"</span><span class="s2">*1/</span><span class="dl">"</span><span class="p">);</span>             <span class="c1">// a/b -&gt; a*1/b</span>
<span class="p">}</span>

<span class="c1">// MAIN</span>
<span class="c1">// ====</span>

<span class="k">if</span> <span class="p">(</span><span class="k">import</span><span class="p">.</span><span class="nx">meta</span><span class="p">.</span><span class="nx">url</span> <span class="o">===</span> <span class="k">new</span> <span class="nx">URL</span><span class="p">(</span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="dl">'</span><span class="s1">file:</span><span class="dl">'</span><span class="p">).</span><span class="nx">href</span><span class="p">)</span> <span class="p">{</span>
  <span class="nx">askQuestion</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>tests.ts:</p>
<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// IMPORTS</span>
<span class="c1">// =======</span>

<span class="k">import</span> <span class="p">{</span> <span class="nx">getResult</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">./calculator.ts</span><span class="dl">"</span><span class="p">;</span>

<span class="c1">// FUNCTIONS</span>
<span class="c1">// =========</span>

<span class="kd">function</span> <span class="nx">runTests</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Test 01: </span><span class="dl">"</span> <span class="o">+</span> <span class="p">(</span><span class="nx">getResult</span><span class="p">(</span><span class="dl">"</span><span class="s2">2 + 3</span><span class="dl">"</span><span class="p">)</span> <span class="o">===</span> <span class="s2">`</span><span class="p">${</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">3</span><span class="p">}</span><span class="s2">`</span><span class="p">));</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Test 02: </span><span class="dl">"</span> <span class="o">+</span> <span class="p">(</span><span class="nx">getResult</span><span class="p">(</span><span class="dl">"</span><span class="s2">2 - 3</span><span class="dl">"</span><span class="p">)</span> <span class="o">===</span> <span class="s2">`</span><span class="p">${</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">3</span><span class="p">}</span><span class="s2">`</span><span class="p">));</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Test 03: </span><span class="dl">"</span> <span class="o">+</span> <span class="p">(</span><span class="nx">getResult</span><span class="p">(</span><span class="dl">"</span><span class="s2">2 * 3</span><span class="dl">"</span><span class="p">)</span> <span class="o">===</span> <span class="s2">`</span><span class="p">${</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span><span class="p">}</span><span class="s2">`</span><span class="p">));</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Test 04: </span><span class="dl">"</span> <span class="o">+</span> <span class="p">(</span><span class="nx">getResult</span><span class="p">(</span><span class="dl">"</span><span class="s2">2 / 3</span><span class="dl">"</span><span class="p">)</span> <span class="o">===</span> <span class="s2">`</span><span class="p">${</span><span class="mi">2</span> <span class="o">/</span> <span class="mi">3</span><span class="p">}</span><span class="s2">`</span><span class="p">));</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Test 05: </span><span class="dl">"</span> <span class="o">+</span> <span class="p">(</span><span class="nx">getResult</span><span class="p">(</span><span class="dl">"</span><span class="s2">2 / 0</span><span class="dl">"</span><span class="p">)</span> <span class="o">===</span> <span class="dl">"</span><span class="s2">Undefined</span><span class="dl">"</span><span class="p">));</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Test 06: </span><span class="dl">"</span> <span class="o">+</span> <span class="p">(</span><span class="nx">getResult</span><span class="p">(</span><span class="dl">"</span><span class="s2">  7 +   2 * 3 - 4 / -2 </span><span class="dl">"</span><span class="p">)</span> <span class="o">===</span> <span class="s2">`</span><span class="p">${</span>  <span class="mi">7</span> <span class="o">+</span>   <span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">/</span> <span class="o">-</span><span class="mi">2</span> <span class="p">}</span><span class="s2">`</span><span class="p">));</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Test 07: </span><span class="dl">"</span> <span class="o">+</span> <span class="p">(</span><span class="nx">getResult</span><span class="p">(</span><span class="dl">"</span><span class="s2">  7 +   2 / 3 - 4 * +-2 </span><span class="dl">"</span><span class="p">)</span> <span class="o">===</span> <span class="s2">`</span><span class="p">${</span>  <span class="mi">7</span> <span class="o">+</span>   <span class="mi">2</span> <span class="o">/</span> <span class="mi">3</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">+-</span><span class="mi">2</span> <span class="p">}</span><span class="s2">`</span><span class="p">));</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Test 08: </span><span class="dl">"</span> <span class="o">+</span> <span class="p">(</span><span class="nx">getResult</span><span class="p">(</span><span class="dl">"</span><span class="s2">2.0 + 3.0</span><span class="dl">"</span><span class="p">)</span> <span class="o">===</span> <span class="s2">`</span><span class="p">${</span><span class="mf">2.0</span> <span class="o">+</span> <span class="mf">3.0</span><span class="p">}</span><span class="s2">`</span><span class="p">));</span>
<span class="p">}</span>

<span class="c1">// MAIN</span>
<span class="c1">// ====</span>

<span class="k">if</span> <span class="p">(</span><span class="k">import</span><span class="p">.</span><span class="nx">meta</span><span class="p">.</span><span class="nx">url</span> <span class="o">===</span> <span class="k">new</span> <span class="nx">URL</span><span class="p">(</span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="dl">'</span><span class="s1">file:</span><span class="dl">'</span><span class="p">).</span><span class="nx">href</span><span class="p">)</span> <span class="p">{</span>
  <span class="nx">runTests</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>tsconfig.json:</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"ts-node"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"esm"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<h2 id="java">Java</h2>

<p>Java is surprisingly just a few months older than JavaScript.</p>

<p>I used to dislike using it because I had to install bulky software. Maybe it wasn’t that big of a deal, but that’s why I held C++ at a higher standard. However, the majority doesn’t seem to have the same opinion, so I’ll stop talking about my feelings. Before doing so, though, I’d like to clarify that my opinion has changed ever since I began using containerization.</p>

<p>Unlike the previous languages, Java is largely a pure object-oriented language. Essentially, most code is structured around classes. It also uses very similar code to JavaScript, even if “Java is to JavaScript as Car is to Carpet”.</p>

<p>Calculator.java:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// IMPORTS</span>
<span class="c1">// =======</span>

<span class="kn">import</span> <span class="nn">java.util.Scanner</span><span class="o">;</span>

<span class="c1">// CLASS</span>
<span class="c1">// =====</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">Calculator</span> <span class="o">{</span>

    <span class="c1">// METHODS</span>
    <span class="c1">// =======</span>
    
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">askQuestion</span><span class="o">()</span> <span class="o">{</span>
        <span class="nc">Scanner</span> <span class="n">scanner</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Scanner</span><span class="o">(</span><span class="nc">System</span><span class="o">.</span><span class="na">in</span><span class="o">);</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">print</span><span class="o">(</span><span class="s">"Your calculation: "</span><span class="o">);</span>
        <span class="nc">String</span> <span class="n">calculation</span> <span class="o">=</span> <span class="n">scanner</span><span class="o">.</span><span class="na">nextLine</span><span class="o">();</span>
        <span class="nc">String</span> <span class="n">result</span> <span class="o">=</span> <span class="n">getResult</span><span class="o">(</span><span class="n">calculation</span><span class="o">);</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">" = "</span> <span class="o">+</span> <span class="n">result</span><span class="o">);</span>
        <span class="n">scanner</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="nc">String</span> <span class="nf">getResult</span><span class="o">(</span><span class="nc">String</span> <span class="n">calculation</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">calculation</span> <span class="o">=</span> <span class="n">sanitizeCalculation</span><span class="o">(</span><span class="n">calculation</span><span class="o">);</span>
        <span class="kt">double</span> <span class="n">result</span> <span class="o">=</span> <span class="mf">0.0</span><span class="o">;</span>
        
        <span class="nc">String</span><span class="o">[]</span> <span class="n">addParts</span> <span class="o">=</span> <span class="n">calculation</span><span class="o">.</span><span class="na">split</span><span class="o">(</span><span class="s">"\\+"</span><span class="o">);</span>
        <span class="k">for</span> <span class="o">(</span><span class="nc">String</span> <span class="n">i</span> <span class="o">:</span> <span class="n">addParts</span><span class="o">)</span> <span class="o">{</span>
            <span class="kt">double</span> <span class="n">subResult</span> <span class="o">=</span> <span class="mf">1.0</span><span class="o">;</span>
            <span class="nc">String</span><span class="o">[]</span> <span class="n">mulParts</span> <span class="o">=</span> <span class="n">i</span><span class="o">.</span><span class="na">split</span><span class="o">(</span><span class="s">"\\*"</span><span class="o">);</span>
            <span class="k">for</span> <span class="o">(</span><span class="nc">String</span> <span class="n">j</span> <span class="o">:</span> <span class="n">mulParts</span><span class="o">)</span> <span class="o">{</span>
                <span class="k">if</span> <span class="o">(</span><span class="n">j</span><span class="o">.</span><span class="na">startsWith</span><span class="o">(</span><span class="s">"1/"</span><span class="o">))</span> <span class="o">{</span>
                    <span class="nc">String</span> <span class="n">sanitizedJ</span> <span class="o">=</span> <span class="n">j</span><span class="o">.</span><span class="na">replaceAll</span><span class="o">(</span><span class="s">"1/"</span><span class="o">,</span> <span class="s">""</span><span class="o">);</span>
                    <span class="k">if</span> <span class="o">(</span><span class="nc">Double</span><span class="o">.</span><span class="na">parseDouble</span><span class="o">(</span><span class="n">sanitizedJ</span><span class="o">)</span> <span class="o">==</span> <span class="mi">0</span><span class="o">)</span> <span class="k">return</span> <span class="s">"Undefined"</span><span class="o">;</span>
                    <span class="n">subResult</span> <span class="o">/=</span> <span class="nc">Double</span><span class="o">.</span><span class="na">parseDouble</span><span class="o">(</span><span class="n">sanitizedJ</span><span class="o">);</span>
                <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
                    <span class="n">subResult</span> <span class="o">*=</span> <span class="nc">Double</span><span class="o">.</span><span class="na">parseDouble</span><span class="o">(</span><span class="n">j</span><span class="o">);</span>
                <span class="o">}</span>
            <span class="o">}</span>
            <span class="n">result</span> <span class="o">+=</span> <span class="n">subResult</span><span class="o">;</span>
        <span class="o">}</span>
        
        <span class="k">if</span> <span class="o">(</span><span class="n">result</span> <span class="o">==</span> <span class="o">(</span><span class="kt">int</span><span class="o">)</span> <span class="n">result</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">calculation</span><span class="o">.</span><span class="na">contains</span><span class="o">(</span><span class="s">"/"</span><span class="o">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">calculation</span><span class="o">.</span><span class="na">contains</span><span class="o">(</span><span class="s">"."</span><span class="o">))</span> <span class="o">{</span>
            <span class="k">return</span> <span class="nc">String</span><span class="o">.</span><span class="na">valueOf</span><span class="o">((</span><span class="kt">int</span><span class="o">)</span> <span class="n">result</span><span class="o">);</span>
        <span class="o">}</span>
        <span class="k">return</span> <span class="nc">String</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="n">result</span><span class="o">);</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="nc">String</span> <span class="nf">sanitizeCalculation</span><span class="o">(</span><span class="nc">String</span> <span class="n">calculation</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">calculation</span>
            <span class="o">.</span><span class="na">replaceAll</span><span class="o">(</span><span class="s">"\\s+"</span><span class="o">,</span> <span class="s">""</span><span class="o">)</span>              <span class="c1">// Remove all spaces</span>
            <span class="o">.</span><span class="na">replaceAll</span><span class="o">(</span><span class="s">"\\++"</span><span class="o">,</span> <span class="s">"+"</span><span class="o">)</span>             <span class="c1">// ++ -&gt; +</span>
            <span class="o">.</span><span class="na">replaceAll</span><span class="o">(</span><span class="s">"-+"</span><span class="o">,</span> <span class="s">"-"</span><span class="o">)</span>               <span class="c1">// -- -&gt; -</span>
            <span class="o">.</span><span class="na">replaceAll</span><span class="o">(</span><span class="s">"\\*\\+"</span><span class="o">,</span> <span class="s">"*"</span><span class="o">)</span>           <span class="c1">// *+ -&gt; *</span>
            <span class="o">.</span><span class="na">replaceAll</span><span class="o">(</span><span class="s">"/\\+"</span><span class="o">,</span> <span class="s">"/"</span><span class="o">)</span>             <span class="c1">// /+ -&gt; /</span>
            <span class="o">.</span><span class="na">replaceAll</span><span class="o">(</span><span class="s">"\\+-"</span><span class="o">,</span> <span class="s">"-"</span><span class="o">)</span>             <span class="c1">// +- -&gt; -</span>
            <span class="o">.</span><span class="na">replaceAll</span><span class="o">(</span><span class="s">"(\\d)-(\\d)"</span><span class="o">,</span> <span class="s">"$1+-$2"</span><span class="o">)</span> <span class="c1">// a-b -&gt; a+-b</span>
            <span class="o">.</span><span class="na">replaceAll</span><span class="o">(</span><span class="s">"/"</span><span class="o">,</span> <span class="s">"*1/"</span><span class="o">);</span>             <span class="c1">// a/b -&gt; a*1/b</span>
    <span class="o">}</span>

    <span class="c1">// MAIN</span>
    <span class="c1">// ====</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">askQuestion</span><span class="o">();</span>
    <span class="o">}</span>

<span class="o">}</span>
</code></pre></div></div>

<p>Tests.java:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// CLASS</span>
<span class="c1">// =====</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">CalculatorTest</span> <span class="o">{</span>

    <span class="c1">// FUNCTIONS</span>
    <span class="c1">// =========</span>
    
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">runTests</span><span class="o">()</span> <span class="o">{</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Test 01: "</span> <span class="o">+</span> <span class="o">(</span><span class="nc">Calculator</span><span class="o">.</span><span class="na">getResult</span><span class="o">(</span><span class="s">"2 + 3"</span><span class="o">).</span><span class="na">equals</span><span class="o">(</span><span class="nc">String</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">3</span><span class="o">))));</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Test 02: "</span> <span class="o">+</span> <span class="o">(</span><span class="nc">Calculator</span><span class="o">.</span><span class="na">getResult</span><span class="o">(</span><span class="s">"2 - 3"</span><span class="o">).</span><span class="na">equals</span><span class="o">(</span><span class="nc">String</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">3</span><span class="o">))));</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Test 03: "</span> <span class="o">+</span> <span class="o">(</span><span class="nc">Calculator</span><span class="o">.</span><span class="na">getResult</span><span class="o">(</span><span class="s">"2 * 3"</span><span class="o">).</span><span class="na">equals</span><span class="o">(</span><span class="nc">String</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span><span class="o">))));</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Test 04: "</span> <span class="o">+</span> <span class="o">(</span><span class="nc">Calculator</span><span class="o">.</span><span class="na">getResult</span><span class="o">(</span><span class="s">"2 / 3"</span><span class="o">).</span><span class="na">equals</span><span class="o">(</span><span class="nc">String</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="mf">2.0</span> <span class="o">/</span> <span class="mf">3.0</span><span class="o">))));</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Test 05: "</span> <span class="o">+</span> <span class="o">(</span><span class="nc">Calculator</span><span class="o">.</span><span class="na">getResult</span><span class="o">(</span><span class="s">"2 / 0"</span><span class="o">).</span><span class="na">equals</span><span class="o">(</span><span class="s">"Undefined"</span><span class="o">)));</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Test 06: "</span> <span class="o">+</span> <span class="o">(</span><span class="nc">Calculator</span><span class="o">.</span><span class="na">getResult</span><span class="o">(</span><span class="s">"  7 +   2 * 3 - 4 / -2 "</span><span class="o">).</span><span class="na">equals</span><span class="o">(</span><span class="nc">String</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="mi">7</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">-</span> <span class="mf">4.0</span> <span class="o">/</span> <span class="o">-</span><span class="mi">2</span><span class="o">))));</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Test 07: "</span> <span class="o">+</span> <span class="o">(</span><span class="nc">Calculator</span><span class="o">.</span><span class="na">getResult</span><span class="o">(</span><span class="s">"  7 +   2 / 3 - 4 * +-2 "</span><span class="o">).</span><span class="na">equals</span><span class="o">(</span><span class="nc">String</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="mi">7</span> <span class="o">+</span> <span class="mf">2.0</span> <span class="o">/</span> <span class="mi">3</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">-</span><span class="mi">2</span><span class="o">))));</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Test 08: "</span> <span class="o">+</span> <span class="o">(</span><span class="nc">Calculator</span><span class="o">.</span><span class="na">getResult</span><span class="o">(</span><span class="s">"2.0 + 3.0"</span><span class="o">).</span><span class="na">equals</span><span class="o">(</span><span class="nc">String</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="mf">2.0</span> <span class="o">+</span> <span class="mf">3.0</span><span class="o">))));</span>
    <span class="o">}</span>

    <span class="c1">// MAIN</span>
    <span class="c1">// ====</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">runTests</span><span class="o">();</span>
    <span class="o">}</span>

<span class="o">}</span>
</code></pre></div></div>

<h2 id="c">C#</h2>

<p>I believe that my only and earliest developer experiences were with C# on Unity and Visual Studio. I haven’t touched the language ever since.</p>

<p>One particularity that stands out to me is namespaces: containers that are used to organize classes and other related code. They’re interesting, but I didn’t find them useful for this example.</p>

<p>C# is also strict with classes, like Java. However, it does offer the possibility of making top-level statements in a single, unique file. Behind the scenes, it still wraps the code in a class, though. I think C# has trust issues and needs counseling.</p>

<p>And like TypeScript, the setup was tedious, and I needed external files for my use case: Calculator.csproj and Tests.csproj.</p>

<p>Calculator.cs:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// IMPORTS</span>
<span class="c1">// =======</span>

<span class="k">using</span> <span class="nn">System</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Text.RegularExpressions</span><span class="p">;</span>

<span class="c1">// CLASS</span>
<span class="c1">// =====</span>

<span class="k">public</span> <span class="k">class</span> <span class="nc">Calculator</span>
<span class="p">{</span>

    <span class="c1">// FUNCTIONS</span>
    <span class="c1">// =========</span>

    <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">AskQuestion</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="n">Console</span><span class="p">.</span><span class="nf">Write</span><span class="p">(</span><span class="s">"Your calculation: "</span><span class="p">);</span>
        <span class="kt">string</span> <span class="n">calculation</span> <span class="p">=</span> <span class="n">Console</span><span class="p">.</span><span class="nf">ReadLine</span><span class="p">();</span>
        <span class="kt">string</span> <span class="n">result</span> <span class="p">=</span> <span class="nf">GetResult</span><span class="p">(</span><span class="n">calculation</span><span class="p">);</span>
        <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">" = "</span> <span class="p">+</span> <span class="n">result</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">static</span> <span class="kt">string</span> <span class="nf">GetResult</span><span class="p">(</span><span class="kt">string</span> <span class="n">calculation</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">calculation</span> <span class="p">=</span> <span class="nf">SanitizeCalculation</span><span class="p">(</span><span class="n">calculation</span><span class="p">);</span>
        <span class="kt">double</span> <span class="n">result</span> <span class="p">=</span> <span class="m">0.0</span><span class="p">;</span>
        
        <span class="k">foreach</span> <span class="p">(</span><span class="kt">string</span> <span class="n">i</span> <span class="k">in</span> <span class="n">calculation</span><span class="p">.</span><span class="nf">Split</span><span class="p">(</span><span class="s">"+"</span><span class="p">))</span>
        <span class="p">{</span>
            <span class="kt">double</span> <span class="n">subResult</span> <span class="p">=</span> <span class="m">1.0</span><span class="p">;</span>
            <span class="k">foreach</span> <span class="p">(</span><span class="kt">string</span> <span class="n">j</span> <span class="k">in</span> <span class="n">i</span><span class="p">.</span><span class="nf">Split</span><span class="p">(</span><span class="s">"*"</span><span class="p">))</span>
            <span class="p">{</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">j</span><span class="p">.</span><span class="nf">StartsWith</span><span class="p">(</span><span class="s">"1/"</span><span class="p">))</span>
                <span class="p">{</span>
                    <span class="kt">string</span> <span class="n">sanitizedJ</span> <span class="p">=</span> <span class="n">j</span><span class="p">.</span><span class="nf">Replace</span><span class="p">(</span><span class="s">"1/"</span><span class="p">,</span> <span class="s">""</span><span class="p">);</span>
                    <span class="k">if</span> <span class="p">(</span><span class="kt">double</span><span class="p">.</span><span class="nf">Parse</span><span class="p">(</span><span class="n">sanitizedJ</span><span class="p">)</span> <span class="p">==</span> <span class="m">0</span><span class="p">)</span> <span class="k">return</span> <span class="s">"Undefined"</span><span class="p">;</span>
                    <span class="n">subResult</span> <span class="p">/=</span> <span class="kt">double</span><span class="p">.</span><span class="nf">Parse</span><span class="p">(</span><span class="n">sanitizedJ</span><span class="p">);</span>
                <span class="p">}</span>
                <span class="k">else</span>
                <span class="p">{</span>
                    <span class="n">subResult</span> <span class="p">*=</span> <span class="kt">double</span><span class="p">.</span><span class="nf">Parse</span><span class="p">(</span><span class="n">j</span><span class="p">);</span>
                <span class="p">}</span>
            <span class="p">}</span>
            <span class="n">result</span> <span class="p">+=</span> <span class="n">subResult</span><span class="p">;</span>
        <span class="p">}</span>
        
        <span class="k">return</span> <span class="n">result</span><span class="p">.</span><span class="nf">ToString</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="k">static</span> <span class="kt">string</span> <span class="nf">SanitizeCalculation</span><span class="p">(</span><span class="kt">string</span> <span class="n">calculation</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="kt">string</span> <span class="n">sanitized</span> <span class="p">=</span> <span class="n">Regex</span><span class="p">.</span><span class="nf">Replace</span><span class="p">(</span><span class="n">calculation</span><span class="p">,</span> <span class="s">@"\s+"</span><span class="p">,</span> <span class="s">""</span><span class="p">);</span>
        <span class="n">sanitized</span> <span class="p">=</span> <span class="n">Regex</span><span class="p">.</span><span class="nf">Replace</span><span class="p">(</span><span class="n">sanitized</span><span class="p">,</span> <span class="s">@"\++"</span><span class="p">,</span> <span class="s">"+"</span><span class="p">);</span>
        <span class="n">sanitized</span> <span class="p">=</span> <span class="n">Regex</span><span class="p">.</span><span class="nf">Replace</span><span class="p">(</span><span class="n">sanitized</span> <span class="p">,</span><span class="s">@"-+"</span><span class="p">,</span> <span class="s">"-"</span><span class="p">);</span>
        <span class="n">sanitized</span> <span class="p">=</span> <span class="n">Regex</span><span class="p">.</span><span class="nf">Replace</span><span class="p">(</span><span class="n">sanitized</span><span class="p">,</span> <span class="s">@"\*\+"</span><span class="p">,</span> <span class="s">"*"</span><span class="p">);</span>
        <span class="n">sanitized</span> <span class="p">=</span> <span class="n">Regex</span><span class="p">.</span><span class="nf">Replace</span><span class="p">(</span><span class="n">sanitized</span><span class="p">,</span> <span class="s">@"/\+"</span><span class="p">,</span> <span class="s">"/"</span><span class="p">);</span>
        <span class="n">sanitized</span> <span class="p">=</span> <span class="n">Regex</span><span class="p">.</span><span class="nf">Replace</span><span class="p">(</span><span class="n">sanitized</span><span class="p">,</span> <span class="s">@"\+-"</span><span class="p">,</span> <span class="s">"-"</span><span class="p">);</span>
        <span class="n">sanitized</span> <span class="p">=</span> <span class="n">Regex</span><span class="p">.</span><span class="nf">Replace</span><span class="p">(</span><span class="n">sanitized</span><span class="p">,</span> <span class="s">@"(\d)-(\d)"</span><span class="p">,</span> <span class="s">"$1+-$2"</span><span class="p">);</span>
        <span class="n">sanitized</span> <span class="p">=</span> <span class="n">Regex</span><span class="p">.</span><span class="nf">Replace</span><span class="p">(</span><span class="n">sanitized</span><span class="p">,</span> <span class="s">@"/"</span><span class="p">,</span> <span class="s">"*1/"</span><span class="p">);</span>
        <span class="k">return</span> <span class="n">sanitized</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// MAIN</span>
    <span class="c1">// ====</span>

    <span class="k">static</span> <span class="k">void</span> <span class="nf">Main</span><span class="p">(</span><span class="kt">string</span><span class="p">[]</span> <span class="n">args</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">Calculator</span><span class="p">.</span><span class="nf">AskQuestion</span><span class="p">();</span>
    <span class="p">}</span>

<span class="p">}</span>
</code></pre></div></div>

<p>Tests.cs:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// IMPORTS</span>
<span class="c1">// =======</span>

<span class="k">using</span> <span class="nn">System</span><span class="p">;</span>

<span class="c1">// CLASS</span>
<span class="c1">// =====</span>

<span class="k">public</span> <span class="k">class</span> <span class="nc">Tests</span>
<span class="p">{</span>

    <span class="c1">// FUNCTIONS</span>
    <span class="c1">// =========</span>

    <span class="k">static</span> <span class="k">void</span> <span class="nf">RunTests</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"Test 01: "</span> <span class="p">+</span> <span class="p">(</span><span class="n">Calculator</span><span class="p">.</span><span class="nf">GetResult</span><span class="p">(</span><span class="s">"2 + 3"</span><span class="p">)</span> <span class="p">==</span> <span class="p">(</span><span class="m">2</span> <span class="p">+</span> <span class="m">3</span><span class="p">).</span><span class="nf">ToString</span><span class="p">()));</span>
        <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"Test 02: "</span> <span class="p">+</span> <span class="p">(</span><span class="n">Calculator</span><span class="p">.</span><span class="nf">GetResult</span><span class="p">(</span><span class="s">"2 - 3"</span><span class="p">)</span> <span class="p">==</span> <span class="p">(</span><span class="m">2</span> <span class="p">-</span> <span class="m">3</span><span class="p">).</span><span class="nf">ToString</span><span class="p">()));</span>
        <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"Test 03: "</span> <span class="p">+</span> <span class="p">(</span><span class="n">Calculator</span><span class="p">.</span><span class="nf">GetResult</span><span class="p">(</span><span class="s">"2 * 3"</span><span class="p">)</span> <span class="p">==</span> <span class="p">(</span><span class="m">2</span> <span class="p">*</span> <span class="m">3</span><span class="p">).</span><span class="nf">ToString</span><span class="p">()));</span>
        <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"Test 04: "</span> <span class="p">+</span> <span class="p">(</span><span class="n">Calculator</span><span class="p">.</span><span class="nf">GetResult</span><span class="p">(</span><span class="s">"2 / 3"</span><span class="p">)</span> <span class="p">==</span> <span class="p">(</span><span class="m">2.0</span> <span class="p">/</span> <span class="m">3.0</span><span class="p">).</span><span class="nf">ToString</span><span class="p">()));</span>
        <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"Test 05: "</span> <span class="p">+</span> <span class="p">(</span><span class="n">Calculator</span><span class="p">.</span><span class="nf">GetResult</span><span class="p">(</span><span class="s">"2 / 0"</span><span class="p">)</span> <span class="p">==</span> <span class="s">"Undefined"</span><span class="p">));</span>
        <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"Test 06: "</span> <span class="p">+</span> <span class="p">(</span><span class="n">Calculator</span><span class="p">.</span><span class="nf">GetResult</span><span class="p">(</span><span class="s">"  7 +   2 * 3 - 4 / -2 "</span><span class="p">)</span> <span class="p">==</span> <span class="p">(</span><span class="m">7</span> <span class="p">+</span> <span class="m">2</span> <span class="p">*</span> <span class="m">3</span> <span class="p">-</span> <span class="m">4.0</span> <span class="p">/</span> <span class="p">-</span><span class="m">2</span><span class="p">).</span><span class="nf">ToString</span><span class="p">()));</span>
        <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"Test 07: "</span> <span class="p">+</span> <span class="p">(</span><span class="n">Calculator</span><span class="p">.</span><span class="nf">GetResult</span><span class="p">(</span><span class="s">"  7 +   2 / 3 - 4 * +-2 "</span><span class="p">)</span> <span class="p">==</span> <span class="p">(</span><span class="m">7</span> <span class="p">+</span> <span class="m">2.0</span> <span class="p">/</span> <span class="m">3</span> <span class="p">-</span> <span class="m">4</span> <span class="p">*</span> <span class="p">-</span><span class="m">2</span><span class="p">).</span><span class="nf">ToString</span><span class="p">()));</span>
        <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"Test 08: "</span> <span class="p">+</span> <span class="p">(</span><span class="n">Calculator</span><span class="p">.</span><span class="nf">GetResult</span><span class="p">(</span><span class="s">"2.0 + 3.0"</span><span class="p">)</span> <span class="p">==</span> <span class="p">(</span><span class="m">2.0</span> <span class="p">+</span> <span class="m">3.0</span><span class="p">).</span><span class="nf">ToString</span><span class="p">()));</span>
    <span class="p">}</span>

    <span class="c1">// MAIN</span>
    <span class="c1">// ====</span>

    <span class="k">static</span> <span class="k">void</span> <span class="nf">Main</span><span class="p">(</span><span class="kt">string</span><span class="p">[]</span> <span class="n">args</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nf">RunTests</span><span class="p">();</span>
    <span class="p">}</span>

<span class="p">}</span>
</code></pre></div></div>

<p>Calculator.csproj:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;Project</span> <span class="na">Sdk=</span><span class="s">"Microsoft.NET.Sdk"</span><span class="nt">&gt;</span>

  <span class="nt">&lt;PropertyGroup&gt;</span>
    <span class="nt">&lt;OutputType&gt;</span>Exe<span class="nt">&lt;/OutputType&gt;</span>
    <span class="nt">&lt;TargetFramework&gt;</span>net8.0<span class="nt">&lt;/TargetFramework&gt;</span>
    <span class="nt">&lt;Nullable&gt;</span>enable<span class="nt">&lt;/Nullable&gt;</span>
    <span class="nt">&lt;StartupObject&gt;</span>Calculator<span class="nt">&lt;/StartupObject&gt;</span>
    <span class="nt">&lt;EnableDefaultCompileItems&gt;</span>false<span class="nt">&lt;/EnableDefaultCompileItems&gt;</span>
  <span class="nt">&lt;/PropertyGroup&gt;</span>

  <span class="nt">&lt;ItemGroup&gt;</span>
    <span class="nt">&lt;Compile</span> <span class="na">Include=</span><span class="s">"Calculator.cs"</span> <span class="nt">/&gt;</span>
  <span class="nt">&lt;/ItemGroup&gt;</span>

<span class="nt">&lt;/Project&gt;</span>
</code></pre></div></div>

<p>Tests.csproj:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;Project</span> <span class="na">Sdk=</span><span class="s">"Microsoft.NET.Sdk"</span><span class="nt">&gt;</span>

  <span class="nt">&lt;PropertyGroup&gt;</span>
    <span class="nt">&lt;OutputType&gt;</span>Exe<span class="nt">&lt;/OutputType&gt;</span>
    <span class="nt">&lt;TargetFramework&gt;</span>net8.0<span class="nt">&lt;/TargetFramework&gt;</span>
    <span class="nt">&lt;Nullable&gt;</span>enable<span class="nt">&lt;/Nullable&gt;</span>
    <span class="nt">&lt;StartupObject&gt;</span>Tests<span class="nt">&lt;/StartupObject&gt;</span>
    <span class="nt">&lt;EnableDefaultCompileItems&gt;</span>false<span class="nt">&lt;/EnableDefaultCompileItems&gt;</span>
  <span class="nt">&lt;/PropertyGroup&gt;</span>

  <span class="nt">&lt;ItemGroup&gt;</span>
    <span class="nt">&lt;Compile</span> <span class="na">Include=</span><span class="s">"Calculator.cs"</span> <span class="nt">/&gt;</span>
    <span class="nt">&lt;Compile</span> <span class="na">Include=</span><span class="s">"Tests.cs"</span> <span class="nt">/&gt;</span>
  <span class="nt">&lt;/ItemGroup&gt;</span>

<span class="nt">&lt;/Project&gt;</span>
</code></pre></div></div>

<h2 id="c-1">C++</h2>

<p>In my mind, after binary, it goes like Assembly → C → C++, the holy trinity.</p>

<p>I didn’t go into this part with excitement, but I was miles away from being right. C++ was… easy. It has some simple yet powerful features that are still very useful, like the <code class="language-plaintext highlighter-rouge">ifdef</code>/<code class="language-plaintext highlighter-rouge">ifndef</code> macros. With great power comes great responsibility. Maybe I could’ve used them to simplify my C# code, but it’s too late; I already wasted my time.</p>

<p>I found that the code looks and works surprisingly similarly to Java. I copied and pasted a part from the latter to the former, made some minor syntax changes, and it worked like magic when I wasn’t expecting it.</p>

<p>calculator.cpp:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// IMPORTS</span>
<span class="c1">// =======</span>

<span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;regex&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;sstream&gt;</span><span class="cp">
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>

<span class="c1">// FUNCTIONS</span>
<span class="c1">// =========</span>

<span class="n">string</span> <span class="nf">sanitizeCalculation</span><span class="p">(</span><span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">calculation</span><span class="p">);</span>
<span class="n">string</span> <span class="nf">getResult</span><span class="p">(</span><span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">calculation</span><span class="p">);</span>

<span class="kt">void</span> <span class="nf">askQuestion</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">string</span> <span class="n">calculation</span><span class="p">;</span>
    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Your calculation: "</span><span class="p">;</span>
    <span class="n">getline</span><span class="p">(</span><span class="n">cin</span><span class="p">,</span> <span class="n">calculation</span><span class="p">);</span>
    <span class="n">string</span> <span class="n">result</span> <span class="o">=</span> <span class="n">getResult</span><span class="p">(</span><span class="n">calculation</span><span class="p">);</span>
    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">" = "</span> <span class="o">&lt;&lt;</span> <span class="n">result</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">string</span> <span class="n">getResult</span><span class="p">(</span><span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">calculation</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">string</span> <span class="n">sanitized</span> <span class="o">=</span> <span class="n">sanitizeCalculation</span><span class="p">(</span><span class="n">calculation</span><span class="p">);</span>
    <span class="kt">double</span> <span class="n">result</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span>
    
    <span class="n">stringstream</span> <span class="n">ss</span><span class="p">(</span><span class="n">sanitized</span><span class="p">);</span>
    <span class="n">string</span> <span class="n">i</span><span class="p">;</span>
    <span class="k">while</span> <span class="p">(</span><span class="n">getline</span><span class="p">(</span><span class="n">ss</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="sc">'+'</span><span class="p">))</span> <span class="p">{</span>
        <span class="kt">double</span> <span class="n">subResult</span> <span class="o">=</span> <span class="mf">1.0</span><span class="p">;</span>
        <span class="n">stringstream</span> <span class="n">ss2</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
        <span class="n">string</span> <span class="n">j</span><span class="p">;</span>
        <span class="k">while</span> <span class="p">(</span><span class="n">getline</span><span class="p">(</span><span class="n">ss2</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="sc">'*'</span><span class="p">))</span> <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">j</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="s">"1/"</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">string</span> <span class="n">sanitizedJ</span> <span class="o">=</span> <span class="n">j</span><span class="p">.</span><span class="n">substr</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
                <span class="kt">double</span> <span class="n">divisor</span> <span class="o">=</span> <span class="n">stod</span><span class="p">(</span><span class="n">sanitizedJ</span><span class="p">);</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">divisor</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="s">"Undefined"</span><span class="p">;</span>
                <span class="n">subResult</span> <span class="o">/=</span> <span class="n">divisor</span><span class="p">;</span>
            <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">j</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span> <span class="p">{</span>
                <span class="n">subResult</span> <span class="o">*=</span> <span class="n">stod</span><span class="p">(</span><span class="n">j</span><span class="p">);</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="n">result</span> <span class="o">+=</span> <span class="n">subResult</span><span class="p">;</span>
    <span class="p">}</span>
    
    <span class="k">if</span> <span class="p">(</span><span class="n">result</span> <span class="o">==</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span> <span class="n">result</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">calculation</span><span class="p">.</span><span class="n">contains</span><span class="p">(</span><span class="s">"."</span><span class="p">))</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">to_string</span><span class="p">((</span><span class="kt">int</span><span class="p">)</span> <span class="n">result</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="n">to_string</span><span class="p">(</span><span class="n">result</span><span class="p">);</span>
<span class="p">}</span>

<span class="n">string</span> <span class="n">sanitizeCalculation</span><span class="p">(</span><span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">calculation</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">string</span> <span class="n">result</span> <span class="o">=</span> <span class="n">calculation</span><span class="p">;</span>
    <span class="n">result</span> <span class="o">=</span> <span class="n">regex_replace</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">regex</span><span class="p">(</span><span class="s">"</span><span class="se">\\</span><span class="s">s+"</span><span class="p">),</span> <span class="s">""</span><span class="p">);</span>                <span class="c1">// Remove all spaces</span>
    <span class="n">result</span> <span class="o">=</span> <span class="n">regex_replace</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">regex</span><span class="p">(</span><span class="s">"</span><span class="se">\\</span><span class="s">++"</span><span class="p">),</span> <span class="s">"+"</span><span class="p">);</span>               <span class="c1">// ++ -&gt; +</span>
    <span class="n">result</span> <span class="o">=</span> <span class="n">regex_replace</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">regex</span><span class="p">(</span><span class="s">"-+"</span><span class="p">),</span> <span class="s">"-"</span><span class="p">);</span>                 <span class="c1">// -- -&gt; -</span>
    <span class="n">result</span> <span class="o">=</span> <span class="n">regex_replace</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">regex</span><span class="p">(</span><span class="s">"</span><span class="se">\\</span><span class="s">*</span><span class="se">\\</span><span class="s">+"</span><span class="p">),</span> <span class="s">"*"</span><span class="p">);</span>             <span class="c1">// *+ -&gt; *</span>
    <span class="n">result</span> <span class="o">=</span> <span class="n">regex_replace</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">regex</span><span class="p">(</span><span class="s">"/</span><span class="se">\\</span><span class="s">+"</span><span class="p">),</span> <span class="s">"/"</span><span class="p">);</span>               <span class="c1">// /+ -&gt; /</span>
    <span class="n">result</span> <span class="o">=</span> <span class="n">regex_replace</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">regex</span><span class="p">(</span><span class="s">"</span><span class="se">\\</span><span class="s">+-"</span><span class="p">),</span> <span class="s">"-"</span><span class="p">);</span>               <span class="c1">// +- -&gt; -</span>
    <span class="n">result</span> <span class="o">=</span> <span class="n">regex_replace</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">regex</span><span class="p">(</span><span class="s">"(</span><span class="se">\\</span><span class="s">d)-(</span><span class="se">\\</span><span class="s">d)"</span><span class="p">),</span> <span class="s">"$1+-$2"</span><span class="p">);</span>   <span class="c1">// a-b -&gt; a+-b</span>
    <span class="n">result</span> <span class="o">=</span> <span class="n">regex_replace</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">regex</span><span class="p">(</span><span class="s">"/"</span><span class="p">),</span> <span class="s">"*1/"</span><span class="p">);</span>                <span class="c1">// a/b -&gt; a*1/b</span>
    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
<span class="p">}</span>

<span class="c1">// MAIN</span>
<span class="c1">// ====</span>

<span class="cp">#ifndef NO_MAIN
</span><span class="kt">int</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">askQuestion</span><span class="p">();</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="cp">#endif
</span></code></pre></div></div>

<p>tests.cpp:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// IMPORTS</span>
<span class="c1">// =======</span>

<span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;string&gt;</span><span class="cp">
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>

<span class="c1">// FUNCTIONS</span>
<span class="c1">// =========</span>

<span class="n">string</span> <span class="nf">getResult</span><span class="p">(</span><span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">calculation</span><span class="p">);</span>

<span class="kt">void</span> <span class="nf">runTests</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Test 01: "</span> <span class="o">&lt;&lt;</span> <span class="p">(</span><span class="n">getResult</span><span class="p">(</span><span class="s">"2 + 3"</span><span class="p">)</span> <span class="o">==</span> <span class="n">to_string</span><span class="p">(</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">3</span><span class="p">))</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span>
    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Test 02: "</span> <span class="o">&lt;&lt;</span> <span class="p">(</span><span class="n">getResult</span><span class="p">(</span><span class="s">"2 - 3"</span><span class="p">)</span> <span class="o">==</span> <span class="n">to_string</span><span class="p">(</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">3</span><span class="p">))</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span>
    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Test 03: "</span> <span class="o">&lt;&lt;</span> <span class="p">(</span><span class="n">getResult</span><span class="p">(</span><span class="s">"2 * 3"</span><span class="p">)</span> <span class="o">==</span> <span class="n">to_string</span><span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span><span class="p">))</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span>
    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Test 04: "</span> <span class="o">&lt;&lt;</span> <span class="p">(</span><span class="n">getResult</span><span class="p">(</span><span class="s">"2 / 3"</span><span class="p">)</span> <span class="o">==</span> <span class="n">to_string</span><span class="p">(</span><span class="mf">2.0</span> <span class="o">/</span> <span class="mi">3</span><span class="p">))</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span>
    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Test 05: "</span> <span class="o">&lt;&lt;</span> <span class="p">(</span><span class="n">getResult</span><span class="p">(</span><span class="s">"2 / 0"</span><span class="p">)</span> <span class="o">==</span> <span class="s">"Undefined"</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span>
    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Test 06: "</span> <span class="o">&lt;&lt;</span> <span class="p">(</span><span class="n">getResult</span><span class="p">(</span><span class="s">"  7 +   2 * 3 - 4 / -2 "</span><span class="p">)</span> <span class="o">==</span> <span class="n">to_string</span><span class="p">(</span>  <span class="mi">7</span> <span class="o">+</span>   <span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">/</span> <span class="o">-</span><span class="mi">2</span> <span class="p">))</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span>
    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Test 07: "</span> <span class="o">&lt;&lt;</span> <span class="p">(</span><span class="n">getResult</span><span class="p">(</span><span class="s">"  7 +   2 / 3 - 4 * +-2 "</span><span class="p">)</span> <span class="o">==</span> <span class="n">to_string</span><span class="p">(</span><span class="mi">7</span> <span class="o">+</span> <span class="mf">2.0</span> <span class="o">/</span> <span class="mi">3</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">-</span><span class="mi">2</span><span class="p">))</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span>
    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Test 08: "</span> <span class="o">&lt;&lt;</span> <span class="p">(</span><span class="n">getResult</span><span class="p">(</span><span class="s">"2.0 + 3.0"</span><span class="p">)</span> <span class="o">==</span> <span class="n">to_string</span><span class="p">(</span><span class="mf">2.0</span> <span class="o">+</span> <span class="mf">3.0</span><span class="p">))</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span>
<span class="p">}</span>

<span class="c1">// MAIN</span>
<span class="c1">// ====</span>

<span class="kt">int</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">runTests</span><span class="p">();</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="powershell">PowerShell</h2>

<p>The first language here to not require imports! Truthefully, this is not necessarily a good thing, but it’s definitely something to underline. Another interesting point to mention is that, unlike Bash and other shell dialects, this one doesn’t look so much like one.</p>

<p>It’s funny how Read-Host automatically adds the two dots after the input question. I genuinely feel stripped of my right to free speech.</p>

<p>calculator.ps1:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># FUNCTIONS</span><span class="w">
</span><span class="c"># =========</span><span class="w">

</span><span class="kr">function</span><span class="w"> </span><span class="nf">Ask-Question</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nv">$calculation</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Read-Host</span><span class="w"> </span><span class="s2">"Your calculation"</span><span class="w">
    </span><span class="nv">$result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Get-Result</span><span class="w"> </span><span class="nv">$calculation</span><span class="w">
    </span><span class="n">Write-Host</span><span class="w"> </span><span class="s2">" = </span><span class="nv">$result</span><span class="s2">"</span><span class="w">
</span><span class="p">}</span><span class="w">

</span><span class="kr">function</span><span class="w"> </span><span class="nf">Get-Result</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="kr">param</span><span class="p">([</span><span class="n">string</span><span class="p">]</span><span class="nv">$calculation</span><span class="p">)</span><span class="w">
    
    </span><span class="nv">$calculation</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Sanitize-Calculation</span><span class="w"> </span><span class="nv">$calculation</span><span class="w">
    </span><span class="nv">$result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.0</span><span class="w">
    
    </span><span class="kr">foreach</span><span class="w"> </span><span class="p">(</span><span class="nv">$i</span><span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="p">(</span><span class="nv">$calculation</span><span class="w"> </span><span class="o">-split</span><span class="w"> </span><span class="s1">'\+'</span><span class="p">))</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nv">$subResult</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1.0</span><span class="w">
        </span><span class="kr">foreach</span><span class="w"> </span><span class="p">(</span><span class="nv">$j</span><span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="p">(</span><span class="nv">$i</span><span class="w"> </span><span class="o">-split</span><span class="w"> </span><span class="s1">'\*'</span><span class="p">))</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="kr">if</span><span class="w"> </span><span class="p">(</span><span class="nv">$j</span><span class="o">.</span><span class="nf">StartsWith</span><span class="p">(</span><span class="s2">"1/"</span><span class="p">))</span><span class="w"> </span><span class="p">{</span><span class="w">
                </span><span class="nv">$sanitizedJ</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nv">$j</span><span class="w"> </span><span class="o">-replace</span><span class="w"> </span><span class="s2">"1/"</span><span class="p">,</span><span class="w"> </span><span class="s2">""</span><span class="w">
                </span><span class="kr">if</span><span class="w"> </span><span class="p">([</span><span class="n">double</span><span class="p">]</span><span class="nv">$sanitizedJ</span><span class="w"> </span><span class="o">-eq</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kr">return</span><span class="w"> </span><span class="s2">"Undefined"</span><span class="w"> </span><span class="p">}</span><span class="w">
                </span><span class="nv">$subResult</span><span class="w"> </span><span class="n">/</span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="n">double</span><span class="p">]</span><span class="nv">$sanitizedJ</span><span class="w">
            </span><span class="p">}</span><span class="w"> </span><span class="kr">elseif</span><span class="w"> </span><span class="p">(</span><span class="nv">$j</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
                </span><span class="nv">$subResult</span><span class="w"> </span><span class="o">*=</span><span class="w"> </span><span class="p">[</span><span class="n">double</span><span class="p">]</span><span class="nv">$j</span><span class="w">
            </span><span class="p">}</span><span class="w">
        </span><span class="p">}</span><span class="w">
        </span><span class="nv">$result</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nv">$subResult</span><span class="w">
    </span><span class="p">}</span><span class="w">
    
    </span><span class="c"># .NET General format specifier with 15 significant digits</span><span class="w">
    </span><span class="kr">return</span><span class="w"> </span><span class="nv">$result</span><span class="o">.</span><span class="nf">ToString</span><span class="p">(</span><span class="s2">"G15"</span><span class="p">)</span><span class="w">
</span><span class="p">}</span><span class="w">

</span><span class="kr">function</span><span class="w"> </span><span class="nf">Sanitize-Calculation</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="kr">param</span><span class="p">([</span><span class="n">string</span><span class="p">]</span><span class="nv">$calculation</span><span class="p">)</span><span class="w">

    </span><span class="nv">$result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nv">$calculation</span><span class="w">
    </span><span class="nv">$result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nv">$result</span><span class="w"> </span><span class="o">-replace</span><span class="w"> </span><span class="s1">'\s+'</span><span class="p">,</span><span class="w"> </span><span class="s2">""</span><span class="w">                </span><span class="c"># Remove all spaces</span><span class="w">
    </span><span class="nv">$result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nv">$result</span><span class="w"> </span><span class="o">-replace</span><span class="w"> </span><span class="s1">'\++'</span><span class="p">,</span><span class="w"> </span><span class="s2">"+"</span><span class="w">               </span><span class="c"># ++ -&gt; +</span><span class="w">
    </span><span class="nv">$result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nv">$result</span><span class="w"> </span><span class="o">-replace</span><span class="w"> </span><span class="s1">'-+'</span><span class="p">,</span><span class="w"> </span><span class="s2">"-"</span><span class="w">                </span><span class="c"># -- -&gt; -</span><span class="w">
    </span><span class="nv">$result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nv">$result</span><span class="w"> </span><span class="o">-replace</span><span class="w"> </span><span class="s1">'\*\+'</span><span class="p">,</span><span class="w"> </span><span class="s2">"*"</span><span class="w">              </span><span class="c"># *+ -&gt; *</span><span class="w">
    </span><span class="nv">$result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nv">$result</span><span class="w"> </span><span class="o">-replace</span><span class="w"> </span><span class="s1">'/\+'</span><span class="p">,</span><span class="w"> </span><span class="s2">"/"</span><span class="w">               </span><span class="c"># /+ -&gt; /</span><span class="w">
    </span><span class="nv">$result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nv">$result</span><span class="w"> </span><span class="o">-replace</span><span class="w"> </span><span class="s1">'\+-'</span><span class="p">,</span><span class="w"> </span><span class="s2">"-"</span><span class="w">               </span><span class="c"># +- -&gt; -</span><span class="w">
    </span><span class="nv">$result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nv">$result</span><span class="w"> </span><span class="o">-replace</span><span class="w"> </span><span class="s1">'(\d)-(\d)'</span><span class="p">,</span><span class="w"> </span><span class="s1">'$1+-$2'</span><span class="w">    </span><span class="c"># a-b -&gt; a+-b</span><span class="w">
    </span><span class="nv">$result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nv">$result</span><span class="w"> </span><span class="o">-replace</span><span class="w"> </span><span class="s1">'/'</span><span class="p">,</span><span class="w"> </span><span class="s2">"*1/"</span><span class="w">               </span><span class="c"># a/b -&gt; a*1/b</span><span class="w">
    </span><span class="kr">return</span><span class="w"> </span><span class="nv">$result</span><span class="w">
</span><span class="p">}</span><span class="w">

</span><span class="c"># MAIN</span><span class="w">
</span><span class="c"># ====</span><span class="w">

</span><span class="kr">if</span><span class="w"> </span><span class="p">((</span><span class="n">Get-PSCallStack</span><span class="p">)</span><span class="o">.</span><span class="nf">Count</span><span class="w"> </span><span class="o">-eq</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="n">Ask-Question</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>tests.ps1:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># IMPORTS</span><span class="w">
</span><span class="c"># =======</span><span class="w">

</span><span class="o">.</span><span class="w"> </span><span class="o">.</span><span class="n">/calculator.ps1</span><span class="w">

</span><span class="c"># FUNCTIONS</span><span class="w">
</span><span class="c"># =========</span><span class="w">

</span><span class="kr">function</span><span class="w"> </span><span class="nf">Run-Tests</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="n">Write-Host</span><span class="w"> </span><span class="p">(</span><span class="s2">"Test 01: "</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="err">$</span><span class="p">(</span><span class="n">Get-Result</span><span class="w"> </span><span class="s2">"2 + 3"</span><span class="p">)</span><span class="w"> </span><span class="o">-eq</span><span class="w"> </span><span class="s2">"</span><span class="si">$(</span><span class="mi">2</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">3</span><span class="si">)</span><span class="s2">"</span><span class="p">))</span><span class="w">
    </span><span class="n">Write-Host</span><span class="w"> </span><span class="p">(</span><span class="s2">"Test 02: "</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="err">$</span><span class="p">(</span><span class="n">Get-Result</span><span class="w"> </span><span class="s2">"2 - 3"</span><span class="p">)</span><span class="w"> </span><span class="o">-eq</span><span class="w"> </span><span class="s2">"</span><span class="si">$(</span><span class="mi">2</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">3</span><span class="si">)</span><span class="s2">"</span><span class="p">))</span><span class="w">
    </span><span class="n">Write-Host</span><span class="w"> </span><span class="p">(</span><span class="s2">"Test 03: "</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="err">$</span><span class="p">(</span><span class="n">Get-Result</span><span class="w"> </span><span class="s2">"2 * 3"</span><span class="p">)</span><span class="w"> </span><span class="o">-eq</span><span class="w"> </span><span class="s2">"</span><span class="si">$(</span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">3</span><span class="si">)</span><span class="s2">"</span><span class="p">))</span><span class="w">
    </span><span class="n">Write-Host</span><span class="w"> </span><span class="p">(</span><span class="s2">"Test 04: "</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="err">$</span><span class="p">(</span><span class="n">Get-Result</span><span class="w"> </span><span class="s2">"2 / 3"</span><span class="p">)</span><span class="w"> </span><span class="o">-eq</span><span class="w"> </span><span class="s2">"</span><span class="si">$(</span><span class="mi">2</span><span class="w"> </span><span class="n">/</span><span class="w"> </span><span class="nx">3</span><span class="p">)</span><span class="s2">"))
    Write-Host ("</span><span class="n">Test</span><span class="w"> </span><span class="nx">05:</span><span class="w"> </span><span class="s2">" + (</span><span class="si">$(</span><span class="n">Get-Result</span><span class="w"> </span><span class="s2">"2 / 0"</span><span class="p">)</span><span class="w"> </span><span class="o">-eq</span><span class="w"> </span><span class="s2">"Undefined"</span><span class="si">)</span><span class="s2">)
    Write-Host ("</span><span class="nx">Test</span><span class="w"> </span><span class="nx">06:</span><span class="w"> </span><span class="s2">" + (</span><span class="si">$(</span><span class="n">Get-Result</span><span class="w"> </span><span class="s2">"  7 +   2 * 3 - 4 / -2 "</span><span class="p">)</span><span class="w"> </span><span class="o">-eq</span><span class="w"> </span><span class="s2">"</span><span class="si">$(</span><span class="w">  </span><span class="mi">7</span><span class="w"> </span><span class="o">+</span><span class="w">   </span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="n">/</span><span class="w"> </span><span class="nt">-2</span><span class="w"> </span><span class="p">)</span><span class="s2">"))
    Write-Host ("</span><span class="n">Test</span><span class="w"> </span><span class="nx">07:</span><span class="w"> </span><span class="s2">" + (</span><span class="si">$(</span><span class="n">Get-Result</span><span class="w"> </span><span class="s2">"  7 +   2 / 3 - 4 * +-2 "</span><span class="p">)</span><span class="w"> </span><span class="o">-eq</span><span class="w"> </span><span class="s2">"</span><span class="si">$(</span><span class="w">  </span><span class="mi">7</span><span class="w"> </span><span class="o">+</span><span class="w">   </span><span class="mi">2</span><span class="w"> </span><span class="n">/</span><span class="w"> </span><span class="nx">3</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">4</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nt">-2</span><span class="w"> </span><span class="p">)</span><span class="s2">"))
    Write-Host ("</span><span class="n">Test</span><span class="w"> </span><span class="nx">08:</span><span class="w"> </span><span class="s2">" + (</span><span class="si">$(</span><span class="n">Get-Result</span><span class="w"> </span><span class="s2">"2.0 + 3.0"</span><span class="p">)</span><span class="w"> </span><span class="o">-eq</span><span class="w"> </span><span class="s2">"</span><span class="si">$(</span><span class="mf">2.0</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">3.0</span><span class="si">)</span><span class="s2">"</span><span class="si">)</span><span class="s2">)
}

# MAIN
# ====

if ((Get-PSCallStack).Count -eq 1) {
    Run-Tests
}
</span></code></pre></div></div>

<h2 id="c-2">C</h2>

<p>Coding in C++ was like a very pleasant ride in a Rolls-Royce Phantom III. Coding in C is like that same car on the country’s bumpiest road. Oh, and the car has no tires.</p>

<p>Reading C code is a pain. Writing it too. I did use some AI for other languages, but, for this one, I had to go all out and trust it with my soul. Not that I had any soul left after witnessing this eye-soaring code. Thankfully, I’m not doing Assembly any time soon, right? Right? (Spoiler: I am in part 2).</p>

<p>There’s also very strict float/int separation, and no implicit type casting. For instance, 2/3 is always 0, because what was an integer stays an integer. It’s the same for C++, so I had to adapt the tests accordingly.</p>

<p>calculator.c:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// DEFINITIONS</span>
<span class="c1">// ===========</span>

<span class="c1">//  Expose the POSIX.1-2008 API set (for strtok_r)</span>
<span class="cp">#define _POSIX_C_SOURCE 200809L
</span>
<span class="c1">// IMPORTS</span>
<span class="c1">// =======</span>

<span class="cp">#include</span> <span class="cpf">&lt;ctype.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
</span>
<span class="c1">// FUNCTIONS</span>
<span class="c1">// =========</span>

<span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="nf">replace_all</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">input</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">pattern</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">replacement</span><span class="p">);</span>
<span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="nf">remove_spaces</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">input</span><span class="p">);</span>
<span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="nf">rewrite_digit_minus_digit</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">input</span><span class="p">);</span>
<span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="nf">sanitize_calculation</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">calculation</span><span class="p">);</span>
<span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="nf">format_double</span><span class="p">(</span><span class="kt">double</span> <span class="n">value</span><span class="p">);</span>

<span class="k">static</span> <span class="kt">void</span> <span class="nf">ask_question</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span>
<span class="kt">char</span> <span class="o">*</span><span class="nf">get_result</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">calculation</span><span class="p">);</span>

<span class="k">static</span> <span class="kt">void</span> <span class="nf">ask_question</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="mi">256</span><span class="p">];</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"Your calculation: "</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">fgets</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buffer</span><span class="p">),</span> <span class="n">stdin</span><span class="p">)</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">buffer</span><span class="p">[</span><span class="n">strcspn</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">)]</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span>
        <span class="kt">char</span> <span class="o">*</span><span class="n">result</span> <span class="o">=</span> <span class="n">get_result</span><span class="p">(</span><span class="n">buffer</span><span class="p">);</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">" = %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">result</span><span class="p">);</span>
        <span class="n">free</span><span class="p">(</span><span class="n">result</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kt">char</span> <span class="o">*</span><span class="nf">get_result</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">calculation</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">sanitized</span> <span class="o">=</span> <span class="n">sanitize_calculation</span><span class="p">(</span><span class="n">calculation</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">sanitized</span><span class="p">)</span> <span class="k">return</span> <span class="n">strdup</span><span class="p">(</span><span class="s">"Undefined"</span><span class="p">);</span>

    <span class="kt">double</span> <span class="n">result</span> <span class="o">=</span> <span class="mi">0</span><span class="p">.</span><span class="mi">0</span><span class="p">;</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">save_i</span><span class="p">;</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">i</span> <span class="o">=</span> <span class="n">strtok_r</span><span class="p">(</span><span class="n">sanitized</span><span class="p">,</span> <span class="s">"+"</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">save_i</span><span class="p">);</span> <span class="n">i</span><span class="p">;</span> <span class="n">i</span> <span class="o">=</span> <span class="n">strtok_r</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="s">"+"</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">save_i</span><span class="p">))</span> <span class="p">{</span>
        <span class="kt">double</span> <span class="n">sub_result</span> <span class="o">=</span> <span class="mi">1</span><span class="p">.</span><span class="mi">0</span><span class="p">;</span>
        <span class="kt">char</span> <span class="o">*</span><span class="n">save_j</span><span class="p">;</span>
        <span class="k">for</span> <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">j</span> <span class="o">=</span> <span class="n">strtok_r</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="s">"*"</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">save_j</span><span class="p">);</span> <span class="n">j</span><span class="p">;</span> <span class="n">j</span> <span class="o">=</span> <span class="n">strtok_r</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="s">"*"</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">save_j</span><span class="p">))</span> <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">strncmp</span><span class="p">(</span><span class="n">j</span><span class="p">,</span> <span class="s">"1/"</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
                <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">sanitized_j</span> <span class="o">=</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">2</span><span class="p">;</span>
                <span class="kt">double</span> <span class="n">divisor</span> <span class="o">=</span> <span class="n">strtod</span><span class="p">(</span><span class="n">sanitized_j</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">divisor</span> <span class="o">==</span> <span class="mi">0</span><span class="p">.</span><span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
                    <span class="n">free</span><span class="p">(</span><span class="n">sanitized</span><span class="p">);</span>
                    <span class="k">return</span> <span class="n">strdup</span><span class="p">(</span><span class="s">"Undefined"</span><span class="p">);</span>
                <span class="p">}</span>
                <span class="n">sub_result</span> <span class="o">/=</span> <span class="n">divisor</span><span class="p">;</span>
            <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">j</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">'\0'</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">sub_result</span> <span class="o">*=</span> <span class="n">strtod</span><span class="p">(</span><span class="n">j</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="n">result</span> <span class="o">+=</span> <span class="n">sub_result</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">free</span><span class="p">(</span><span class="n">sanitized</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">format_double</span><span class="p">(</span><span class="n">result</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="nf">sanitize_calculation</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">calculation</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">result</span> <span class="o">=</span> <span class="n">remove_spaces</span><span class="p">(</span><span class="n">calculation</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">result</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>

    <span class="kt">char</span> <span class="o">*</span><span class="n">tmp</span><span class="p">;</span>

    <span class="n">tmp</span> <span class="o">=</span> <span class="n">replace_all</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="s">"++"</span><span class="p">,</span> <span class="s">"+"</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">result</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">tmp</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
    <span class="n">result</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span>

    <span class="n">tmp</span> <span class="o">=</span> <span class="n">replace_all</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="s">"-+"</span><span class="p">,</span> <span class="s">"-"</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">result</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">tmp</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
    <span class="n">result</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span>

    <span class="n">tmp</span> <span class="o">=</span> <span class="n">replace_all</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="s">"*+"</span><span class="p">,</span> <span class="s">"*"</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">result</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">tmp</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
    <span class="n">result</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span>

    <span class="n">tmp</span> <span class="o">=</span> <span class="n">replace_all</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="s">"/+"</span><span class="p">,</span> <span class="s">"/"</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">result</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">tmp</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
    <span class="n">result</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span>

    <span class="n">tmp</span> <span class="o">=</span> <span class="n">replace_all</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="s">"+-"</span><span class="p">,</span> <span class="s">"-"</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">result</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">tmp</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
    <span class="n">result</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span>

    <span class="n">tmp</span> <span class="o">=</span> <span class="n">rewrite_digit_minus_digit</span><span class="p">(</span><span class="n">result</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">result</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">tmp</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
    <span class="n">result</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span>

    <span class="n">tmp</span> <span class="o">=</span> <span class="n">replace_all</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="s">"/"</span><span class="p">,</span> <span class="s">"*1/"</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">result</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">tmp</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
    <span class="n">result</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span>

    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="nf">remove_spaces</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">input</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">size_t</span> <span class="n">len</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">(</span><span class="n">input</span><span class="p">);</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">out</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="n">len</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">out</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>

    <span class="kt">size_t</span> <span class="n">idx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">isspace</span><span class="p">((</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="p">)</span><span class="n">input</span><span class="p">[</span><span class="n">i</span><span class="p">]))</span> <span class="p">{</span>
            <span class="n">out</span><span class="p">[</span><span class="n">idx</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">input</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
        <span class="p">}</span>
    <span class="p">}</span>
    <span class="n">out</span><span class="p">[</span><span class="n">idx</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span>
    <span class="k">return</span> <span class="n">out</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="nf">replace_all</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">input</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">pattern</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">replacement</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">size_t</span> <span class="n">input_len</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">(</span><span class="n">input</span><span class="p">);</span>
    <span class="kt">size_t</span> <span class="n">pat_len</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">(</span><span class="n">pattern</span><span class="p">);</span>
    <span class="kt">size_t</span> <span class="n">rep_len</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">(</span><span class="n">replacement</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">pat_len</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="n">strdup</span><span class="p">(</span><span class="n">input</span><span class="p">);</span>

    <span class="kt">size_t</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">cursor</span> <span class="o">=</span> <span class="n">input</span><span class="p">;</span>
    <span class="k">while</span> <span class="p">((</span><span class="n">cursor</span> <span class="o">=</span> <span class="n">strstr</span><span class="p">(</span><span class="n">cursor</span><span class="p">,</span> <span class="n">pattern</span><span class="p">))</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
        <span class="o">++</span><span class="n">count</span><span class="p">;</span>
        <span class="n">cursor</span> <span class="o">+=</span> <span class="n">pat_len</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="kt">size_t</span> <span class="n">new_len</span> <span class="o">=</span> <span class="n">input_len</span> <span class="o">+</span> <span class="n">count</span> <span class="o">*</span> <span class="p">(</span><span class="n">rep_len</span> <span class="o">-</span> <span class="n">pat_len</span><span class="p">);</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">out</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="n">new_len</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">out</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>

    <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">read_ptr</span> <span class="o">=</span> <span class="n">input</span><span class="p">;</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">write_ptr</span> <span class="o">=</span> <span class="n">out</span><span class="p">;</span>
    <span class="k">while</span> <span class="p">((</span><span class="n">cursor</span> <span class="o">=</span> <span class="n">strstr</span><span class="p">(</span><span class="n">read_ptr</span><span class="p">,</span> <span class="n">pattern</span><span class="p">))</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
        <span class="kt">size_t</span> <span class="n">segment_len</span> <span class="o">=</span> <span class="p">(</span><span class="kt">size_t</span><span class="p">)(</span><span class="n">cursor</span> <span class="o">-</span> <span class="n">read_ptr</span><span class="p">);</span>
        <span class="n">memcpy</span><span class="p">(</span><span class="n">write_ptr</span><span class="p">,</span> <span class="n">read_ptr</span><span class="p">,</span> <span class="n">segment_len</span><span class="p">);</span>
        <span class="n">write_ptr</span> <span class="o">+=</span> <span class="n">segment_len</span><span class="p">;</span>
        <span class="n">memcpy</span><span class="p">(</span><span class="n">write_ptr</span><span class="p">,</span> <span class="n">replacement</span><span class="p">,</span> <span class="n">rep_len</span><span class="p">);</span>
        <span class="n">write_ptr</span> <span class="o">+=</span> <span class="n">rep_len</span><span class="p">;</span>
        <span class="n">read_ptr</span> <span class="o">=</span> <span class="n">cursor</span> <span class="o">+</span> <span class="n">pat_len</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="n">strcpy</span><span class="p">(</span><span class="n">write_ptr</span><span class="p">,</span> <span class="n">read_ptr</span><span class="p">);</span>

    <span class="k">return</span> <span class="n">out</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="nf">rewrite_digit_minus_digit</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">input</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">size_t</span> <span class="n">len</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">(</span><span class="n">input</span><span class="p">);</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">out</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="n">len</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">out</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>

    <span class="kt">size_t</span> <span class="n">idx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
        <span class="kt">char</span> <span class="n">c</span> <span class="o">=</span> <span class="n">input</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">c</span> <span class="o">==</span> <span class="sc">'-'</span> <span class="o">&amp;&amp;</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&lt;</span> <span class="n">len</span> <span class="o">&amp;&amp;</span> <span class="n">isdigit</span><span class="p">((</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="p">)</span><span class="n">input</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="o">&amp;&amp;</span> <span class="n">isdigit</span><span class="p">((</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="p">)</span><span class="n">input</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]))</span> <span class="p">{</span>
            <span class="n">out</span><span class="p">[</span><span class="n">idx</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'+'</span><span class="p">;</span>
            <span class="n">out</span><span class="p">[</span><span class="n">idx</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'-'</span><span class="p">;</span>
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
            <span class="n">out</span><span class="p">[</span><span class="n">idx</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">c</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>
    <span class="n">out</span><span class="p">[</span><span class="n">idx</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span>
    <span class="k">return</span> <span class="n">out</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="nf">format_double</span><span class="p">(</span><span class="kt">double</span> <span class="n">value</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="mi">64</span><span class="p">];</span>
    <span class="n">snprintf</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buffer</span><span class="p">),</span> <span class="s">"%.15g"</span><span class="p">,</span> <span class="n">value</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">strdup</span><span class="p">(</span><span class="n">buffer</span><span class="p">);</span>
<span class="p">}</span>

<span class="c1">// MAIN</span>
<span class="c1">// ====</span>

<span class="cp">#ifndef NO_MAIN
</span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">ask_question</span><span class="p">();</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="cp">#endif
</span></code></pre></div></div>

<p>tests.c:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// IMPORTS</span>
<span class="c1">// =======</span>

<span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
</span>
<span class="c1">// FUNCTIONS</span>
<span class="c1">// =========</span>

<span class="kt">char</span> <span class="o">*</span><span class="nf">get_result</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">calculation</span><span class="p">);</span>
<span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="nf">format_double</span><span class="p">(</span><span class="kt">double</span> <span class="n">value</span><span class="p">);</span>
<span class="k">static</span> <span class="kt">void</span> <span class="nf">run_tests</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span>

<span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="nf">format_double</span><span class="p">(</span><span class="kt">double</span> <span class="n">value</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="mi">64</span><span class="p">];</span>
    <span class="n">snprintf</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buffer</span><span class="p">),</span> <span class="s">"%.15g"</span><span class="p">,</span> <span class="n">value</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">strdup</span><span class="p">(</span><span class="n">buffer</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">static</span> <span class="kt">void</span> <span class="nf">run_tests</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">expected</span><span class="p">;</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">actual</span><span class="p">;</span>

    <span class="n">expected</span> <span class="o">=</span> <span class="n">format_double</span><span class="p">(</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">3</span><span class="p">);</span>
    <span class="n">actual</span> <span class="o">=</span> <span class="n">get_result</span><span class="p">(</span><span class="s">"2 + 3"</span><span class="p">);</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"Test 01: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">strcmp</span><span class="p">(</span><span class="n">actual</span><span class="p">,</span> <span class="n">expected</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">expected</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">actual</span><span class="p">);</span>

    <span class="n">expected</span> <span class="o">=</span> <span class="n">format_double</span><span class="p">(</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">3</span><span class="p">);</span>
    <span class="n">actual</span> <span class="o">=</span> <span class="n">get_result</span><span class="p">(</span><span class="s">"2 - 3"</span><span class="p">);</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"Test 02: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">strcmp</span><span class="p">(</span><span class="n">actual</span><span class="p">,</span> <span class="n">expected</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">expected</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">actual</span><span class="p">);</span>

    <span class="n">expected</span> <span class="o">=</span> <span class="n">format_double</span><span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span><span class="p">);</span>
    <span class="n">actual</span> <span class="o">=</span> <span class="n">get_result</span><span class="p">(</span><span class="s">"2 * 3"</span><span class="p">);</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"Test 03: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">strcmp</span><span class="p">(</span><span class="n">actual</span><span class="p">,</span> <span class="n">expected</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">expected</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">actual</span><span class="p">);</span>

    <span class="n">expected</span> <span class="o">=</span> <span class="n">format_double</span><span class="p">(</span><span class="mi">2</span><span class="p">.</span><span class="mi">0</span> <span class="o">/</span> <span class="mi">3</span><span class="p">);</span>
    <span class="n">actual</span> <span class="o">=</span> <span class="n">get_result</span><span class="p">(</span><span class="s">"2 / 3"</span><span class="p">);</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"Test 04: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">strcmp</span><span class="p">(</span><span class="n">actual</span><span class="p">,</span> <span class="n">expected</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">expected</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">actual</span><span class="p">);</span>

    <span class="n">actual</span> <span class="o">=</span> <span class="n">get_result</span><span class="p">(</span><span class="s">"2 / 0"</span><span class="p">);</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"Test 05: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">strcmp</span><span class="p">(</span><span class="n">actual</span><span class="p">,</span> <span class="s">"Undefined"</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">actual</span><span class="p">);</span>

    <span class="n">expected</span> <span class="o">=</span> <span class="n">format_double</span><span class="p">(</span>  <span class="mi">7</span> <span class="o">+</span>   <span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">/</span> <span class="o">-</span><span class="mi">2</span> <span class="p">);</span>
    <span class="n">actual</span> <span class="o">=</span> <span class="n">get_result</span><span class="p">(</span><span class="s">"  7 +   2 * 3 - 4 / -2 "</span><span class="p">);</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"Test 06: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">strcmp</span><span class="p">(</span><span class="n">actual</span><span class="p">,</span> <span class="n">expected</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">expected</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">actual</span><span class="p">);</span>

    <span class="n">expected</span> <span class="o">=</span> <span class="n">format_double</span><span class="p">(</span>  <span class="mi">7</span> <span class="o">+</span>   <span class="mi">2</span><span class="p">.</span><span class="mi">0</span> <span class="o">/</span> <span class="mi">3</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">+-</span><span class="mi">2</span> <span class="p">);</span>
    <span class="n">actual</span> <span class="o">=</span> <span class="n">get_result</span><span class="p">(</span><span class="s">"  7 +   2 / 3 - 4 * +-2 "</span><span class="p">);</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"Test 07: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">strcmp</span><span class="p">(</span><span class="n">actual</span><span class="p">,</span> <span class="n">expected</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">expected</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">actual</span><span class="p">);</span>

    <span class="n">expected</span> <span class="o">=</span> <span class="n">format_double</span><span class="p">(</span><span class="mi">2</span><span class="p">.</span><span class="mi">0</span> <span class="o">+</span> <span class="mi">3</span><span class="p">.</span><span class="mi">0</span><span class="p">);</span>
    <span class="n">actual</span> <span class="o">=</span> <span class="n">get_result</span><span class="p">(</span><span class="s">"2.0 + 3.0"</span><span class="p">);</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"Test 08: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">strcmp</span><span class="p">(</span><span class="n">actual</span><span class="p">,</span> <span class="n">expected</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">expected</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">actual</span><span class="p">);</span>
<span class="p">}</span>

<span class="c1">// MAIN</span>
<span class="c1">// ====</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">run_tests</span><span class="p">();</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="php">PHP</h2>

<p><code class="language-plaintext highlighter-rouge">&lt;?php</code>, what a weird thing to put at the beginning of a file. That’s the opening tag used to denote the beginning of PHP code. <code class="language-plaintext highlighter-rouge">?&gt;</code> is the closing tag, but I didn’t use it and probably shouldn’t, since omitting the closing tag is just one solution for avoiding blanks and other characters at the end of the file. All code outside these tags is typically regarded as HTML code in web servers, so any character accidentally added after the closing tag could trigger an error.</p>

<p>I’m quite surprised that PHP is still as popular. In my mind, it was wrongfully like COBOL. I’m exaggerating, don’t take it too seriously. I could’ve compared it to even older: Fortran!</p>

<p>I like the function name for splitting a string: explode. Sounds a bit threatening though…</p>

<p>calculator.php:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>

<span class="c1">// FUNCTIONS</span>
<span class="c1">// =========</span>

<span class="k">function</span> <span class="n">askQuestion</span><span class="p">():</span> <span class="kt">void</span> <span class="p">{</span>
    <span class="nv">$calculation</span> <span class="o">=</span> <span class="nb">readline</span><span class="p">(</span><span class="s2">"Your calculation: "</span><span class="p">);</span>
    <span class="nv">$result</span> <span class="o">=</span> <span class="nf">getResult</span><span class="p">(</span><span class="nv">$calculation</span><span class="p">);</span>
    <span class="k">echo</span> <span class="s2">" = </span><span class="nv">$result</span><span class="se">\n</span><span class="s2">"</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">function</span> <span class="n">getResult</span><span class="p">(</span><span class="kt">string</span> <span class="nv">$calculation</span><span class="p">):</span> <span class="kt">string</span> <span class="p">{</span>
    <span class="nv">$calculation</span> <span class="o">=</span> <span class="nf">sanitizeCalculation</span><span class="p">(</span><span class="nv">$calculation</span><span class="p">);</span>
    <span class="nv">$result</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span>

    <span class="k">foreach</span> <span class="p">(</span><span class="nb">explode</span><span class="p">(</span><span class="s1">'+'</span><span class="p">,</span> <span class="nv">$calculation</span><span class="p">)</span> <span class="k">as</span> <span class="nv">$i</span><span class="p">)</span> <span class="p">{</span>
        <span class="nv">$subResult</span> <span class="o">=</span> <span class="mf">1.0</span><span class="p">;</span>
        <span class="k">foreach</span> <span class="p">(</span><span class="nb">explode</span><span class="p">(</span><span class="s1">'*'</span><span class="p">,</span> <span class="nv">$i</span><span class="p">)</span> <span class="k">as</span> <span class="nv">$j</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="nb">strpos</span><span class="p">(</span><span class="nv">$j</span><span class="p">,</span> <span class="s1">'1/'</span><span class="p">)</span> <span class="o">===</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
                <span class="nv">$sanitizedJ</span> <span class="o">=</span> <span class="nb">substr</span><span class="p">(</span><span class="nv">$j</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>
                <span class="k">if</span> <span class="p">((</span><span class="n">float</span><span class="p">)</span><span class="nv">$sanitizedJ</span> <span class="o">==</span> <span class="mf">0.0</span><span class="p">)</span> <span class="p">{</span>
                    <span class="k">return</span> <span class="s2">"Undefined"</span><span class="p">;</span>
                <span class="p">}</span>
                <span class="nv">$subResult</span> <span class="o">/=</span> <span class="p">(</span><span class="n">float</span><span class="p">)</span><span class="nv">$sanitizedJ</span><span class="p">;</span>
            <span class="p">}</span> <span class="k">elseif</span> <span class="p">(</span><span class="nv">$j</span> <span class="o">!==</span> <span class="s1">''</span><span class="p">)</span> <span class="p">{</span>
                <span class="nv">$subResult</span> <span class="o">*=</span> <span class="p">(</span><span class="n">float</span><span class="p">)</span><span class="nv">$j</span><span class="p">;</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="nv">$result</span> <span class="o">+=</span> <span class="nv">$subResult</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="p">(</span><span class="n">string</span><span class="p">)</span><span class="nv">$result</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">function</span> <span class="n">sanitizeCalculation</span><span class="p">(</span><span class="kt">string</span> <span class="nv">$calculation</span><span class="p">):</span> <span class="kt">string</span> <span class="p">{</span>
    <span class="nv">$result</span> <span class="o">=</span> <span class="nv">$calculation</span><span class="p">;</span>
    <span class="nv">$result</span> <span class="o">=</span> <span class="nb">preg_replace</span><span class="p">(</span><span class="s1">'/\s+/'</span><span class="p">,</span> <span class="s1">''</span><span class="p">,</span> <span class="nv">$result</span><span class="p">);</span>               <span class="c1">// Remove all spaces</span>
    <span class="nv">$result</span> <span class="o">=</span> <span class="nb">preg_replace</span><span class="p">(</span><span class="s1">'/\++/'</span><span class="p">,</span> <span class="s1">'+'</span><span class="p">,</span> <span class="nv">$result</span><span class="p">);</span>              <span class="c1">// ++ -&gt; +</span>
    <span class="nv">$result</span> <span class="o">=</span> <span class="nb">preg_replace</span><span class="p">(</span><span class="s1">'/-+/'</span><span class="p">,</span> <span class="s1">'-'</span><span class="p">,</span> <span class="nv">$result</span><span class="p">);</span>               <span class="c1">// -- -&gt; -</span>
    <span class="nv">$result</span> <span class="o">=</span> <span class="nb">preg_replace</span><span class="p">(</span><span class="s1">'/\*\+/'</span><span class="p">,</span> <span class="s1">'*'</span><span class="p">,</span> <span class="nv">$result</span><span class="p">);</span>             <span class="c1">// *+ -&gt; *</span>
    <span class="nv">$result</span> <span class="o">=</span> <span class="nb">preg_replace</span><span class="p">(</span><span class="s1">'/\/\+/'</span><span class="p">,</span> <span class="s1">'/'</span><span class="p">,</span> <span class="nv">$result</span><span class="p">);</span>             <span class="c1">// /+ -&gt; /</span>
    <span class="nv">$result</span> <span class="o">=</span> <span class="nb">preg_replace</span><span class="p">(</span><span class="s1">'/\+-/'</span><span class="p">,</span> <span class="s1">'-'</span><span class="p">,</span> <span class="nv">$result</span><span class="p">);</span>              <span class="c1">// +- -&gt; -</span>
    <span class="nv">$result</span> <span class="o">=</span> <span class="nb">preg_replace</span><span class="p">(</span><span class="s1">'/(\d)-(\d)/'</span><span class="p">,</span> <span class="s1">'$1+-$2'</span><span class="p">,</span> <span class="nv">$result</span><span class="p">);</span>   <span class="c1">// a-b -&gt; a+-b</span>
    <span class="nv">$result</span> <span class="o">=</span> <span class="nb">preg_replace</span><span class="p">(</span><span class="s1">'/\//'</span><span class="p">,</span> <span class="s1">'*1/'</span><span class="p">,</span> <span class="nv">$result</span><span class="p">);</span>             <span class="c1">// a/b -&gt; a*1/b</span>
    <span class="k">return</span> <span class="nv">$result</span><span class="p">;</span>
<span class="p">}</span>

<span class="c1">// MAIN</span>
<span class="c1">// ====</span>

<span class="k">if</span> <span class="p">(</span><span class="k">__FILE__</span> <span class="o">===</span> <span class="nb">realpath</span><span class="p">(</span><span class="nv">$_SERVER</span><span class="p">[</span><span class="s1">'SCRIPT_FILENAME'</span><span class="p">]))</span> <span class="p">{</span>
    <span class="nf">askQuestion</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>tests.php:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>

<span class="c1">// IMPORTS</span>
<span class="c1">// =======</span>

<span class="k">require_once</span> <span class="k">__DIR__</span> <span class="mf">.</span> <span class="s1">'/calculator.php'</span><span class="p">;</span>

<span class="c1">// FUNCTIONS</span>
<span class="c1">// =========</span>

<span class="k">function</span> <span class="n">runTests</span><span class="p">():</span> <span class="kt">void</span> <span class="p">{</span>
    <span class="k">echo</span> <span class="s2">"Test 01: "</span> <span class="mf">.</span> <span class="p">(</span><span class="nf">getResult</span><span class="p">(</span><span class="s2">"2 + 3"</span><span class="p">)</span> <span class="o">===</span> <span class="p">(</span><span class="n">string</span><span class="p">)(</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">3</span><span class="p">))</span> <span class="mf">.</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">;</span>
    <span class="k">echo</span> <span class="s2">"Test 02: "</span> <span class="mf">.</span> <span class="p">(</span><span class="nf">getResult</span><span class="p">(</span><span class="s2">"2 - 3"</span><span class="p">)</span> <span class="o">===</span> <span class="p">(</span><span class="n">string</span><span class="p">)(</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">3</span><span class="p">))</span> <span class="mf">.</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">;</span>
    <span class="k">echo</span> <span class="s2">"Test 03: "</span> <span class="mf">.</span> <span class="p">(</span><span class="nf">getResult</span><span class="p">(</span><span class="s2">"2 * 3"</span><span class="p">)</span> <span class="o">===</span> <span class="p">(</span><span class="n">string</span><span class="p">)(</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span><span class="p">))</span> <span class="mf">.</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">;</span>
    <span class="k">echo</span> <span class="s2">"Test 04: "</span> <span class="mf">.</span> <span class="p">(</span><span class="nf">getResult</span><span class="p">(</span><span class="s2">"2 / 3"</span><span class="p">)</span> <span class="o">===</span> <span class="p">(</span><span class="n">string</span><span class="p">)(</span><span class="mi">2</span> <span class="o">/</span> <span class="mi">3</span><span class="p">))</span> <span class="mf">.</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">;</span>
    <span class="k">echo</span> <span class="s2">"Test 05: "</span> <span class="mf">.</span> <span class="p">(</span><span class="nf">getResult</span><span class="p">(</span><span class="s2">"2 / 0"</span><span class="p">)</span> <span class="o">===</span> <span class="s2">"Undefined"</span><span class="p">)</span> <span class="mf">.</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">;</span>
    <span class="k">echo</span> <span class="s2">"Test 06: "</span> <span class="mf">.</span> <span class="p">(</span><span class="nf">getResult</span><span class="p">(</span><span class="s2">"  7 +   2 * 3 - 4 / -2 "</span><span class="p">)</span> <span class="o">===</span> <span class="p">(</span><span class="n">string</span><span class="p">)(</span>  <span class="mi">7</span> <span class="o">+</span>   <span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">/</span> <span class="o">-</span><span class="mi">2</span> <span class="p">))</span> <span class="mf">.</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">;</span>
    <span class="k">echo</span> <span class="s2">"Test 07: "</span> <span class="mf">.</span> <span class="p">(</span><span class="nf">getResult</span><span class="p">(</span><span class="s2">"  7 +   2 / 3 - 4 * +-2 "</span><span class="p">)</span> <span class="o">===</span> <span class="p">(</span><span class="n">string</span><span class="p">)(</span>  <span class="mi">7</span> <span class="o">+</span>   <span class="mi">2</span> <span class="o">/</span> <span class="mi">3</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">+-</span><span class="mi">2</span> <span class="p">))</span> <span class="mf">.</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">;</span>
    <span class="k">echo</span> <span class="s2">"Test 08: "</span> <span class="mf">.</span> <span class="p">(</span><span class="nf">getResult</span><span class="p">(</span><span class="s2">"2.0 + 3.0"</span><span class="p">)</span> <span class="o">===</span> <span class="p">(</span><span class="n">string</span><span class="p">)(</span><span class="mf">2.0</span> <span class="o">+</span> <span class="mf">3.0</span><span class="p">))</span> <span class="mf">.</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">;</span>
<span class="p">}</span>

<span class="c1">// MAIN</span>
<span class="c1">// ====</span>

<span class="k">if</span> <span class="p">(</span><span class="k">__FILE__</span> <span class="o">===</span> <span class="nb">realpath</span><span class="p">(</span><span class="nv">$_SERVER</span><span class="p">[</span><span class="s1">'SCRIPT_FILENAME'</span><span class="p">]))</span> <span class="p">{</span>
    <span class="nf">runTests</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="whats-next">What’s next?</h2>

<p>Part 2, with the remaining most popular languages!</p>]]></content><author><name>Peter Yaacoub</name></author><category term="articles" /><category term="code-dome" /><summary type="html"><![CDATA[Introduction]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://yaacoub.github.io/social.webp" /><media:content medium="image" url="https://yaacoub.github.io/social.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">One SwiftUI App, Six Architectures</title><link href="https://yaacoub.github.io/articles/swift-tip/one-swiftui-app-six-architectures/" rel="alternate" type="text/html" title="One SwiftUI App, Six Architectures" /><published>2025-12-08T00:00:00+00:00</published><updated>2025-12-08T00:00:00+00:00</updated><id>https://yaacoub.github.io/articles/swift-tip/one-swiftui-app-six-architectures</id><content type="html" xml:base="https://yaacoub.github.io/articles/swift-tip/one-swiftui-app-six-architectures/"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>What’s the best architecture for SwiftUI? This question always sparks endless debate in the iOS development community. Today, I finally decided to cut through the theory by building a simple task manager app six times. Yes, you read it right: SIX times. One app, six different architectures.</p>

<p>First things first, I’m no architecture expert, and I’ll never pretend to be one. If you find mistakes or disagree with my following methods, reasoning, or learning, I’ll be happy to get your feedback via email or social media. For most of the following, it will be my first time dabbling in, so be indulgent!</p>

<p>To start this new journey, I began with an initial list of 12 candidates. After realizing that many overlapped, I instead turned my focus to the ones that felt the most interesting and popular to me. I’m not hiding the fact that I used AI assistants to help clarify each architecture’s philosophy and implementation. With their strengths, some offering strong starting points, others distinguishing subtle differences, and IDE-integrated AI helping with debugging, I was ready to compare these options head-to-head.</p>

<h2 id="whats-the-difference-between-architecture-and-design-patterns">What’s the difference between architecture and design patterns?</h2>

<p>The terms are often used interchangeably, including in this article, but there’s a subtle distinction worth understanding.</p>

<p>Design patterns solve specific code challenges: ensuring a single existing instance (Singleton), notifying multiple objects of changes (Observer)… In contrast, architectural patterns refer to the high-level organization of the entire application: its data, business logic, navigation handling,…</p>

<p>An architecture like MVVM uses the Observer pattern for data binding, and a Clean Architecture might use Repository and Factory patterns for data access.</p>

<p>Now that this is out of the way, let’s build the same task manager six different ways, ordered by a progression that felt logical as I learned.</p>

<h2 id="model-view-controller-mvc">Model-View-Controller (MVC)</h2>

<p>MVC was invented by Trygve Reenskaug at the Xerox Palo Alto Research Center in the late 70s for Smalltalk, making it one of the oldest architectural patterns in software development. The name simply describes its three core components: <strong>Model</strong> (data), <strong>View</strong> (UI), and <strong>Controller</strong> (logic coordinator).</p>

<p>Apple embraced MVC as the primary pattern for both macOS and iOS development, deeply integrating it into UIKit with <code class="language-plaintext highlighter-rouge">UIViewController</code>. It remained dominant throughout the 2010s, though it was criticized for producing “Massive View Controllers” in complex apps. This is caused by Apple’s tight coupling of Views and Controllers, unlike classical MVC, where both are peers. Even though it still plays a role in older and hybrid codebases, MVC is less prominent today due to SwiftUI’s declarative approach.</p>

<p>So, is MVC still compatible with SwiftUI? You’ll get the answer to that question in just a few minutes!</p>

<h3 id="file-structure">File structure</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>MVC/
├── MVCApp.swift
├── 1 - Models/
│   └── Task.swift
├── 2 - Views/
│   └── TaskListView.swift
└── 3 - Controllers/
    └── TaskController.swift

</code></pre></div></div>

<p>The structure is straightforward: Models define data, Views display the UI, and Controllers coordinate between them. In this simple task manager, all logic resides in the <code class="language-plaintext highlighter-rouge">TaskController</code>, which the View observes for state changes, enabling the UI to automatically update when the underlying data is modified.</p>

<h3 id="implementation">Implementation</h3>

<p>Well, actually, there’s no implementation. When I initially wrote the code for this part, it really looked like MVVM, and I didn’t understand why or even the difference between the two. It’s only after a lot of research that I finally understood.</p>

<p>In MVC, the Controller holds references to Views and controls their layout. This supposes that Views are classes, which is not the case in SwiftUI. It also implies that Views are actual views, and always. Not a set of either layout constraints, layers, or views. Just views.</p>

<h2 id="model-view-viewmodel-mvvm">Model-View-ViewModel (MVVM)</h2>

<p>MVVM was created by Microsoft architects John Gossman and Ken Cooper around 2005 for WPF (Windows Presentation Foundation) and Silverlight. The <strong>ViewModel</strong> sits as the mediator between the View and Model, exposing data and commands in a View-friendly format.</p>

<p>MVVM gained serious traction in the iOS community around 2015 with the rise of Swift 2 and reactive programming. It then truly took off with SwiftUI’s launch. Currently, MVVM is the most common baseline architecture for SwiftUI apps, especially for small to medium-sized projects. It’s often the recommended approach and feels natural with SwiftUI’s declarative syntax and reactive nature.</p>

<h3 id="file-structure-1">File structure</h3>

<p>Almost identical to MVC’s structure, here the ViewModel replaces the Controller.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>MVVM/
├── MVVMApp.swift
├── 1 - Models/
│   └── Task.swift
├── 2 - Views/
│   └── TaskListView.swift
└── 3 - ViewModels/
    └── TaskListViewModel.swift

</code></pre></div></div>

<h3 id="implementation-1">Implementation</h3>

<p>In MVVM, the ViewModel exposes observable properties that the View binds to. The View automatically updates itself through these bindings. The ViewModel doesn’t “control” the View; it just tells it that a change was made.</p>

<p>Tasks.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">Foundation</span>

<span class="kd">struct</span> <span class="kt">Task</span><span class="p">:</span> <span class="kt">Identifiable</span> <span class="p">{</span>
    <span class="k">let</span> <span class="nv">id</span><span class="p">:</span> <span class="kt">UUID</span> <span class="o">=</span> <span class="kt">UUID</span><span class="p">()</span>
    <span class="k">var</span> <span class="nv">title</span><span class="p">:</span> <span class="kt">String</span>
    <span class="k">var</span> <span class="nv">isDone</span><span class="p">:</span> <span class="kt">Bool</span> <span class="o">=</span> <span class="kc">false</span>
<span class="p">}</span>

</code></pre></div></div>

<p>TaskListView.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">SwiftUI</span>

<span class="kd">struct</span> <span class="kt">TaskListView</span><span class="p">:</span> <span class="kt">View</span> <span class="p">{</span>
    <span class="kd">@State</span> <span class="kd">private</span> <span class="k">var</span> <span class="nv">viewModel</span> <span class="o">=</span> <span class="kt">TaskListViewModel</span><span class="p">()</span>
    
    <span class="k">var</span> <span class="nv">body</span><span class="p">:</span> <span class="kd">some</span> <span class="kt">View</span> <span class="p">{</span>
        <span class="kt">NavigationStack</span> <span class="p">{</span>
            <span class="kt">VStack</span> <span class="p">{</span>
                <span class="kt">HStack</span> <span class="p">{</span>
                    <span class="kt">TextField</span><span class="p">(</span><span class="s">"Enter a new task…"</span><span class="p">,</span> <span class="nv">text</span><span class="p">:</span> <span class="err">$</span><span class="n">viewModel</span><span class="o">.</span><span class="n">taskTitle</span><span class="p">)</span>
                        <span class="o">.</span><span class="nf">textFieldStyle</span><span class="p">(</span><span class="o">.</span><span class="n">roundedBorder</span><span class="p">)</span>
                        <span class="o">.</span><span class="nf">padding</span><span class="p">(</span><span class="o">.</span><span class="n">trailing</span><span class="p">)</span>
                    <span class="kt">Button</span><span class="p">(</span><span class="s">"Add"</span><span class="p">,</span> <span class="nv">action</span><span class="p">:</span> <span class="n">viewModel</span><span class="o">.</span><span class="n">addTask</span><span class="p">)</span>
                        <span class="o">.</span><span class="nf">buttonStyle</span><span class="p">(</span><span class="o">.</span><span class="n">borderedProminent</span><span class="p">)</span>
                <span class="p">}</span>
                <span class="o">.</span><span class="nf">padding</span><span class="p">()</span>
                
                <span class="kt">List</span> <span class="p">{</span>
                    <span class="kt">ForEach</span><span class="p">(</span><span class="n">viewModel</span><span class="o">.</span><span class="n">tasks</span><span class="p">)</span> <span class="p">{</span> <span class="n">task</span> <span class="k">in</span>
                        <span class="kt">HStack</span> <span class="p">{</span>
                            <span class="kt">Text</span><span class="p">(</span><span class="n">task</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
                            <span class="kt">Spacer</span><span class="p">()</span>
                            <span class="kt">Button</span><span class="p">(</span><span class="n">task</span><span class="o">.</span><span class="n">isDone</span> <span class="p">?</span> <span class="s">"✓"</span> <span class="p">:</span> <span class="s">"○"</span><span class="p">)</span> <span class="p">{</span>
                                <span class="n">viewModel</span><span class="o">.</span><span class="nf">toggleTask</span><span class="p">(</span><span class="n">task</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
                            <span class="p">}</span>
                        <span class="p">}</span>
                    <span class="p">}</span>
                    <span class="o">.</span><span class="nf">onDelete</span><span class="p">(</span><span class="nv">perform</span><span class="p">:</span> <span class="n">viewModel</span><span class="o">.</span><span class="n">deleteTask</span><span class="p">)</span>
                <span class="p">}</span>
                <span class="o">.</span><span class="nf">listStyle</span><span class="p">(</span><span class="o">.</span><span class="n">plain</span><span class="p">)</span>
            <span class="p">}</span>
            <span class="o">.</span><span class="nf">navigationTitle</span><span class="p">(</span><span class="s">"Tasks"</span><span class="p">)</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>

</code></pre></div></div>

<p>TaskListViewModel.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">Foundation</span>
<span class="kd">import</span> <span class="kt">Observation</span>

<span class="kd">@Observable</span>
<span class="kd">final</span> <span class="kd">class</span> <span class="kt">TaskListViewModel</span> <span class="p">{</span>
    <span class="kd">private(set)</span> <span class="k">var</span> <span class="nv">tasks</span><span class="p">:</span> <span class="p">[</span><span class="kt">Task</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="k">var</span> <span class="nv">taskTitle</span><span class="p">:</span> <span class="kt">String</span> <span class="o">=</span> <span class="s">""</span>
    
    <span class="kd">func</span> <span class="nf">addTask</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">guard</span> <span class="o">!</span><span class="n">taskTitle</span><span class="o">.</span><span class="n">isEmpty</span> <span class="k">else</span> <span class="p">{</span> <span class="k">return</span> <span class="p">}</span>
        <span class="k">let</span> <span class="nv">task</span> <span class="o">=</span> <span class="kt">Task</span><span class="p">(</span><span class="nv">title</span><span class="p">:</span> <span class="n">taskTitle</span><span class="p">)</span>
        <span class="n">tasks</span><span class="o">.</span><span class="nf">append</span><span class="p">(</span><span class="n">task</span><span class="p">)</span>
        <span class="n">taskTitle</span> <span class="o">=</span> <span class="s">""</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">toggleTask</span><span class="p">(</span><span class="n">_</span> <span class="nv">id</span><span class="p">:</span> <span class="kt">UUID</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">guard</span> <span class="k">let</span> <span class="nv">index</span> <span class="o">=</span> <span class="n">tasks</span><span class="o">.</span><span class="nf">firstIndex</span><span class="p">(</span><span class="nv">where</span><span class="p">:</span> <span class="p">{</span> <span class="nv">$0</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">id</span> <span class="p">})</span> <span class="k">else</span> <span class="p">{</span> <span class="k">return</span> <span class="p">}</span>
        <span class="n">tasks</span><span class="p">[</span><span class="n">index</span><span class="p">]</span><span class="o">.</span><span class="n">isDone</span><span class="o">.</span><span class="nf">toggle</span><span class="p">()</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">deleteTask</span><span class="p">(</span><span class="n">_</span> <span class="nv">indexSet</span><span class="p">:</span> <span class="kt">IndexSet</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">for</span> <span class="n">index</span> <span class="k">in</span> <span class="n">indexSet</span> <span class="p">{</span>
            <span class="n">tasks</span><span class="o">.</span><span class="nf">remove</span><span class="p">(</span><span class="nv">at</span><span class="p">:</span> <span class="n">index</span><span class="p">)</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>

</code></pre></div></div>

<h2 id="model-view-viewmodel--combine-mvvm">Model-View-ViewModel + Combine (MVVM)</h2>

<p>Ok, I cheated… this isn’t a separate architecture, but I just wanted to show that this was once the norm in SwiftUI. This pattern is MVVM implemented with reactive streams. <strong>Combine</strong> is Apple’s reactive programming framework, announced at WWDC 2019 alongside SwiftUI. It brought first-party support for reactive patterns that previously required third-party libraries like RxSwift. The name “Combine” actually refers to its ability to combine, transform, and react to asynchronous streams of values over time, all features not demonstrated in this simple example.</p>

<p>Introduced in 2023, SwiftUI’s @Observable macro has reduced the need for Combine in simple data flows and MVVM. However, Combine remains widely adopted for complex data flows, networking, timers, and multi-source data streams. One doesn’t always replace the other. Observable is for basic state, and Combine is for complex async operations.</p>

<h3 id="file-structure-2">File structure</h3>

<p>Identical structure to standard MVVM. The difference stands entirely on how the ViewModel publishes changes.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>MVVM/
├── MVVMApp.swift
├── 1 - Models/
│   └── Task.swift
├── 2 - Views/
│   └── TaskListView.swift
└── 3 - ViewModels/
    └── TaskListViewModel.swift

</code></pre></div></div>

<h3 id="implementation-2">Implementation</h3>

<p>TaskListView.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// ...</span>
<span class="kd">@StateObject</span> <span class="kd">private</span> <span class="k">var</span> <span class="nv">viewModel</span> <span class="o">=</span> <span class="kt">TaskListViewModel</span><span class="p">()</span>
<span class="c1">// ...</span>

</code></pre></div></div>

<p>TaskListViewModel.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">Foundation</span>
<span class="kd">import</span> <span class="kt">Combine</span>

<span class="kd">final</span> <span class="kd">class</span> <span class="kt">TaskListViewModel</span><span class="p">:</span> <span class="kt">ObservableObject</span> <span class="p">{</span>
    <span class="kd">@Published</span> <span class="kd">private(set)</span> <span class="k">var</span> <span class="nv">tasks</span><span class="p">:</span> <span class="p">[</span><span class="kt">Task</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="kd">@Published</span> <span class="k">var</span> <span class="nv">taskTitle</span><span class="p">:</span> <span class="kt">String</span> <span class="o">=</span> <span class="s">""</span>
    
    <span class="c1">// ...</span>
<span class="p">}</span>

</code></pre></div></div>

<h2 id="the-composable-architecture-tca">The Composable Architecture (TCA)</h2>

<p>TCA was created by Brandon Williams and Stephen Celis of Point-Free around 2020. It’s heavily inspired by the <strong>Elm</strong> Architecture (2012) and <strong>Redux</strong> (2015), bringing functional, unidirectional data flow to SwiftUI. The name emphasizes <strong>composability</strong>: the ability to break down features into independent, testable, and reusable components that compose together seamlessly.</p>

<p>This architecture is gaining momentum in the SwiftUI community, especially for complex apps requiring predictable state management. It’s become the go-to choice for teams wanting strict architectural guarantees.</p>

<p>As stated, TCA draws inspiration from Elm’s message-driven architecture and Redux’s single-source-of-truth model, adapted to Swift. It’s also similar to ReactorKit, an RxSwift-based and imperative architecture. All share core principles: single source of truth, unidirectional data flow, and pure reducers. Unidirectional data flow means data moves in one direction through the application: <strong>Actions → Reducer → State → View</strong>, and the chain repeats. Unlike bidirectional patterns where Views might directly modify state (creating unpredictable behavior), unidirectional flow enforces that strict path.</p>

<p>TCA’s completeness comes with a steep learning curve. Its implementation requires an external Swift Package, and the architecture was the hardest to implement. <strong>The idea, for large projects at least, is that you sacrifice initial development speed for long-term maintainability and correctness</strong>. For my quick task manager, TCA is way overkill. For a banking app with 50 features and 10 developers, TCA prevents chaos, hidden side effects, and race conditions.</p>

<h3 id="file-structure-3">File structure</h3>

<p>TCA organizes code by features rather than technical layers. Each feature is self-contained with its State, Action, Reducer, and View bundled together. The <code class="language-plaintext highlighter-rouge">Domain</code> folder holds shared models used across features.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>TCA/
├── TCAApp.swift
├── Domain/
│   └── Task.swift
└── Features/
    └── TaskList/
        ├── TaskListFeature.swift
        └── TaskListView.swift

</code></pre></div></div>

<h3 id="implementation-3">Implementation</h3>

<p>TaskListFeature.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">Foundation</span>
<span class="kd">import</span> <span class="kt">ComposableArchitecture</span>

<span class="kd">@Reducer</span>
<span class="kd">struct</span> <span class="kt">TaskListFeature</span><span class="p">:</span> <span class="kt">Reducer</span> <span class="p">{</span>
    <span class="kd">@ObservableState</span>
    <span class="kd">struct</span> <span class="kt">State</span> <span class="p">{</span>
        <span class="k">var</span> <span class="nv">tasks</span><span class="p">:</span> <span class="kt">IdentifiedArrayOf</span><span class="o">&lt;</span><span class="kt">Task</span><span class="o">&gt;</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">var</span> <span class="nv">taskTitle</span><span class="p">:</span> <span class="kt">String</span> <span class="o">=</span> <span class="s">""</span>
    <span class="p">}</span>
    
    <span class="kd">enum</span> <span class="kt">Action</span><span class="p">:</span> <span class="kt">BindableAction</span> <span class="p">{</span>
        <span class="k">case</span> <span class="nf">binding</span><span class="p">(</span><span class="kt">BindingAction</span><span class="o">&lt;</span><span class="kt">State</span><span class="o">&gt;</span><span class="p">)</span>
        <span class="k">case</span> <span class="n">addTask</span>
        <span class="k">case</span> <span class="nf">toggleTask</span><span class="p">(</span><span class="kt">UUID</span><span class="p">)</span>
        <span class="k">case</span> <span class="nf">deleteTask</span><span class="p">(</span><span class="kt">IndexSet</span><span class="p">)</span>
    <span class="p">}</span>
    
    <span class="k">var</span> <span class="nv">body</span><span class="p">:</span> <span class="kd">some</span> <span class="kt">Reducer</span><span class="o">&lt;</span><span class="kt">State</span><span class="p">,</span> <span class="kt">Action</span><span class="o">&gt;</span> <span class="p">{</span>
        <span class="kt">BindingReducer</span><span class="p">()</span>
        <span class="kt">Reduce</span> <span class="p">{</span> <span class="n">state</span><span class="p">,</span> <span class="n">action</span> <span class="k">in</span>
            <span class="k">switch</span> <span class="n">action</span> <span class="p">{</span>
            <span class="k">case</span> <span class="o">.</span><span class="nv">binding</span><span class="p">:</span>
                <span class="k">return</span> <span class="o">.</span><span class="k">none</span>
                
            <span class="k">case</span> <span class="o">.</span><span class="nv">addTask</span><span class="p">:</span>
                <span class="k">let</span> <span class="nv">task</span> <span class="o">=</span> <span class="kt">Task</span><span class="p">(</span><span class="nv">title</span><span class="p">:</span> <span class="n">state</span><span class="o">.</span><span class="n">taskTitle</span><span class="p">)</span>
                <span class="n">state</span><span class="o">.</span><span class="n">tasks</span><span class="o">.</span><span class="nf">append</span><span class="p">(</span><span class="n">task</span><span class="p">)</span>
                <span class="n">state</span><span class="o">.</span><span class="n">taskTitle</span> <span class="o">=</span> <span class="s">""</span>
                <span class="k">return</span> <span class="o">.</span><span class="k">none</span>
                
            <span class="k">case</span> <span class="o">.</span><span class="nf">toggleTask</span><span class="p">(</span><span class="k">let</span> <span class="nv">id</span><span class="p">):</span>
                <span class="k">guard</span> <span class="k">let</span> <span class="nv">id</span> <span class="o">=</span> <span class="n">state</span><span class="o">.</span><span class="n">tasks</span><span class="o">.</span><span class="nf">firstIndex</span><span class="p">(</span><span class="nv">where</span><span class="p">:</span> <span class="p">{</span> <span class="nv">$0</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">id</span> <span class="p">})</span> <span class="k">else</span> <span class="p">{</span> <span class="k">return</span> <span class="o">.</span><span class="k">none</span> <span class="p">}</span>
                <span class="n">state</span><span class="o">.</span><span class="n">tasks</span><span class="p">[</span><span class="n">id</span><span class="p">]</span><span class="o">.</span><span class="n">isDone</span><span class="o">.</span><span class="nf">toggle</span><span class="p">()</span>
                <span class="k">return</span> <span class="o">.</span><span class="k">none</span>
                
            <span class="k">case</span> <span class="o">.</span><span class="nf">deleteTask</span><span class="p">(</span><span class="k">let</span> <span class="nv">indexSet</span><span class="p">):</span>
                <span class="n">state</span><span class="o">.</span><span class="n">tasks</span><span class="o">.</span><span class="nf">remove</span><span class="p">(</span><span class="nv">atOffsets</span><span class="p">:</span> <span class="n">indexSet</span><span class="p">)</span>
                <span class="k">return</span> <span class="o">.</span><span class="k">none</span>
            <span class="p">}</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>

</code></pre></div></div>

<p>TaskListView.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">SwiftUI</span>
<span class="kd">import</span> <span class="kt">ComposableArchitecture</span>

<span class="kd">struct</span> <span class="kt">TaskListView</span><span class="p">:</span> <span class="kt">View</span> <span class="p">{</span>
    <span class="kd">@Bindable</span> <span class="k">var</span> <span class="nv">store</span><span class="p">:</span> <span class="kt">StoreOf</span><span class="o">&lt;</span><span class="kt">TaskListFeature</span><span class="o">&gt;</span>
    
    <span class="k">var</span> <span class="nv">body</span><span class="p">:</span> <span class="kd">some</span> <span class="kt">View</span> <span class="p">{</span>
        <span class="kt">NavigationStack</span> <span class="p">{</span>
            <span class="kt">VStack</span> <span class="p">{</span>
                <span class="kt">HStack</span> <span class="p">{</span>
                    <span class="kt">TextField</span><span class="p">(</span><span class="s">"Enter a new task…"</span><span class="p">,</span> <span class="nv">text</span><span class="p">:</span> <span class="err">$</span><span class="n">store</span><span class="o">.</span><span class="n">taskTitle</span><span class="p">)</span>
                        <span class="o">.</span><span class="nf">textFieldStyle</span><span class="p">(</span><span class="o">.</span><span class="n">roundedBorder</span><span class="p">)</span>
                        <span class="o">.</span><span class="nf">padding</span><span class="p">(</span><span class="o">.</span><span class="n">trailing</span><span class="p">)</span>
                    <span class="kt">Button</span><span class="p">(</span><span class="s">"Add"</span><span class="p">)</span> <span class="p">{</span>
                        <span class="n">store</span><span class="o">.</span><span class="nf">send</span><span class="p">(</span><span class="o">.</span><span class="n">addTask</span><span class="p">)</span>
                    <span class="p">}</span>
                    <span class="o">.</span><span class="nf">buttonStyle</span><span class="p">(</span><span class="o">.</span><span class="n">borderedProminent</span><span class="p">)</span>
                <span class="p">}</span>
                <span class="o">.</span><span class="nf">padding</span><span class="p">()</span>
                
                <span class="kt">List</span> <span class="p">{</span>
                    <span class="kt">ForEach</span><span class="p">(</span><span class="n">store</span><span class="o">.</span><span class="n">tasks</span><span class="p">)</span> <span class="p">{</span> <span class="n">task</span> <span class="k">in</span>
                        <span class="kt">HStack</span> <span class="p">{</span>
                            <span class="kt">Text</span><span class="p">(</span><span class="n">task</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
                            <span class="kt">Spacer</span><span class="p">()</span>
                            <span class="kt">Button</span><span class="p">(</span><span class="n">task</span><span class="o">.</span><span class="n">isDone</span> <span class="p">?</span> <span class="s">"✓"</span> <span class="p">:</span> <span class="s">"○"</span><span class="p">)</span> <span class="p">{</span>
                                <span class="n">store</span><span class="o">.</span><span class="nf">send</span><span class="p">(</span><span class="o">.</span><span class="nf">toggleTask</span><span class="p">(</span><span class="n">task</span><span class="o">.</span><span class="n">id</span><span class="p">))</span>
                            <span class="p">}</span>
                        <span class="p">}</span>
                    <span class="p">}</span>
                    <span class="o">.</span><span class="n">onDelete</span> <span class="p">{</span> <span class="n">indexSet</span> <span class="k">in</span>
                        <span class="n">store</span><span class="o">.</span><span class="nf">send</span><span class="p">(</span><span class="o">.</span><span class="nf">deleteTask</span><span class="p">(</span><span class="n">indexSet</span><span class="p">))</span>
                    <span class="p">}</span>
                <span class="p">}</span>
                <span class="o">.</span><span class="nf">listStyle</span><span class="p">(</span><span class="o">.</span><span class="n">plain</span><span class="p">)</span>
            <span class="p">}</span>
            <span class="o">.</span><span class="nf">navigationTitle</span><span class="p">(</span><span class="s">"Tasks"</span><span class="p">)</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>

</code></pre></div></div>

<p>TCAApp.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">SwiftUI</span>
<span class="kd">import</span> <span class="kt">ComposableArchitecture</span>

<span class="kd">@main</span>
<span class="kd">struct</span> <span class="kt">TCAApp</span><span class="p">:</span> <span class="kt">App</span> <span class="p">{</span>
    <span class="kd">static</span> <span class="k">let</span> <span class="nv">store</span> <span class="o">=</span> <span class="kt">Store</span><span class="p">(</span><span class="nv">initialState</span><span class="p">:</span> <span class="kt">TaskListFeature</span><span class="o">.</span><span class="kt">State</span><span class="p">())</span> <span class="p">{</span>
        <span class="kt">TaskListFeature</span><span class="p">()</span>
    <span class="p">}</span>
    
    <span class="k">var</span> <span class="nv">body</span><span class="p">:</span> <span class="kd">some</span> <span class="kt">Scene</span> <span class="p">{</span>
        <span class="kt">WindowGroup</span> <span class="p">{</span>
            <span class="kt">TaskListView</span><span class="p">(</span><span class="nv">store</span><span class="p">:</span> <span class="kt">TCAApp</span><span class="o">.</span><span class="n">store</span><span class="p">)</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>

</code></pre></div></div>

<h2 id="view-interactor-presenter-entity-router-viper">View-Interactor-Presenter-Entity-Router (VIPER)</h2>

<p>VIPER was introduced by Mutual Mobile in 2014 as an application of Clean Architecture principles to iOS. The acronym describes its five components: <strong>View</strong> (UI), <strong>Interactor</strong> (business logic), <strong>Presenter</strong>(presentation logic), <strong>Entity</strong> (business models), and <strong>Router</strong> (navigation).</p>

<p>It gained significant popularity in the first years of Swift as iOS projects grew larger and developers sought alternatives to “Massive View Controller” syndrome. In fact, it makes the code highly modular with clear, strict separation of concerns. Today, VIPER is still used in legacy codebases using UIKit’s imperative paradigm and by teams already familiar with it. The pattern’s complexity feels at odds with SwiftUI’s declarative simplicity.</p>

<p>Another popular but similar alternative is <strong>Clean Swift</strong> or <strong>VIP</strong> (View-Interactor-Presenter). It works just like VIPER but with a one-way data flow. It also uses Workers for external services and emphasizes scenes over features. There’s also Uber’s <strong>RIBs</strong> (Router-Interactor-Builder), a reactive cross-platform architecture that structures apps as a hierarchy of features. It includes Builders for dependency injection and was designed for cross-platform teams (iOS/Android).</p>

<h3 id="file-structure-4">File structure</h3>

<p>VIPER organizes by modules (features), with each module containing all five VIPER components. The <code class="language-plaintext highlighter-rouge">TaskListModule.swift</code> file acts as an assembly point, wiring all components together. <code class="language-plaintext highlighter-rouge">TaskListInterface.swift</code> contains the protocols that define how components communicate.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>VIPER/
├── VIPERApp.swift
└── Modules/
    ├── Entities/
    │   └── Task.swift
    └── TaskList/
        ├── TaskListModule.swift
        ├── TaskListInterface.swift
        ├── TaskListView.swift
        ├── TaskListPresenter.swift
        ├── TaskListInteractor.swift
        └── TaskListRouter.swift

</code></pre></div></div>

<h3 id="implementation-4">Implementation</h3>

<p>TaskListModule.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">SwiftUI</span>

<span class="kd">struct</span> <span class="kt">TaskListModule</span> <span class="p">{</span>
    <span class="kd">static</span> <span class="kd">func</span> <span class="nf">build</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="kd">some</span> <span class="kt">View</span> <span class="p">{</span>
        <span class="k">let</span> <span class="nv">interactor</span> <span class="o">=</span> <span class="kt">TaskListInteractor</span><span class="p">()</span>
        <span class="k">let</span> <span class="nv">router</span> <span class="o">=</span> <span class="kt">TaskListRouter</span><span class="p">()</span>
        <span class="k">let</span> <span class="nv">presenter</span> <span class="o">=</span> <span class="kt">TaskListPresenter</span><span class="p">(</span><span class="nv">interactor</span><span class="p">:</span> <span class="n">interactor</span><span class="p">,</span> <span class="nv">router</span><span class="p">:</span> <span class="n">router</span><span class="p">)</span>
        <span class="k">return</span> <span class="kt">TaskListView</span><span class="p">(</span><span class="nv">presenter</span><span class="p">:</span> <span class="n">presenter</span><span class="p">)</span>
    <span class="p">}</span>
<span class="p">}</span>

</code></pre></div></div>

<p>TaskListInterface.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">Foundation</span>
<span class="kd">import</span> <span class="kt">Combine</span>

<span class="c1">// View -&gt; Presenter</span>
<span class="kd">protocol</span> <span class="kt">TaskListPresenterProtocol</span><span class="p">:</span> <span class="kt">ObservableObject</span> <span class="p">{</span>
    <span class="k">var</span> <span class="nv">tasks</span><span class="p">:</span> <span class="p">[</span><span class="kt">Task</span><span class="p">]</span> <span class="p">{</span> <span class="k">get</span> <span class="p">}</span>
    <span class="k">var</span> <span class="nv">taskTitle</span><span class="p">:</span> <span class="kt">String</span> <span class="p">{</span> <span class="k">get</span> <span class="k">set</span> <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">addTask</span><span class="p">()</span>
    <span class="kd">func</span> <span class="nf">toggleTask</span><span class="p">(</span><span class="n">_</span> <span class="nv">id</span><span class="p">:</span> <span class="kt">UUID</span><span class="p">)</span>
    <span class="kd">func</span> <span class="nf">deleteTask</span><span class="p">(</span><span class="n">_</span> <span class="nv">indexSet</span><span class="p">:</span> <span class="kt">IndexSet</span><span class="p">)</span>
    <span class="kd">func</span> <span class="nf">didSelectTaskDetails</span><span class="p">(</span><span class="nv">task</span><span class="p">:</span> <span class="kt">Task</span><span class="p">)</span>
<span class="p">}</span>

<span class="c1">// Presenter -&gt; Interactor</span>
<span class="kd">protocol</span> <span class="kt">TaskListInteractorProtocol</span> <span class="p">{</span>
    <span class="kd">func</span> <span class="nf">fetchTasks</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="kt">Task</span><span class="p">]</span>
    <span class="kd">func</span> <span class="nf">saveTask</span><span class="p">(</span><span class="n">_</span> <span class="nv">task</span><span class="p">:</span> <span class="kt">Task</span><span class="p">)</span>
    <span class="kd">func</span> <span class="nf">updateTask</span><span class="p">(</span><span class="n">_</span> <span class="nv">task</span><span class="p">:</span> <span class="kt">Task</span><span class="p">)</span>
    <span class="kd">func</span> <span class="nf">deleteTasks</span><span class="p">(</span><span class="n">_</span> <span class="nv">tasks</span><span class="p">:</span> <span class="p">[</span><span class="kt">Task</span><span class="p">])</span>
<span class="p">}</span>

<span class="c1">// Presenter -&gt; Router</span>
<span class="kd">protocol</span> <span class="kt">TaskListRouterProtocol</span> <span class="p">{</span>
    <span class="kd">func</span> <span class="nf">navigateToDetails</span><span class="p">(</span><span class="k">for</span> <span class="nv">task</span><span class="p">:</span> <span class="kt">Task</span><span class="p">)</span>
<span class="p">}</span>

</code></pre></div></div>

<p>TaskListView.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">SwiftUI</span>

<span class="kd">struct</span> <span class="kt">TaskListView</span><span class="o">&lt;</span><span class="kt">Presenter</span><span class="p">:</span> <span class="kt">TaskListPresenterProtocol</span><span class="o">&gt;</span><span class="p">:</span> <span class="kt">View</span> <span class="p">{</span>
    <span class="kd">@StateObject</span> <span class="k">var</span> <span class="nv">presenter</span><span class="p">:</span> <span class="kt">Presenter</span>
    
    <span class="k">var</span> <span class="nv">body</span><span class="p">:</span> <span class="kd">some</span> <span class="kt">View</span> <span class="p">{</span>
        <span class="kt">NavigationStack</span> <span class="p">{</span>
            <span class="kt">VStack</span> <span class="p">{</span>
                <span class="kt">HStack</span> <span class="p">{</span>
                    <span class="kt">TextField</span><span class="p">(</span><span class="s">"Enter a new task…"</span><span class="p">,</span> <span class="nv">text</span><span class="p">:</span> <span class="err">$</span><span class="n">presenter</span><span class="o">.</span><span class="n">taskTitle</span><span class="p">)</span>
                        <span class="o">.</span><span class="nf">textFieldStyle</span><span class="p">(</span><span class="o">.</span><span class="n">roundedBorder</span><span class="p">)</span>
                        <span class="o">.</span><span class="nf">padding</span><span class="p">(</span><span class="o">.</span><span class="n">trailing</span><span class="p">)</span>
                    <span class="kt">Button</span><span class="p">(</span><span class="s">"Add"</span><span class="p">,</span> <span class="nv">action</span><span class="p">:</span> <span class="n">presenter</span><span class="o">.</span><span class="n">addTask</span><span class="p">)</span>
                        <span class="o">.</span><span class="nf">buttonStyle</span><span class="p">(</span><span class="o">.</span><span class="n">borderedProminent</span><span class="p">)</span>
                <span class="p">}</span>
                <span class="o">.</span><span class="nf">padding</span><span class="p">()</span>
                
                <span class="kt">List</span> <span class="p">{</span>
                    <span class="kt">ForEach</span><span class="p">(</span><span class="n">presenter</span><span class="o">.</span><span class="n">tasks</span><span class="p">)</span> <span class="p">{</span> <span class="n">task</span> <span class="k">in</span>
                        <span class="kt">HStack</span> <span class="p">{</span>
                            <span class="kt">Text</span><span class="p">(</span><span class="n">task</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
                            <span class="kt">Spacer</span><span class="p">()</span>
                            <span class="kt">Button</span><span class="p">(</span><span class="n">task</span><span class="o">.</span><span class="n">isDone</span> <span class="p">?</span> <span class="s">"✓"</span> <span class="p">:</span> <span class="s">"○"</span><span class="p">)</span> <span class="p">{</span>
                                <span class="n">presenter</span><span class="o">.</span><span class="nf">toggleTask</span><span class="p">(</span><span class="n">task</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
                            <span class="p">}</span>
                        <span class="p">}</span>
                    <span class="p">}</span>
                    <span class="o">.</span><span class="nf">onDelete</span><span class="p">(</span><span class="nv">perform</span><span class="p">:</span> <span class="n">presenter</span><span class="o">.</span><span class="n">deleteTask</span><span class="p">)</span>
                <span class="p">}</span>
                <span class="o">.</span><span class="nf">listStyle</span><span class="p">(</span><span class="o">.</span><span class="n">plain</span><span class="p">)</span>
            <span class="p">}</span>
            <span class="o">.</span><span class="nf">navigationTitle</span><span class="p">(</span><span class="s">"Tasks"</span><span class="p">)</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>

</code></pre></div></div>

<p>TaskListPresenter.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">Foundation</span>
<span class="kd">import</span> <span class="kt">Combine</span>

<span class="kd">class</span> <span class="kt">TaskListPresenter</span><span class="p">:</span> <span class="kt">TaskListPresenterProtocol</span><span class="p">,</span> <span class="kt">ObservableObject</span> <span class="p">{</span>
    <span class="kd">@Published</span> <span class="k">var</span> <span class="nv">tasks</span><span class="p">:</span> <span class="p">[</span><span class="kt">Task</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="kd">@Published</span> <span class="k">var</span> <span class="nv">taskTitle</span><span class="p">:</span> <span class="kt">String</span> <span class="o">=</span> <span class="s">""</span>
    
    <span class="kd">private</span> <span class="k">let</span> <span class="nv">interactor</span><span class="p">:</span> <span class="kt">TaskListInteractorProtocol</span>
    <span class="kd">private</span> <span class="k">let</span> <span class="nv">router</span><span class="p">:</span> <span class="kt">TaskListRouterProtocol</span>
    
    <span class="nf">init</span><span class="p">(</span><span class="nv">interactor</span><span class="p">:</span> <span class="kt">TaskListInteractorProtocol</span><span class="p">,</span> <span class="nv">router</span><span class="p">:</span> <span class="kt">TaskListRouterProtocol</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">self</span><span class="o">.</span><span class="n">interactor</span> <span class="o">=</span> <span class="n">interactor</span>
        <span class="k">self</span><span class="o">.</span><span class="n">router</span> <span class="o">=</span> <span class="n">router</span>
        <span class="k">self</span><span class="o">.</span><span class="n">tasks</span> <span class="o">=</span> <span class="n">interactor</span><span class="o">.</span><span class="nf">fetchTasks</span><span class="p">()</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">addTask</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">guard</span> <span class="o">!</span><span class="n">taskTitle</span><span class="o">.</span><span class="n">isEmpty</span> <span class="k">else</span> <span class="p">{</span> <span class="k">return</span> <span class="p">}</span>
        <span class="k">let</span> <span class="nv">task</span> <span class="o">=</span> <span class="kt">Task</span><span class="p">(</span><span class="nv">title</span><span class="p">:</span> <span class="n">taskTitle</span><span class="p">)</span>
        <span class="n">interactor</span><span class="o">.</span><span class="nf">saveTask</span><span class="p">(</span><span class="n">task</span><span class="p">)</span>
        <span class="n">tasks</span> <span class="o">=</span> <span class="n">interactor</span><span class="o">.</span><span class="nf">fetchTasks</span><span class="p">()</span>
        <span class="n">taskTitle</span> <span class="o">=</span> <span class="s">""</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">toggleTask</span><span class="p">(</span><span class="n">_</span> <span class="nv">id</span><span class="p">:</span> <span class="kt">UUID</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">guard</span> <span class="k">var</span> <span class="nv">task</span> <span class="o">=</span> <span class="n">tasks</span><span class="o">.</span><span class="nf">first</span><span class="p">(</span><span class="nv">where</span><span class="p">:</span> <span class="p">{</span> <span class="nv">$0</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">id</span> <span class="p">})</span> <span class="k">else</span> <span class="p">{</span> <span class="k">return</span> <span class="p">}</span>
        <span class="n">task</span><span class="o">.</span><span class="n">isDone</span><span class="o">.</span><span class="nf">toggle</span><span class="p">()</span>
        <span class="n">interactor</span><span class="o">.</span><span class="nf">updateTask</span><span class="p">(</span><span class="n">task</span><span class="p">)</span>
        <span class="n">tasks</span> <span class="o">=</span> <span class="n">interactor</span><span class="o">.</span><span class="nf">fetchTasks</span><span class="p">()</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">deleteTask</span><span class="p">(</span><span class="n">_</span> <span class="nv">indexSet</span><span class="p">:</span> <span class="kt">IndexSet</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">let</span> <span class="nv">tasksToDelete</span> <span class="o">=</span> <span class="n">indexSet</span><span class="o">.</span><span class="n">map</span> <span class="p">{</span> <span class="n">tasks</span><span class="p">[</span><span class="nv">$0</span><span class="p">]</span> <span class="p">}</span>
        <span class="n">interactor</span><span class="o">.</span><span class="nf">deleteTasks</span><span class="p">(</span><span class="n">tasksToDelete</span><span class="p">)</span>
        <span class="n">tasks</span> <span class="o">=</span> <span class="n">interactor</span><span class="o">.</span><span class="nf">fetchTasks</span><span class="p">()</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">didSelectTaskDetails</span><span class="p">(</span><span class="nv">task</span><span class="p">:</span> <span class="kt">Task</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">router</span><span class="o">.</span><span class="nf">navigateToDetails</span><span class="p">(</span><span class="nv">for</span><span class="p">:</span> <span class="n">task</span><span class="p">)</span>
    <span class="p">}</span>
<span class="p">}</span>

</code></pre></div></div>

<p>TaskListInteractor.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">Foundation</span>

<span class="kd">class</span> <span class="kt">TaskListInteractor</span><span class="p">:</span> <span class="kt">TaskListInteractorProtocol</span> <span class="p">{</span>
    <span class="kd">private</span> <span class="k">var</span> <span class="nv">dataStore</span><span class="p">:</span> <span class="p">[</span><span class="kt">Task</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
    
    <span class="kd">func</span> <span class="nf">fetchTasks</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="kt">Task</span><span class="p">]</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">dataStore</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">saveTask</span><span class="p">(</span><span class="n">_</span> <span class="nv">task</span><span class="p">:</span> <span class="kt">Task</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">dataStore</span><span class="o">.</span><span class="nf">append</span><span class="p">(</span><span class="n">task</span><span class="p">)</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">updateTask</span><span class="p">(</span><span class="n">_</span> <span class="nv">task</span><span class="p">:</span> <span class="kt">Task</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="k">let</span> <span class="nv">index</span> <span class="o">=</span> <span class="n">dataStore</span><span class="o">.</span><span class="nf">firstIndex</span><span class="p">(</span><span class="nv">where</span><span class="p">:</span> <span class="p">{</span> <span class="nv">$0</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">task</span><span class="o">.</span><span class="n">id</span> <span class="p">})</span> <span class="p">{</span>
            <span class="n">dataStore</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">=</span> <span class="n">task</span>
        <span class="p">}</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">deleteTasks</span><span class="p">(</span><span class="n">_</span> <span class="nv">tasks</span><span class="p">:</span> <span class="p">[</span><span class="kt">Task</span><span class="p">])</span> <span class="p">{</span>
        <span class="k">for</span> <span class="n">task</span> <span class="k">in</span> <span class="n">tasks</span> <span class="p">{</span>
            <span class="k">if</span> <span class="k">let</span> <span class="nv">index</span> <span class="o">=</span> <span class="n">dataStore</span><span class="o">.</span><span class="nf">firstIndex</span><span class="p">(</span><span class="nv">where</span><span class="p">:</span> <span class="p">{</span> <span class="nv">$0</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">task</span><span class="o">.</span><span class="n">id</span> <span class="p">})</span> <span class="p">{</span>
                <span class="n">dataStore</span><span class="o">.</span><span class="nf">remove</span><span class="p">(</span><span class="nv">at</span><span class="p">:</span> <span class="n">index</span><span class="p">)</span>
            <span class="p">}</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>

</code></pre></div></div>

<p>TaskListRouter.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="kt">TaskListRouter</span><span class="p">:</span> <span class="kt">TaskListRouterProtocol</span> <span class="p">{</span>
    <span class="kd">func</span> <span class="nf">navigateToDetails</span><span class="p">(</span><span class="k">for</span> <span class="nv">task</span><span class="p">:</span> <span class="kt">Task</span><span class="p">)</span> <span class="p">{</span>
        <span class="nf">print</span><span class="p">(</span><span class="s">"Navigate to details for </span><span class="se">\(</span><span class="n">task</span><span class="o">.</span><span class="n">title</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
    <span class="p">}</span>
<span class="p">}</span>

</code></pre></div></div>

<p>VIPERApp.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">SwiftUI</span>

<span class="kd">@main</span>
<span class="kd">struct</span> <span class="kt">VIPERApp</span><span class="p">:</span> <span class="kt">App</span> <span class="p">{</span>
    <span class="k">var</span> <span class="nv">body</span><span class="p">:</span> <span class="kd">some</span> <span class="kt">Scene</span> <span class="p">{</span>
        <span class="kt">WindowGroup</span> <span class="p">{</span>
            <span class="kt">TaskListModule</span><span class="o">.</span><span class="nf">build</span><span class="p">()</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>

</code></pre></div></div>

<h2 id="clean-architecture">Clean Architecture</h2>

<p>Clean Architecture is a set of abstract principles defined by Robert C. Martin (Uncle Bob) in his 2012 book. It’s not a specific pattern like MVVM or VIPER, nor a prescribed folder structure. So yes, I cheated again… Clean Architecture is rather a philosophy: <strong>organize code in concentric layers where dependencies point inward, and business logic is independent of frameworks, UI, and databases</strong>.</p>

<p>The name reflects the goal: “clean” separation of concerns that makes code maintainable, testable, and framework-agnostic. While specific implementations evolve, the principles remain relevant, and many modern architectures (TCA, RIBs, even well-structured MVVM) incorporate Clean Architecture concepts.</p>

<p>Deriving architectures include <strong>Layered Architecture</strong>, <strong>Hexagonal Architecture</strong> (Ports &amp; Adapters), <strong>Onion Architecture</strong>, and <strong>CQRS</strong> (Command-Query-Responsibility-Segregation). All share the goal of framework-independent business logic. A typical modern architecture for large projects might even use all of them: Clean Architecture for overall structure (layers, dependency rules), Hexagonal principles for implementation (ports/adapters at boundaries), and CQRS for data access (separate read/write models when needed).</p>

<h3 id="file-structure-5">File structure</h3>

<p>Clean Architecture’s structure reflects its concentric layers:</p>

<ul>
  <li>Domain (innermost): Pure business logic; entities, repository interfaces (ports), and use cases. No framework dependencies.</li>
  <li>Data (middle): Implementation details; repository implementations that conform to domain interfaces. Could swap in CoreData, UserDefaults, or Firebase.</li>
  <li>Presentation (outer): UI layer; ViewModels and Views that depend on domain use cases.</li>
</ul>

<p>The <code class="language-plaintext highlighter-rouge">CleanAppFactory.swift</code> handles dependency injection, wiring concrete implementations to interfaces.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Clean/
├── CleanApp.swift
├── CleanAppFactory.swift
├── 1 - Domain/
│   ├── Entities/
│   │   └── Task.swift
│   ├── Interfaces/
│   │   └── TaskRepositories.swift
│   └── UseCases/
│       └── TaskUseCases.swift
├── 2 - Data/
│   └── Repositories/
│       └── InMemoryTaskRepository.swift
└── 3 - Presentation/
    ├── ViewModels/
    │   └── TaskListViewModel.swift
    └── Views/
        └── TaskListView.swift

</code></pre></div></div>

<h3 id="implementation-5">Implementation</h3>

<p>TaskRepositories.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">Foundation</span>

<span class="kd">protocol</span> <span class="kt">TaskRepository</span> <span class="p">{</span>
    <span class="kd">func</span> <span class="nf">getTasks</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="kt">Task</span><span class="p">]</span>
    <span class="kd">func</span> <span class="nf">save</span><span class="p">(</span><span class="n">_</span> <span class="nv">task</span><span class="p">:</span> <span class="kt">Task</span><span class="p">)</span>
    <span class="kd">func</span> <span class="nf">update</span><span class="p">(</span><span class="n">_</span> <span class="nv">task</span><span class="p">:</span> <span class="kt">Task</span><span class="p">)</span>
    <span class="kd">func</span> <span class="nf">delete</span><span class="p">(</span><span class="n">_</span> <span class="nv">task</span><span class="p">:</span> <span class="kt">Task</span><span class="p">)</span>
<span class="p">}</span>

</code></pre></div></div>

<p>TaskUseCases.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">Foundation</span>

<span class="kd">struct</span> <span class="kt">GetTasksUseCase</span> <span class="p">{</span>
    <span class="k">let</span> <span class="nv">repo</span><span class="p">:</span> <span class="kt">TaskRepository</span>
    <span class="kd">func</span> <span class="nf">execute</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="kt">Task</span><span class="p">]</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">repo</span><span class="o">.</span><span class="nf">getTasks</span><span class="p">()</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kd">struct</span> <span class="kt">AddTaskUseCase</span> <span class="p">{</span>
    <span class="k">let</span> <span class="nv">repo</span><span class="p">:</span> <span class="kt">TaskRepository</span>
    <span class="kd">func</span> <span class="nf">execute</span><span class="p">(</span><span class="nv">title</span><span class="p">:</span> <span class="kt">String</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">let</span> <span class="nv">task</span> <span class="o">=</span> <span class="kt">Task</span><span class="p">(</span><span class="nv">title</span><span class="p">:</span> <span class="n">title</span><span class="p">)</span>
        <span class="n">repo</span><span class="o">.</span><span class="nf">save</span><span class="p">(</span><span class="n">task</span><span class="p">)</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kd">struct</span> <span class="kt">ToggleTaskUseCase</span> <span class="p">{</span>
    <span class="k">let</span> <span class="nv">repo</span><span class="p">:</span> <span class="kt">TaskRepository</span>
    <span class="kd">func</span> <span class="nf">execute</span><span class="p">(</span><span class="nv">id</span><span class="p">:</span> <span class="kt">UUID</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">let</span> <span class="nv">tasks</span> <span class="o">=</span> <span class="n">repo</span><span class="o">.</span><span class="nf">getTasks</span><span class="p">()</span>
        <span class="k">guard</span> <span class="k">var</span> <span class="nv">task</span> <span class="o">=</span> <span class="n">tasks</span><span class="o">.</span><span class="nf">first</span><span class="p">(</span><span class="nv">where</span><span class="p">:</span> <span class="p">{</span> <span class="nv">$0</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">id</span> <span class="p">})</span> <span class="k">else</span> <span class="p">{</span> <span class="k">return</span> <span class="p">}</span>
        <span class="n">task</span><span class="o">.</span><span class="n">isDone</span><span class="o">.</span><span class="nf">toggle</span><span class="p">()</span>
        <span class="n">repo</span><span class="o">.</span><span class="nf">update</span><span class="p">(</span><span class="n">task</span><span class="p">)</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kd">struct</span> <span class="kt">DeleteTaskUseCase</span> <span class="p">{</span>
    <span class="k">let</span> <span class="nv">repo</span><span class="p">:</span> <span class="kt">TaskRepository</span>
    <span class="kd">func</span> <span class="nf">execute</span><span class="p">(</span><span class="nv">indexSet</span><span class="p">:</span> <span class="kt">IndexSet</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">for</span> <span class="n">index</span> <span class="k">in</span> <span class="n">indexSet</span> <span class="p">{</span>
            <span class="k">let</span> <span class="nv">tasks</span> <span class="o">=</span> <span class="n">repo</span><span class="o">.</span><span class="nf">getTasks</span><span class="p">()</span>
            <span class="n">repo</span><span class="o">.</span><span class="nf">delete</span><span class="p">(</span><span class="n">tasks</span><span class="p">[</span><span class="n">index</span><span class="p">])</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>

</code></pre></div></div>

<p>InMemoryTaskRepository.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">Foundation</span>

<span class="kd">class</span> <span class="kt">InMemoryTaskRepository</span><span class="p">:</span> <span class="kt">TaskRepository</span> <span class="p">{</span>
    <span class="kd">private</span> <span class="k">var</span> <span class="nv">tasks</span><span class="p">:</span> <span class="p">[</span><span class="kt">Task</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
    
    <span class="kd">func</span> <span class="nf">getTasks</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="kt">Task</span><span class="p">]</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">tasks</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">save</span><span class="p">(</span><span class="n">_</span> <span class="nv">task</span><span class="p">:</span> <span class="kt">Task</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">tasks</span><span class="o">.</span><span class="nf">append</span><span class="p">(</span><span class="n">task</span><span class="p">)</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">update</span><span class="p">(</span><span class="n">_</span> <span class="nv">task</span><span class="p">:</span> <span class="kt">Task</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="k">let</span> <span class="nv">index</span> <span class="o">=</span> <span class="n">tasks</span><span class="o">.</span><span class="nf">firstIndex</span><span class="p">(</span><span class="nv">where</span><span class="p">:</span> <span class="p">{</span> <span class="nv">$0</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">task</span><span class="o">.</span><span class="n">id</span> <span class="p">})</span> <span class="p">{</span>
            <span class="n">tasks</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">=</span> <span class="n">task</span>
        <span class="p">}</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">delete</span><span class="p">(</span><span class="n">_</span> <span class="nv">task</span><span class="p">:</span> <span class="kt">Task</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">tasks</span><span class="o">.</span><span class="nf">removeAll</span><span class="p">(</span><span class="nv">where</span><span class="p">:</span> <span class="p">{</span> <span class="nv">$0</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">task</span><span class="o">.</span><span class="n">id</span> <span class="p">})</span>
    <span class="p">}</span>
<span class="p">}</span>

</code></pre></div></div>

<p>TaskListViewModel.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">Foundation</span>
<span class="kd">import</span> <span class="kt">Observation</span>

<span class="kd">@Observable</span>
<span class="kd">class</span> <span class="kt">TaskListViewModel</span> <span class="p">{</span>
    <span class="k">var</span> <span class="nv">tasks</span><span class="p">:</span> <span class="p">[</span><span class="kt">Task</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="k">var</span> <span class="nv">taskTitle</span><span class="p">:</span> <span class="kt">String</span> <span class="o">=</span> <span class="s">""</span>
    
    <span class="kd">private</span> <span class="k">let</span> <span class="nv">getTasks</span><span class="p">:</span> <span class="kt">GetTasksUseCase</span>
    <span class="kd">private</span> <span class="k">let</span> <span class="nv">addTask</span><span class="p">:</span> <span class="kt">AddTaskUseCase</span>
    <span class="kd">private</span> <span class="k">let</span> <span class="nv">toggleTask</span><span class="p">:</span> <span class="kt">ToggleTaskUseCase</span>
    <span class="kd">private</span> <span class="k">let</span> <span class="nv">deleteTask</span><span class="p">:</span> <span class="kt">DeleteTaskUseCase</span>
    
    <span class="nf">init</span><span class="p">(</span><span class="nv">getTasks</span><span class="p">:</span> <span class="kt">GetTasksUseCase</span><span class="p">,</span> <span class="nv">addTask</span><span class="p">:</span> <span class="kt">AddTaskUseCase</span><span class="p">,</span> <span class="nv">toggleTask</span><span class="p">:</span> <span class="kt">ToggleTaskUseCase</span><span class="p">,</span> <span class="nv">deleteTask</span><span class="p">:</span> <span class="kt">DeleteTaskUseCase</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">self</span><span class="o">.</span><span class="n">getTasks</span> <span class="o">=</span> <span class="n">getTasks</span>
        <span class="k">self</span><span class="o">.</span><span class="n">addTask</span> <span class="o">=</span> <span class="n">addTask</span>
        <span class="k">self</span><span class="o">.</span><span class="n">toggleTask</span> <span class="o">=</span> <span class="n">toggleTask</span>
        <span class="k">self</span><span class="o">.</span><span class="n">deleteTask</span> <span class="o">=</span> <span class="n">deleteTask</span>
        <span class="nf">refresh</span><span class="p">()</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">refresh</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">self</span><span class="o">.</span><span class="n">tasks</span> <span class="o">=</span> <span class="n">getTasks</span><span class="o">.</span><span class="nf">execute</span><span class="p">()</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">performAdd</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">guard</span> <span class="o">!</span><span class="n">taskTitle</span><span class="o">.</span><span class="n">isEmpty</span> <span class="k">else</span> <span class="p">{</span> <span class="k">return</span> <span class="p">}</span>
        <span class="n">addTask</span><span class="o">.</span><span class="nf">execute</span><span class="p">(</span><span class="nv">title</span><span class="p">:</span> <span class="n">taskTitle</span><span class="p">)</span>
        <span class="n">taskTitle</span> <span class="o">=</span> <span class="s">""</span>
        <span class="nf">refresh</span><span class="p">()</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">performToggle</span><span class="p">(</span><span class="n">_</span> <span class="nv">id</span><span class="p">:</span> <span class="kt">UUID</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">toggleTask</span><span class="o">.</span><span class="nf">execute</span><span class="p">(</span><span class="nv">id</span><span class="p">:</span> <span class="n">id</span><span class="p">)</span>
        <span class="nf">refresh</span><span class="p">()</span>
    <span class="p">}</span>
    
    <span class="kd">func</span> <span class="nf">performDelete</span><span class="p">(</span><span class="n">_</span> <span class="nv">indexSet</span><span class="p">:</span> <span class="kt">IndexSet</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">deleteTask</span><span class="o">.</span><span class="nf">execute</span><span class="p">(</span><span class="nv">indexSet</span><span class="p">:</span> <span class="n">indexSet</span><span class="p">)</span>
        <span class="nf">refresh</span><span class="p">()</span>
    <span class="p">}</span>
<span class="p">}</span>

</code></pre></div></div>

<p>CleanAppFactory.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">SwiftUI</span>

<span class="kd">struct</span> <span class="kt">CleanAppFactory</span> <span class="p">{</span>
    <span class="kd">static</span> <span class="kd">func</span> <span class="nf">makeView</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="kd">some</span> <span class="kt">View</span> <span class="p">{</span>
        <span class="k">let</span> <span class="nv">repo</span> <span class="o">=</span> <span class="kt">InMemoryTaskRepository</span><span class="p">()</span>
        
        <span class="k">let</span> <span class="nv">getUC</span> <span class="o">=</span> <span class="kt">GetTasksUseCase</span><span class="p">(</span><span class="nv">repo</span><span class="p">:</span> <span class="n">repo</span><span class="p">)</span>
        <span class="k">let</span> <span class="nv">addUC</span> <span class="o">=</span> <span class="kt">AddTaskUseCase</span><span class="p">(</span><span class="nv">repo</span><span class="p">:</span> <span class="n">repo</span><span class="p">)</span>
        <span class="k">let</span> <span class="nv">toggleUC</span> <span class="o">=</span> <span class="kt">ToggleTaskUseCase</span><span class="p">(</span><span class="nv">repo</span><span class="p">:</span> <span class="n">repo</span><span class="p">)</span>
        <span class="k">let</span> <span class="nv">deleteUC</span> <span class="o">=</span> <span class="kt">DeleteTaskUseCase</span><span class="p">(</span><span class="nv">repo</span><span class="p">:</span> <span class="n">repo</span><span class="p">)</span>
        
        <span class="k">let</span> <span class="nv">vm</span> <span class="o">=</span> <span class="kt">TaskListViewModel</span><span class="p">(</span><span class="nv">getTasks</span><span class="p">:</span> <span class="n">getUC</span><span class="p">,</span> <span class="nv">addTask</span><span class="p">:</span> <span class="n">addUC</span><span class="p">,</span> <span class="nv">toggleTask</span><span class="p">:</span> <span class="n">toggleUC</span><span class="p">,</span> <span class="nv">deleteTask</span><span class="p">:</span> <span class="n">deleteUC</span><span class="p">)</span>
        
        <span class="k">return</span> <span class="kt">TaskListView</span><span class="p">(</span><span class="nv">viewModel</span><span class="p">:</span> <span class="n">vm</span><span class="p">)</span>
    <span class="p">}</span>
<span class="p">}</span>

</code></pre></div></div>

<p>CleanApp.swift:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">SwiftUI</span>

<span class="kd">@main</span>
<span class="kd">struct</span> <span class="kt">CleanApp</span><span class="p">:</span> <span class="kt">App</span> <span class="p">{</span>
    <span class="k">var</span> <span class="nv">body</span><span class="p">:</span> <span class="kd">some</span> <span class="kt">Scene</span> <span class="p">{</span>
        <span class="kt">WindowGroup</span> <span class="p">{</span>
            <span class="kt">CleanAppFactory</span><span class="o">.</span><span class="nf">makeView</span><span class="p">()</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>

</code></pre></div></div>

<h2 id="conclusion">Conclusion</h2>

<p>After building the same task manager six times, one truth became clear, and it’s quite cliché: there’s no universally “best” architecture, only trade-offs that align better or worse with specific needs.</p>

<p>From my experience, the easiest and fastest to implement is MVVM, SwiftUI’s sweet spot. For most projects, basic MVVM with <code class="language-plaintext highlighter-rouge">@Observable</code> gives testability and clean separation without boilerplate overhead. I’d point out how TCA was very interesting, even if it trades speed for safety.</p>

<p>On the other side of the coin, MVC and VIPER are fading gracefully. While VIPER taught iOS developers about modularity and testability, its UIKit-centric design feels awkward in SwiftUI.</p>

<p>Finally, Clean Architecture is about principles, not patterns. You don’t need five layers and a dozen protocols to write clean code. The core insights (depend on abstractions, separate business logic from frameworks) can be applied within any pattern.</p>

<p>Remember, architecture serves the code, not the other way around. The best architecture is the one that lets your team ship reliable features efficiently. Start simple, measure pain points, and add structure when complexity demands it, not because someone tells you to.</p>]]></content><author><name>Peter Yaacoub</name></author><category term="articles" /><category term="swift-tip" /><summary type="html"><![CDATA[Introduction What’s the best architecture for SwiftUI? This question always sparks endless debate in the iOS development community. Today, I finally decided to cut through the theory by building a simple task manager app six times. Yes, you read it right: SIX times. One app, six different architectures. First things first, I’m no architecture expert, and I’ll never pretend to be one. If you find mistakes or disagree with my following methods, reasoning, or learning, I’ll be happy to get your feedback via email or social media. For most of the following, it will be my first time dabbling in, so be indulgent! To start this new journey, I began with an initial list of 12 candidates. After realizing that many overlapped, I instead turned my focus to the ones that felt the most interesting and popular to me. I’m not hiding the fact that I used AI assistants to help clarify each architecture’s philosophy and implementation. With their strengths, some offering strong starting points, others distinguishing subtle differences, and IDE-integrated AI helping with debugging, I was ready to compare these options head-to-head.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://yaacoub.github.io/social.webp" /><media:content medium="image" url="https://yaacoub.github.io/social.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Build a Smart App with Apple Intelligence</title><link href="https://yaacoub.github.io/articles/swift-tip/build-a-smart-app-with-apple-intelligence-wwdc25/" rel="alternate" type="text/html" title="Build a Smart App with Apple Intelligence" /><published>2025-10-04T00:00:00+00:00</published><updated>2025-10-04T00:00:00+00:00</updated><id>https://yaacoub.github.io/articles/swift-tip/build-a-smart-app-with-apple-intelligence-wwdc25</id><content type="html" xml:base="https://yaacoub.github.io/articles/swift-tip/build-a-smart-app-with-apple-intelligence-wwdc25/"><![CDATA[<p>At WWDC25, Apple introduced new tools and frameworks that enable the design of intelligent, privacy-preserving, and on-device experiences without requiring access to massive cloud-based models. The central idea is to provide developers with flexible yet secure ways to integrate generative features directly into their applications. This article follows the structure of the sessions presented at WWDC25 to explore how to build smarter apps by leveraging on-device foundation models, prompt engineering strategies, and the latest advances in computer vision.</p>

<h2 id="meet-the-foundation-models-framework">Meet the Foundation Models Framework</h2>

<p>The Foundation Models framework provides the building blocks for integrating Apple Intelligence into applications. Unlike large cloud-hosted models with hundreds of billions of parameters, Apple’s on-device model is around 3 billion parameters, making it efficient enough to run locally while preserving user privacy. This model is not designed for fact retrieval, code generation, or complex mathematical calculations. Instead, its strength lies in natural language processing tasks where style, tone, and adaptability matter.</p>

<p>Developers can define <strong>instructions</strong> (static developer-provided guidance) and combine them with user <strong>prompts</strong> (dynamic input) to generate tailored responses. Prompt engineering is central here, and Apple provides tools like Playgrounds to experiment with different prompt designs and safety mechanisms. The framework supports guided generation using annotations such as <a href="https://developer.apple.com/documentation/foundationmodels/generable"><code class="language-plaintext highlighter-rouge">Generable</code></a> for data structures and <a href="https://developer.apple.com/documentation/foundationmodels/generationguide"><code class="language-plaintext highlighter-rouge">GenerationGuide</code></a> with a <a href="https://developer.apple.com/documentation/foundationmodels/generationguide/maximumcount(_:)"><code class="language-plaintext highlighter-rouge">maximumCount(_:)</code></a> parameter to control response scope and reliability. Partial results can be handled with <a href="https://developer.apple.com/documentation/foundationmodels/languagemodelsession/streamresponse(to:options:)"><code class="language-plaintext highlighter-rouge">streamResponse(to:options:)</code></a>, while snapshots such as <a href="https://developer.apple.com/documentation/foundationmodels/generable/partiallygenerated"><code class="language-plaintext highlighter-rouge">PartiallyGenerated</code></a> help developers capture intermediate output.</p>

<p>The <a href="https://developer.apple.com/documentation/foundationmodels/tool"><code class="language-plaintext highlighter-rouge">Tool</code></a> protocol defines how apps can extend a model’s capabilities with external logic. Each tool specifies a name, description, arguments, and a <a href="https://developer.apple.com/documentation/foundationmodels/tool/call(arguments:)"><code class="language-plaintext highlighter-rouge">call(arguments:)</code></a> method. Tools can even be created dynamically, enabling developers to adapt models to context-specific workflows. Sessions are managed with <a href="https://developer.apple.com/documentation/foundationmodels/languagemodelsession"><code class="language-plaintext highlighter-rouge">LanguageModelSession</code></a>, which can be paused or disabled while the model is actively responding. This level of orchestration helps prevent resource conflicts and improves responsiveness.</p>

<p>Availability checks are essential. The <a href="https://developer.apple.com/documentation/foundationmodels/systemlanguagemodel/availability-swift.property"><code class="language-plaintext highlighter-rouge">availability</code></a> property lets developers ensure the required model is present and handle errors gracefully. Since large language models are inherently slower than classic ML tasks, developers must also account for performance trade-offs and provide clear feedback when responses are delayed.</p>

<h2 id="explore-prompt-design-and-safety-for-on-device-foundation-models">Explore Prompt Design and Safety for On-Device Foundation Models</h2>

<p>Apple emphasizes that on-device intelligence must be designed with safety, quality, and clarity in mind. Developers are encouraged to combine pre-written instructions with user-generated prompts, while recognizing that these measures are not bulletproof. Commands expressed in all caps (e.g., MUST, DO NOT) help guide the model’s behavior, especially when precision is required.</p>

<p>Error handling is tightly integrated: if a generation violates guardrails, developers receive a <a href="https://developer.apple.com/documentation/foundationmodels/languagemodelsession/generationerror/guardrailviolation(_:)"><code class="language-plaintext highlighter-rouge">guardrailViolation(_:)</code></a> result. This ensures apps can gracefully recover without exposing users to unintended or unsafe outputs. For safety and effectiveness, Apple recommends extensive testing with varied inputs, followed by systematic feedback collection and sending.</p>

<h2 id="read-documents-using-the-vision-framework">Read Documents Using the Vision Framework</h2>

<p>Beyond text generation, Apple has expanded the Vision framework to include new APIs that allow apps to understand and process structured content directly from images. The new <a href="https://developer.apple.com/documentation/vision/recognizedocumentsrequest"><code class="language-plaintext highlighter-rouge">RecognizeDocumentsRequest</code></a> API supports more than twenty languages and can identify hierarchical document structures, including headers, paragraphs, tables, and lists. The resulting <a href="https://developer.apple.com/documentation/vision/documentobservation"><code class="language-plaintext highlighter-rouge">DocumentObservation</code></a> objects break content down into transcripts, lines, words, and paragraphs, enabling precise extraction and downstream processing.</p>

<p>Additional vision-based requests extend the range of on-device intelligence. For example, the new <a href="https://developer.apple.com/documentation/vision/detectlenssmudgerequest"><code class="language-plaintext highlighter-rouge">DetectLensSmudgeRequest</code></a> analyzes images for lens contamination, returning an observation with a confidence value from 0 to 1. Developers can use this information to provide real-time user feedback on camera quality. Similarly, <a href="https://developer.apple.com/documentation/vision/detecthumanhandposerequest"><code class="language-plaintext highlighter-rouge">DetectHumanHandPoseRequest</code></a> introduces a new model with refined joint position detection, improving the accuracy of gesture-based interfaces and assistive technologies.</p>

<p>These vision APIs integrate seamlessly with Apple Intelligence, allowing developers to combine natural language understanding with perceptual features for richer multimodal apps. Together, the Foundation Models framework and the Vision framework empower developers to build apps that are not only intelligent but also deeply integrated with the user’s environment, while keeping computation and privacy on-device.</p>]]></content><author><name>Peter Yaacoub</name></author><category term="articles" /><category term="swift-tip" /><summary type="html"><![CDATA[At WWDC25, Apple introduced new tools and frameworks that enable the design of intelligent, privacy-preserving, and on-device experiences without requiring access to massive cloud-based models. The central idea is to provide developers with flexible yet secure ways to integrate generative features directly into their applications. This article follows the structure of the sessions presented at WWDC25 to explore how to build smarter apps by leveraging on-device foundation models, prompt engineering strategies, and the latest advances in computer vision.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://yaacoub.github.io/social.webp" /><media:content medium="image" url="https://yaacoub.github.io/social.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Apple’s New Design Language - WWDC25</title><link href="https://yaacoub.github.io/articles/swift-tip/apple-s-new-design-language-wwdc25/" rel="alternate" type="text/html" title="Apple’s New Design Language - WWDC25" /><published>2025-09-27T00:00:00+00:00</published><updated>2025-09-27T00:00:00+00:00</updated><id>https://yaacoub.github.io/articles/swift-tip/apple-s-new-design-language-wwdc25</id><content type="html" xml:base="https://yaacoub.github.io/articles/swift-tip/apple-s-new-design-language-wwdc25/"><![CDATA[<p>Apple’s latest design updates represent a new era of consistency and continuous refinement in their ecosystem, showing a strong emphasis on fluidity, clarity, and adaptability across all platforms.</p>

<h2 id="meet-liquid-glass">Meet Liquid Glass</h2>

<p>Liquid Glass is Apple’s newest material, a direct evolution of the Mac OS X Aqua design and iOS 7 translucency. It embraces the best of flat and skeuomorphic designs with a metamaterial aesthetic that feels organic. Unlike older effects and animations, Liquid Glass uses optical depth and dynamic morphing, for example, when a button transforms into a menu or one view morphs into another.</p>

<p><img src="/-assets/images/articles/swift-tip/apple-s-new-design-language-wwdc25/meet-liquid-glass-1.webp" alt="Liquid Glass" /></p>

<p>All the glass and transparency effects can make legibility feel worse. However, it is evident that Apple has it at the core of the system. Shadows, a wide dynamic range, and careful use of light and dark modes ensure text and elements remain clear against any background. The system defines two functional layers: a content layer underneath and a functional interface layer on top, connected by blur effects, hard-edge styles, and scroll-edge interactions.</p>

<p><img src="/-assets/images/articles/swift-tip/apple-s-new-design-language-wwdc25/meet-liquid-glass-2.webp" alt="Functional layers" /></p>

<p>Highlights and shadows add dimensionality, with a normal state and a grayed-out inactive state. Designers are encouraged to use Liquid Glass primarily for navigation. They should avoid layering multiple glass panels together, which can compromise clarity. Apple also distinguishes between Regular and Clear variants: Regular is used in most interface contexts, while Clear is designed for media-rich backgrounds or bold, bright content that benefits from a dimming layer. Sparse tinting can provide emphasis, but the intersection of elements should be avoided in steady states. Importantly, Liquid Glass respects all accessibility settings.</p>

<p><img src="/-assets/images/articles/swift-tip/apple-s-new-design-language-wwdc25/meet-liquid-glass-3.webp" alt="Clear variant" /></p>

<h2 id="get-to-know-the-new-design-system">Get to Know the New Design System</h2>

<p>Apple’s broader design system has been updated with three pillars in mind: language, structure, and continuity. System colors have been refreshed to be bolder and more legible, and typography is now consistently left-aligned across interfaces. Borders and radii follow consistent rules: fixed corners for standard components, capsule radii for pill-shaped controls, and concentric radii that scale naturally with parent elements and padding.</p>

<p><img src="/-assets/images/articles/swift-tip/apple-s-new-design-language-wwdc25/get-to-know-the-new-design-system.webp" alt="Border and radii" /></p>

<p>Navigation and content separation are streamlined. Action sheets now rise from the bottom and point directly to their source, while scroll views feature a single edge effect per view for clarity. Menus emphasize text labels with optional icons, reducing reliance on symbolic shorthand. Apple encourages a platform-adaptive approach: a single view on iPhone, collapsible sidebar and split view navigation on iPad, and sidebar and split view navigation on Mac, all powered by the same underlying decision.</p>

<p>This system aims to reduce redundancy while providing a consistent cross-platform identity. By simplifying grouping, prioritizing layout, and ensuring consistent navigation patterns, designers can build interfaces that feel native on each device without reinventing the wheel.</p>

<h2 id="elevate-the-design-of-your-ipad-app">Elevate the Design of Your iPad App</h2>

<p>On iPad, design enhancements focus on navigation, windows, the pointer, and the menu bar. Navigation now offers more flexibility, starting with sidebars that can collapse into tab bars, adapting to context without losing content. Layout changes are non-destructive, so resizing or rotating does not force users to relearn controls. Window controls are now at the leading edge of the toolbar, aligning with macOS conventions and removing unnecessary safe area padding. Each new document can now also open in its own window with descriptive titles, improving multitasking.</p>

<p><img src="/-assets/images/articles/swift-tip/apple-s-new-design-language-wwdc25/elevate-the-design-of-your-ipad-app.webp" alt="Tab bar" /></p>

<p>Pointer interactions remain central to iPadOS. Apple distinguishes between default menus, which cover common system actions like tab navigation and sidebar toggling, and custom menus, where developers can surface their app’s most relevant features. Custom menus should be populated fully, ordered by frequency, grouped into logical sections, and paired with symbols. The most common actions should be assigned keyboard shortcuts. Importantly, Apple emphasizes never hiding menus or actions based on context. Disabled states are preferable and maintain a predictable interface for users.</p>

<h2 id="say-hello-to-the-new-look-of-app-icons">Say Hello to the New Look of App Icons</h2>

<p>Apple has also rethought how app icons integrate into the system, offering new modes: icons can now appear in translucent light or dark and tinted light or dark modes.</p>

<p>The design grid has been refined for both squircles and circles, with rounder corner radii across platforms. Within icons, designers are encouraged to avoid sharp edges, increase line weights for clarity at smaller sizes, and embrace gradients. A typical icon now uses a gradient that shifts from light at the top to dark at the bottom. Backgrounds adapt as well: colorful in normal mode, darker in dark mode, with translucent variations on request.</p>

<p><img src="/-assets/images/articles/swift-tip/apple-s-new-design-language-wwdc25/say-hello-to-the-new-look-of-app-icons.webp" alt="Icons" /></p>

<h2 id="create-icons-with-icon-composer">Create Icons with Icon Composer</h2>

<p>Apple has consolidated its icon creation pipeline with the new Icon Composer, integrated into Xcode. Historically, developers needed to manage multiple icons per platform. Then came per-platform consolidation. Now, with Icon Composer, a single source can generate all required icon variants across devices.</p>

<p><img src="/-assets/images/articles/swift-tip/apple-s-new-design-language-wwdc25/create-icons-with-icon-composer.webp" alt="Icon Composer" /></p>

<p>Icon Composer provides a default specular highlight for depth, but also allows fine control over blur, shadow, specular intensity, opacity, translucency, and masking. Designers should limit designs to four groups for simplicity and avoid overusing highlights or Liquid Glass on text. Chromatic shadows work well for colored icons against light backgrounds. For legibility in dark mode, use monochrome shadows.</p>

<p>The workflow integrates seamlessly with Apple’s design templates for Figma, Sketch, Photoshop, and Illustrator. Developers can export icons with backgrounds, outlines, and per-layer SVG or PNG assets, or rely on Icon Composer for common gradients and fills. The end result is greater consistency across platforms and less manual overhead.</p>

<h2 id="a-fluid-and-coherent-ecosystem">A fluid and coherent ecosystem</h2>

<p>Liquid Glass brings depth and organic transitions. The updated design system strengthens cross-platform consistency. iPad apps gain more flexibility with windows and menus. New icon styles harmonize apps with the system. Icon Composer reduces friction in delivering polished icons. Together, these updates point to Apple’s long-term vision for its products and its ever-increasing interest in Augmented Reality.</p>]]></content><author><name>Peter Yaacoub</name></author><category term="articles" /><category term="swift-tip" /><summary type="html"><![CDATA[Apple’s latest design updates represent a new era of consistency and continuous refinement in their ecosystem, showing a strong emphasis on fluidity, clarity, and adaptability across all platforms.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://yaacoub.github.io/social.webp" /><media:content medium="image" url="https://yaacoub.github.io/social.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Get Familiar with Your New Development Tools - WWDC25</title><link href="https://yaacoub.github.io/articles/swift-tip/get-familiar-with-your-new-development-tools-wwdc25/" rel="alternate" type="text/html" title="Get Familiar with Your New Development Tools - WWDC25" /><published>2025-09-20T00:00:00+00:00</published><updated>2025-09-20T00:00:00+00:00</updated><id>https://yaacoub.github.io/articles/swift-tip/get-familiar-with-your-new-development-tools-wwdc25</id><content type="html" xml:base="https://yaacoub.github.io/articles/swift-tip/get-familiar-with-your-new-development-tools-wwdc25/"><![CDATA[<p>WWDC25 introduced another set of significant updates to Apple’s developer ecosystem. Xcode 26, Swift 6.2, and SwiftUI all gained major improvements, while WebKit finally arrives as a native SwiftUI component. Here’s what’s new and why it matters.</p>

<h2 id="whats-new-in-xcode-26">What’s New in Xcode 26</h2>

<p>Xcode 26 focuses on speed, size, and smarter tooling. The IDE is about 24% smaller to download, with Intel simulator runtimes no longer bundled by default, and the Metal toolchain installed only when needed. Large projects also open up to 40% faster, cutting down time wasted on reloads.</p>

<p>Tabs now behave like Safari with pinning and start page options, while search has been redesigned to handle multiple words in any order, even across multiple lines, with results ranked by relevance. Voice Control has a new “Swift mode,” which recognizes operators and camelCase, allowing you to navigate and edit entirely by voice.</p>

<p>AI assistance is now built into the workflow. You can connect to ChatGPT, other providers, or even local models to explain code, generate fixes, or suggest refactors. Prompts can reference code symbols with “@,” attach files or images, and selectively include project context. The assistant proposes changes inline, ready for you to accept or refine.</p>

<p>Debugging is also deeper. Concurrency debugging reveals async execution across threads, with task IDs, TaskGroup properties, and actors clearly visible. A new Processor Trace instrument (on M4 Macs and iPhone 16) logs every branch and call. CPU Counters offer presets including “CPU Bottlenecks,” and a new Power Profiler correlates CPU, GPU, networking, and display use with thermal and charging states.</p>

<p>Testing has become more powerful with UI test recording, including failing test replays with videos and element snapshots, as well as the new <a href="https://developer.apple.com/documentation/xctest/xcthitchmetric"><code class="language-plaintext highlighter-rouge">XCTHitchMetric</code></a> for measuring UI stutters. Organizer now provides launch and hang diagnostics, benchmarks your app’s startup against similar apps, and gives you measurable performance goals.</p>

<h2 id="whats-new-in-swift">What’s New in Swift</h2>

<p>Swift 6.2 is all about safety, performance, and reach. The headline feature is default actor isolation, which implicitly applies <code class="language-plaintext highlighter-rouge">@MainActor</code> to module-level types. This reduces repetitive annotations while protecting against common concurrency errors.</p>

<p>Performance improves with <a href="https://developer.apple.com/documentation/swift/inlinearray"><code class="language-plaintext highlighter-rouge">InlineArray</code></a>, which stores fixed-size arrays directly on the stack instead of the heap, and with the new <a href="https://developer.apple.com/documentation/swift/span"><code class="language-plaintext highlighter-rouge">Span</code></a> type, which replaces unsafe buffer pointers with a safer, structured abstraction. Memory safety checks are stricter, compiler diagnostics are clearer, and error messages provide more context.</p>

<p>Interoperability continues to expand. Swift-Java interoperability is now available alongside improved C++ integration, making Swift more viable in mixed-language environments. On the systems front, Swift adds better containerization support, FreeBSD compatibility, and further progress toward WebAssembly targets.</p>

<p>Concurrency becomes more approachable with expanded attributes and built-in checking. Potential data races are hence caught earlier. Combined with performance and platform updates, Swift 6.2 positions the language as both a safer systems tool and a faster app language.</p>

<h2 id="whats-new-in-swiftui">What’s New in SwiftUI</h2>

<p>SwiftUI advances visually and functionally, embracing Apple’s new Liquid Glass design language. Standard components such as <a href="https://developer.apple.com/documentation/swiftui/navigationsplitview"><code class="language-plaintext highlighter-rouge">NavigationSplitView</code></a>, <a href="https://developer.apple.com/documentation/SwiftUI/TabView"><code class="language-plaintext highlighter-rouge">TabView</code></a>, sheets, and sidebars adapt more naturally across devices. On iPhone, tab bars float and shrink on scroll, while sheets gain built-in insets and translucent backgrounds. Developers can extend content with the new <a href="https://developer.apple.com/documentation/SwiftUI/View/backgroundExtensionEffect()"><code class="language-plaintext highlighter-rouge">backgroundExtensionEffect()</code></a> modifier for a more immersive layout.</p>

<p>Controls receive polish and flexibility. Sliders support tick marks and neutral positions, toolbar items can carry badges, and monochrome icons provide a unified appearance. Text editing also improves as <a href="https://developer.apple.com/documentation/swiftui/texteditor"><code class="language-plaintext highlighter-rouge">TextEditor</code></a> now supports <a href="https://developer.apple.com/documentation/foundation/attributedstring"><code class="language-plaintext highlighter-rouge">AttributedString</code></a> for inline formatting, styling, and links.</p>

<p>Search becomes a first-class citizen. Developers can place search bars in toolbars, whether at the bottom of the iPhone, the top of the iPad, or the side of the Mac. New behaviors let you control when search bars expand, collapse, or persist, and even dedicate entire tabs to search experiences.</p>

<p>Concurrency is integrated at the framework level. With Swift’s new default actor isolation, SwiftUI code is automatically safer. Background tasks are intelligently offloaded to prevent blocking the main thread, for smooth animations and no UI stutters, even in complex apps.</p>

<p>SwiftUI also stretches into new domains. <a href="https://developer.apple.com/documentation/realitykit">RealityKit</a> integrates directly, letting you embed 3D scenes, immersive content, and interactive 3D charts. Developers can now build truly multimodal experiences without leaving the SwiftUI ecosystem.</p>

<h2 id="meet-webkit-for-swiftui">Meet WebKit for SwiftUI</h2>

<p>One of the most anticipated updates finally arrived at WWDC25: <a href="https://developer.apple.com/documentation/webkit">WebKit</a> has been rebuilt as a native SwiftUI component. No more UIViewRepresentable or NSViewRepresentable workarounds. With the new WebView API, developers can embed web content directly into SwiftUI apps across iOS, macOS, iPadOS, and visionOS.</p>

<p>The API is more than a simple wrapper. It introduces a <a href="https://developer.apple.com/documentation/webkit/webpage"><code class="language-plaintext highlighter-rouge">WebPage</code></a> model that represents the state of the web content. You can load requests, HTML strings, or data blobs, and SwiftUI updates as the page transitions through navigation states such as start, redirect, commit, fail, and finish. Policy decisions are fully declarative, letting you approve or block navigation with SwiftUI-like clarity.</p>

<p>Developers can go further by injecting JavaScript using <a href="https://developer.apple.com/documentation/webkit/webpage/calljavascript(_:arguments:in:contentworld:)"><code class="language-plaintext highlighter-rouge">callJavaScript(_:arguments:in:contentWorld:)</code></a>, receiving typed results in Swift. Communication flows in both directions, so hybrid apps and embedded tools feel at home. WebKit in SwiftUI also supports navigation delegates, scroll behaviors, bounce effects, and geometry awareness, even adapting to visionOS’s unique scrolling input.</p>

<p>By baking WebKit directly into SwiftUI, Apple bridges the gap between native and web. Whether you need a hybrid UI, a documentation viewer, or a dynamic content container, the new WebView gives you full control without leaving SwiftUI’s declarative world.</p>

<h2 id="looking-ahead">Looking Ahead</h2>

<p>Development is faster and lighter, concurrency is safer by default, and SwiftUI is now flexible enough to host everything from immersive 3D content to fully interactive web pages.</p>

<p>For developers, these changes mean fewer workarounds, cleaner code, and apps that feel smoother and more consistent across platforms.</p>]]></content><author><name>Peter Yaacoub</name></author><category term="articles" /><category term="swift-tip" /><summary type="html"><![CDATA[WWDC25 introduced another set of significant updates to Apple’s developer ecosystem. Xcode 26, Swift 6.2, and SwiftUI all gained major improvements, while WebKit finally arrives as a native SwiftUI component. Here’s what’s new and why it matters.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://yaacoub.github.io/social.webp" /><media:content medium="image" url="https://yaacoub.github.io/social.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">What I Learned from Ego Is the Enemy by Ryan Holiday</title><link href="https://yaacoub.github.io/articles/loud-letters/what-i-learned-from-ego-is-the-enemy-by-ryan-holiday/" rel="alternate" type="text/html" title="What I Learned from Ego Is the Enemy by Ryan Holiday" /><published>2025-09-13T00:00:00+00:00</published><updated>2025-09-13T00:00:00+00:00</updated><id>https://yaacoub.github.io/articles/loud-letters/what-i-learned-from-ego-is-the-enemy-by-ryan-holiday</id><content type="html" xml:base="https://yaacoub.github.io/articles/loud-letters/what-i-learned-from-ego-is-the-enemy-by-ryan-holiday/"><![CDATA[<h2 id="greatness-comes-from-humble-beginnings">Greatness Comes from Humble Beginnings</h2>

<p>Ego tells us we need to announce ourselves, to show the world how capable we are. But you have to be ready before you ascend. It’s not brilliance that makes the difference. Real greatness comes from consistent effort; practicing, improving, and staying committed to the process.</p>

<h2 id="talk-is-cheap-execution-is-everything">Talk is Cheap, Execution is Everything.</h2>

<p>We often confuse talking with doing. But this takes time and effort away from success.</p>

<p>Image, labels, and external recognition can distract from what actually matters: execution. The work itself is more important than what others and you call you.</p>

<h2 id="dont-take-the-bait">Don’t Take the Bait</h2>

<p>Ego thrives on provocation, whether it’s criticism, praise, or conflict. Don’t lose your temper or let yourself be pulled into unnecessary battles. Uncomfortable conversations will happen, but instead of reacting, let others reveal themselves. The real power is control.</p>

<h2 id="stay-on-the-path">Stay on the Path</h2>

<p>Ego says “yes” too easily. Yes to recognition, to distractions, and to obligations that dilute focus. You want it all, what you have and what you don’t, but the challenge is to know what truly matters and stay on the path. Urgent things aren’t always important. The goal isn’t to please others but to pursue what really aligns with your values.</p>

<h2 id="honor-over-honors">Honor Over Honors</h2>

<p>There’s a strong distinction to make between honor and honors. Honor is about living with integrity and doing the work well. Honors, awards, fame, and titles are secondary.</p>

<p>Success, in this view, is self-satisfaction: becoming the best you can be. Recognition and rewards are extras, not the goal.</p>

<p>In particular, there’s a difference to make between global and selective fame. The first feeds the ego. It is loud, widespread, and often shallow; it seeks validation from the masses, many of whom don’t truly know or care about the substance behind the name. The second can affirm that you’re on the right path. It is quieter and more meaningful; it stems from being recognized by the people who matter: peers, mentors, or those who deeply understand the craft.</p>

<h2 id="redefining-failure-and-success">Redefining Failure and Success</h2>

<p>The ego is terrified of failure and can even lead to it. Yet, failure from the outside can actually be success on the inside if it means we’ve stayed true to our principles. In the same way, outside “success” can be empty if it’s only about ego.</p>

<h2 id="my-final-thoughts">My Final Thoughts</h2>

<p>This book felt quick and impactful, like a jab to the chin. It questioned my goals and aspirations in a good way. For anyone wishing to find success and perhaps fame, this is the book to read, not to suppress aspirations but to recenter objectives.</p>]]></content><author><name>Peter Yaacoub</name></author><category term="articles" /><category term="loud-letters" /><summary type="html"><![CDATA[Greatness Comes from Humble Beginnings Ego tells us we need to announce ourselves, to show the world how capable we are. But you have to be ready before you ascend. It’s not brilliance that makes the difference. Real greatness comes from consistent effort; practicing, improving, and staying committed to the process. Talk is Cheap, Execution is Everything. We often confuse talking with doing. But this takes time and effort away from success. Image, labels, and external recognition can distract from what actually matters: execution. The work itself is more important than what others and you call you. Don’t Take the Bait Ego thrives on provocation, whether it’s criticism, praise, or conflict. Don’t lose your temper or let yourself be pulled into unnecessary battles. Uncomfortable conversations will happen, but instead of reacting, let others reveal themselves. The real power is control. Stay on the Path Ego says “yes” too easily. Yes to recognition, to distractions, and to obligations that dilute focus. You want it all, what you have and what you don’t, but the challenge is to know what truly matters and stay on the path. Urgent things aren’t always important. The goal isn’t to please others but to pursue what really aligns with your values. Honor Over Honors There’s a strong distinction to make between honor and honors. Honor is about living with integrity and doing the work well. Honors, awards, fame, and titles are secondary. Success, in this view, is self-satisfaction: becoming the best you can be. Recognition and rewards are extras, not the goal. In particular, there’s a difference to make between global and selective fame. The first feeds the ego. It is loud, widespread, and often shallow; it seeks validation from the masses, many of whom don’t truly know or care about the substance behind the name. The second can affirm that you’re on the right path. It is quieter and more meaningful; it stems from being recognized by the people who matter: peers, mentors, or those who deeply understand the craft. Redefining Failure and Success The ego is terrified of failure and can even lead to it. Yet, failure from the outside can actually be success on the inside if it means we’ve stayed true to our principles. In the same way, outside “success” can be empty if it’s only about ego. My Final Thoughts This book felt quick and impactful, like a jab to the chin. It questioned my goals and aspirations in a good way. For anyone wishing to find success and perhaps fame, this is the book to read, not to suppress aspirations but to recenter objectives.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://yaacoub.github.io/social.webp" /><media:content medium="image" url="https://yaacoub.github.io/social.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">What I Learned from The Almanack of Naval Ravikant by Eric Jorgenson</title><link href="https://yaacoub.github.io/articles/loud-letters/what-i-learned-from-the-almanack-of-naval-ravikant-by-eric-jorgenson-copy/" rel="alternate" type="text/html" title="What I Learned from The Almanack of Naval Ravikant by Eric Jorgenson" /><published>2025-09-06T00:00:00+00:00</published><updated>2025-09-06T00:00:00+00:00</updated><id>https://yaacoub.github.io/articles/loud-letters/what-i-learned-from-the-almanack-of-naval-ravikant-by-eric-jorgenson%20copy</id><content type="html" xml:base="https://yaacoub.github.io/articles/loud-letters/what-i-learned-from-the-almanack-of-naval-ravikant-by-eric-jorgenson-copy/"><![CDATA[<h2 id="do-what-youre-100-into">Do What You’re 100% Into</h2>

<p>You shouldn’t do something just because it’s “hot.” Whether it’s a career move, a startup idea, or even a hobby, if you’re not fully into it, you won’t go far. Authenticity wins over imitation every time. Trying to copy others may work in the short term, but it doesn’t compound over time.</p>

<p>And when you hesitate or can’t decide, it’s usually a sign to say no. This also ties into time: when you catch yourself saying, “I don’t have time,” what you really mean is, “It’s not my priority.” Intention is about aligning words with actions.</p>

<h2 id="integrity-compounds-like-interest">Integrity Compounds Like Interest</h2>

<p>Reputation is like compound interest: it builds slowly, but the effects are exponential over time. That only works if you operate with high integrity. A single dishonest move can break what years of honesty have built. If you focus on long-term reputation, wealth and opportunities naturally follow.</p>

<h2 id="leverage-and-knowledge-over-time">Leverage and Knowledge Over Time</h2>

<p>A key idea is to shift from trading time for money to getting paid for your knowledge and judgment. Time is capped; leverage is infinite. Code, capital, and media are all forms of leverage that enable you to multiply your impact without increasing your hours. Until you get there, your input will be tied to your output. The goal is to break that equation.<br />
Short-term pain often leads to long-term gain here. Learning new skills, practicing judgment, and building knowledge can be uncomfortable in the moment, but compound massively over time.</p>

<h2 id="lifestyle-discipline">Lifestyle Discipline</h2>

<p>Another counterintuitive idea: hold your lifestyle fixed. The temptation is always to upgrade as income grows, but that only chains you to the need for more. Financial freedom comes from keeping expenses flat while your leverage and earnings increase. Freedom beats status games every time.</p>

<p>It’s also worth remembering that charisma, like freedom, isn’t about status or charm. It’s rather the projection of courage and love at the same time. It’s about being grounded and authentic.</p>

<h2 id="value-over-networking">Value Over Networking</h2>

<p>Early in your career, promotions can come faster in startups, but what matters more than titles or even “networking” is the actual value you bring. Deliver results, and networks form naturally around you. Don’t build relationships on ranking but on genuine peer respect. They are worth more than chasing social circles for their own sake.</p>

<h2 id="free-time-is-thinking-time">Free Time Is Thinking Time</h2>

<p>Real breakthroughs happen when you have time to think. Filling every hour with meetings, calls, or errands leaves no room for insights. If you can outsource your work, outsource it. Free time isn’t wasted time; it’s where clarity lives.</p>

<h2 id="peace-over-happiness">Peace Over Happiness</h2>

<p>Happiness is fleeting, peace is stable. Happiness comes and goes with circumstances. Peace is an internal state. Practices such as meditation are all ways to improve clarity and cultivate peace. It teaches you to watch your thoughts instead of fighting them.</p>

<p>When it comes to learning, read widely and have fun doing it, but don’t stop at interpretations. Go the extra mile and build solid knowledge from the fundamentals.</p>

<h2 id="my-final-thoughts">My Final Thoughts</h2>

<p>I really liked reading this book. I didn’t know what to expect at first, but the teachings, thoughts, and experience emanating from the words were impactful, to say the least. This felt more like reading philosophy than a productivity or business book, and it was freshening. I highly recommend this read to anyone interested in discovering the best ways of living a modern and free life.</p>]]></content><author><name>Peter Yaacoub</name></author><category term="articles" /><category term="loud-letters" /><summary type="html"><![CDATA[Do What You’re 100% Into]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://yaacoub.github.io/social.webp" /><media:content medium="image" url="https://yaacoub.github.io/social.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">What I Learned from A Mind For Numbers by Barbara Oakley</title><link href="https://yaacoub.github.io/articles/loud-letters/what-i-learned-from-a-mind-for-numbers-by-barbara-oakley/" rel="alternate" type="text/html" title="What I Learned from A Mind For Numbers by Barbara Oakley" /><published>2025-08-30T00:00:00+00:00</published><updated>2025-08-30T00:00:00+00:00</updated><id>https://yaacoub.github.io/articles/loud-letters/what-i-learned-from-a-mind-for-numbers-by-barbara-oakley</id><content type="html" xml:base="https://yaacoub.github.io/articles/loud-letters/what-i-learned-from-a-mind-for-numbers-by-barbara-oakley/"><![CDATA[<h2 id="focus-vs-diffuse-thinking">Focus vs. Diffuse Thinking</h2>

<p>Learning requires switching between two modes:</p>

<ul>
  <li>Focused mode: when you’re locked in, working through details.</li>
  <li>Diffuse mode: when your brain wanders, making connections in the background.</li>
</ul>

<p>Taking a break is part of working. Just like muscles need recovery between sets and workouts, the brain needs downtime for deep learning.</p>

<p>A great way to utilize diffuse mode is while being active, walking outside, running, or even doing housework.</p>

<h2 id="learning-slow-means-learning-deep">Learning Slow Means Learning Deep</h2>

<p>We all know that learning fast isn’t the same as learning well. Rushing leads to shallow understanding. Instead, spreading practice into short, daily sessions makes knowledge automatic. It’s just like working out. To build muscles, you don’t rush; you increase the weight gradually, with patience and consistency.</p>

<p>Even recalling information in different places helps lock it in. This could be at home, outside, or in class, for example.</p>

<h2 id="its-about-the-process-not-the-product">It’s About the Process, Not the Product</h2>

<p>Cramming the night before an exam is like going for your first run the day before a marathon. It doesn’t work. What matters is the process: daily practice, testing yourself, reviewing, and redoing.</p>

<p>When doing homework, the main focus shouldn’t be on finishing, but on the work itself. Treat each assignment as training for the test. Every session is a workout that slowly and methodically builds the skill.</p>

<h2 id="active-learning-beats-passive-learning">Active Learning Beats Passive Learning</h2>

<p>Some study methods feel productive but aren’t. Highlighting, for example, gives the illusion that what’s colored is already learned, or that anything not highlighted is unimportant when in fact it is.</p>

<p>Here’s what actually works:</p>

<ul>
  <li>Active recall: testing yourself without looking at the answer.</li>
  <li>The Feynman technique: explaining concepts simply, as if teaching.</li>
  <li>The Pomodoro method: short, focused sprints with breaks in between.</li>
</ul>

<h2 id="managing-willpower-and-stress">Managing Willpower and Stress</h2>

<p>Willpower is like a muscle: you can use it, but it gets tired. That’s why habits matter. They save willpower for when you really need it. (For more on habits, check out my takeaways from Atomic Habits by James Clear.)</p>

<p>Stress can also be valuable. Not panic-level stress, but just enough challenge to stay engaged. During exam prep, time yourself solving questions, or practice in a classroom setting. On test day, start by skimming all the exercises. Begin with the hardest, and when you get stuck, switch to an easier one. That puts the hard problem into diffuse mode while you make progress.</p>

<h2 id="mindsets-that-matter">Mindsets That Matter</h2>

<p>A eureka moment, when you finally grasp a solution, isn’t the end. What matters is understanding how the solution came about and reviewing it the same day.</p>

<p>If you’re doubting your intellect, skills, or accomplishments, you’re not alone; even experts feel imposter syndrome. And if you’re frustrated by low grades, remember: they may just mean you’re approaching problems differently. That difference could make you a more creative thinker. Nobody is “not good” at learning; they may just not have been exposed to all the lenses yet.</p>

<h2 id="experiment-compete-improve">Experiment, Compete, Improve</h2>

<p>Learning is a cycle of self-experimentation: try methods, determine what sticks, adjust. But it’s also important to distinguish between training (homework, practice) and competition (tests, real applications). Both are essential. Athletes don’t always win every competition, but they learn from each attempt and improve.</p>

<p>And mastery doesn’t mean you have to stick with something forever. It means building the skill so you can move on. It’s okay to “get good and then quit.”</p>

<h2 id="shared-wisdom">Shared Wisdom</h2>

<p>Learning is not just personal, it’s collective. Sharing ideas, questioning weak arguments, and working back and forth sharpens understanding. A good study environment is one where study wins over chatter.</p>

<p>If you’re in the same room as a friend, try doing the same homework separately and only asking for help when stuck. If you’re in different places, work on the same questions individually, then compare answers. If your answers differ, redo the exercise and compare again.</p>

<p>The Einstellung effect occurs when a pre-existing solution blinds you and blocks problem-solving. That’s why collaboration is key to opening your horizons. Techniques like diffuse-mode thinking also help your brain connect dots you wouldn’t have made otherwise.</p>

<h2 id="my-final-thoughts">My Final Thoughts</h2>

<p>I found the book’s strategies really helpful. One technique they used that I especially liked was ending chapters with active recall questions.</p>

<p>Like with Atomic Habits, I felt at first that I “already knew” much of what the author would say. I was wrong. The insights run much deeper once you apply them. That said, the book isn’t the easiest read. Not because it’s complex, but because the ideas are scattered. For this article, I actually had to reorder and regroup my notes to make sense of it all.</p>

<p>Still, the effort was worthwhile, and I recommend this book to anyone wishing to improve their learning.</p>]]></content><author><name>Peter Yaacoub</name></author><category term="articles" /><category term="loud-letters" /><summary type="html"><![CDATA[Focus vs. Diffuse Thinking Learning requires switching between two modes: Focused mode: when you’re locked in, working through details. Diffuse mode: when your brain wanders, making connections in the background. Taking a break is part of working. Just like muscles need recovery between sets and workouts, the brain needs downtime for deep learning. A great way to utilize diffuse mode is while being active, walking outside, running, or even doing housework. Learning Slow Means Learning Deep We all know that learning fast isn’t the same as learning well. Rushing leads to shallow understanding. Instead, spreading practice into short, daily sessions makes knowledge automatic. It’s just like working out. To build muscles, you don’t rush; you increase the weight gradually, with patience and consistency. Even recalling information in different places helps lock it in. This could be at home, outside, or in class, for example. It’s About the Process, Not the Product Cramming the night before an exam is like going for your first run the day before a marathon. It doesn’t work. What matters is the process: daily practice, testing yourself, reviewing, and redoing. When doing homework, the main focus shouldn’t be on finishing, but on the work itself. Treat each assignment as training for the test. Every session is a workout that slowly and methodically builds the skill. Active Learning Beats Passive Learning Some study methods feel productive but aren’t. Highlighting, for example, gives the illusion that what’s colored is already learned, or that anything not highlighted is unimportant when in fact it is. Here’s what actually works: Active recall: testing yourself without looking at the answer. The Feynman technique: explaining concepts simply, as if teaching. The Pomodoro method: short, focused sprints with breaks in between. Managing Willpower and Stress Willpower is like a muscle: you can use it, but it gets tired. That’s why habits matter. They save willpower for when you really need it. (For more on habits, check out my takeaways from Atomic Habits by James Clear.) Stress can also be valuable. Not panic-level stress, but just enough challenge to stay engaged. During exam prep, time yourself solving questions, or practice in a classroom setting. On test day, start by skimming all the exercises. Begin with the hardest, and when you get stuck, switch to an easier one. That puts the hard problem into diffuse mode while you make progress. Mindsets That Matter A eureka moment, when you finally grasp a solution, isn’t the end. What matters is understanding how the solution came about and reviewing it the same day. If you’re doubting your intellect, skills, or accomplishments, you’re not alone; even experts feel imposter syndrome. And if you’re frustrated by low grades, remember: they may just mean you’re approaching problems differently. That difference could make you a more creative thinker. Nobody is “not good” at learning; they may just not have been exposed to all the lenses yet. Experiment, Compete, Improve Learning is a cycle of self-experimentation: try methods, determine what sticks, adjust. But it’s also important to distinguish between training (homework, practice) and competition (tests, real applications). Both are essential. Athletes don’t always win every competition, but they learn from each attempt and improve. And mastery doesn’t mean you have to stick with something forever. It means building the skill so you can move on. It’s okay to “get good and then quit.” Shared Wisdom Learning is not just personal, it’s collective. Sharing ideas, questioning weak arguments, and working back and forth sharpens understanding. A good study environment is one where study wins over chatter. If you’re in the same room as a friend, try doing the same homework separately and only asking for help when stuck. If you’re in different places, work on the same questions individually, then compare answers. If your answers differ, redo the exercise and compare again. The Einstellung effect occurs when a pre-existing solution blinds you and blocks problem-solving. That’s why collaboration is key to opening your horizons. Techniques like diffuse-mode thinking also help your brain connect dots you wouldn’t have made otherwise. My Final Thoughts I found the book’s strategies really helpful. One technique they used that I especially liked was ending chapters with active recall questions. Like with Atomic Habits, I felt at first that I “already knew” much of what the author would say. I was wrong. The insights run much deeper once you apply them. That said, the book isn’t the easiest read. Not because it’s complex, but because the ideas are scattered. For this article, I actually had to reorder and regroup my notes to make sense of it all. Still, the effort was worthwhile, and I recommend this book to anyone wishing to improve their learning.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://yaacoub.github.io/social.webp" /><media:content medium="image" url="https://yaacoub.github.io/social.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>