<?xml version="1.0" encoding="utf-8"?>
  <feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US">
    <link href="https://nshipster.com/feed.xml" rel="self" type="application/atom+xml" />
    <link href="https://nshipster.com/" rel="alternate" type="text/html" hreflang="en-US"/>
    <updated>2025-12-31T08:19:21-08:00</updated>
    <id>https://nshipster.com/feed.xml</id>
    <title>NSHipster</title>
    <subtitle>NSHipster is a journal of the overlooked bits in Objective-C, Swift, and Cocoa.
    </subtitle>
    <author>
      <name>Mattt</name>
      <email>mattt@nshipster.com</email>
      <uri>https://nshipster.com/authors/mattt</uri>
    </author>
    <entry>
      <title type="html">Replay</title>
      <link href="https://nshipster.com/replay/" rel="alternate" type="text/html" title="Replay" />
      <published>2025-12-31T00:00:00-08:00</published>
      <updated>2025-12-31T00:00:00-08:00</updated>
      <id>https://nshipster.com/replay</id>
      <content type="html" xml:base="https://nshipster.com/replay/">
        &lt;p&gt;The year is 2025.
        You’re writing tests for networking code in your Swift app.&lt;/p&gt;
        &lt;p&gt;You could hit the live API,
        but then your tests are slow, flaky,
        and fail whenever that third-party service has a bad day.
        You could stub &lt;code&gt;URLSession&lt;/code&gt;,
        but then you’re maintaining two implementations of your networking layer.
        You could maintain JSON fixtures by hand,
        but there’s no way to capture real responses automatically,
        so your fixtures go stale without anyone noticing.&lt;/p&gt;
        &lt;p&gt;There’s a better approach:
        &lt;strong&gt;Record real HTTP traffic once, then replay it instantly for every subsequent test run.&lt;/strong&gt;
        This pattern has been battle-tested for over fifteen years in other languages.&lt;/p&gt;
        &lt;p&gt;&lt;a href=&quot;https://github.com/mattt/Replay&quot;&gt;Replay&lt;/a&gt; brings it to Swift.&lt;/p&gt;
        &lt;hr&gt;&lt;a id=&quot;get-on-with-it&quot;&gt;&lt;/a&gt;
        &lt;p&gt;In February 2010,
        &lt;a href=&quot;https://github.com/myronmarston&quot;&gt;Myron Marston&lt;/a&gt; created &lt;a href=&quot;https://github.com/vcr/vcr&quot;&gt;VCR&lt;/a&gt; for Ruby.
        Just like a videocassette recorder could capture television for later playback,
        VCR captured HTTP interactions so tests could replay them without hitting the network.
        Record once, play back forever.&lt;/p&gt;
        &lt;p&gt;The idea spread.
        Python got &lt;a href=&quot;https://github.com/kevin1024/vcrpy&quot;&gt;VCR.py&lt;/a&gt; and &lt;a href=&quot;https://github.com/kiwicom/pytest-recording&quot;&gt;pytest-recording&lt;/a&gt;.
        Java got &lt;a href=&quot;https://github.com/betamaxteam/betamax&quot;&gt;Betamax&lt;/a&gt; (continuing the home video theme).
        Go got &lt;a href=&quot;https://github.com/dnaeon/go-vcr&quot;&gt;go-vcr&lt;/a&gt;.&lt;/p&gt;
        &lt;p&gt;I’ve used VCR and pytest-recording for years
        and always missed having something comparable in Swift.
        &lt;a href=&quot;https://github.com/venmo/DVR&quot;&gt;DVR&lt;/a&gt; from Venmo came closest,
        using the same &lt;code&gt;URLProtocol&lt;/code&gt; injection point that Replay uses.
        But it was built for a different era of Swift —
        before we had the tools to make something that felt really nice.&lt;/p&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;for-auld-lang-syne&quot; href=&quot;#for-auld-lang-syne&quot;&gt;&lt;/a&gt;For Auld Lang Syne&lt;/h3&gt;
        &lt;p&gt;Being in conversation with that prior art means asking what’s different now.
        Two things stand out:&lt;/p&gt;
        &lt;p&gt;First, &lt;a href=&quot;https://en.wikipedia.org/wiki/HAR_%28file_format%29&quot;&gt;HAR&lt;/a&gt; became a &lt;em&gt;de facto&lt;/em&gt; standard.
        When Myron built VCR,
        there was no widely-adopted format for HTTP archives,
        so he invented one using YAML.
        That’s where the “cassette” terminology comes from.
        But around the same time,
        Jan Odvarko on the Firefox developer tools team was creating HAR (HTTP Archive).
        Today, every major browser exports HAR.
        As do Charles Proxy, Proxyman, mitmproxy, and Postman.&lt;/p&gt;
        &lt;p&gt;Replay uses HAR instead of inventing a new format.
        This means you can capture traffic from Safari’s Network tab and drop it directly into your test fixtures.
        You can inspect fixtures with any text editor.&lt;/p&gt;
        &lt;p&gt;Second, Swift finally has the extension points we need.
        Swift Testing traits —
        especially the
        &lt;a href=&quot;https://developer.apple.com/documentation/testing/testscoping&quot;&gt;&lt;code&gt;Test&lt;wbr&gt;&lt;/wbr&gt;Scoping&lt;/code&gt; protocol&lt;/a&gt;
        from Swift 6.1 —
        enable the kind of declarative, per-test configuration that pytest fixtures provide.
        Package plugins let us build integrated tooling that feels native.&lt;/p&gt;
        &lt;p&gt;These capabilities simply didn’t exist before —
        not in any way that felt intuitive or convenient.&lt;/p&gt;
        &lt;hr&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;how-replay-works&quot; href=&quot;#how-replay-works&quot;&gt;&lt;/a&gt;How Replay Works&lt;/h2&gt;
        &lt;p&gt;Add &lt;code&gt;.replay&lt;/code&gt; to a test and Replay intercepts HTTP requests,
        serving responses from a HAR file instead of hitting the network:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Testing&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Replay&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Codable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;@Test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;replay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;fetch&lt;wbr&gt;&lt;/wbr&gt;User&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fetch&lt;wbr&gt;&lt;/wbr&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;URLSession&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://api.example.com/users/42&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;JSONDecoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;cp&quot;&gt;#expect(user.id == 42)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;The &lt;code&gt;.replay(&quot;fetch&lt;wbr&gt;&lt;/wbr&gt;User&quot;)&lt;/code&gt; trait loads responses from &lt;code&gt;Replays/fetch&lt;wbr&gt;&lt;/wbr&gt;User.har&lt;/code&gt;.
        Your production code uses &lt;code&gt;URLSession&lt;/code&gt; normally.
        No protocols to define.
        No mocks to inject.
        Replay’s interception uses built-in affordances in the
        &lt;a href=&quot;https://developer.apple.com/documentation/foundation/url-loading-system&quot;&gt;Foundation URL Loading System&lt;/a&gt;,
        so it works with &lt;code&gt;URLSession.shared&lt;/code&gt;, custom sessions, and libraries like &lt;a href=&quot;/alamofire&quot;&gt;Alamofire&lt;/a&gt;.&lt;/p&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;the-recording-workflow&quot; href=&quot;#the-recording-workflow&quot;&gt;&lt;/a&gt;The Recording Workflow&lt;/h3&gt;
        &lt;p&gt;The first time you run a test with &lt;code&gt;.replay&lt;/code&gt;, it fails intentionally:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;plaintext&quot;&gt;&lt;code&gt;❌  Test fetch&lt;wbr&gt;&lt;/wbr&gt;User() recorded an issue at Example&lt;wbr&gt;&lt;/wbr&gt;Tests.swift
        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
        ⚠️  No Matching Entry in Archive
        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
        Request: GET https://api.example.com/users/42
        Archive: /path/to/.../Replays/fetch&lt;wbr&gt;&lt;/wbr&gt;User.har
        This request was not found in the replay archive.
        Options:
        1. Run against the live network:
        REPLAY_PLAYBACK_MODE=live swift test --filter &amp;lt;test-name&amp;gt;
        2. Record the archive:
        REPLAY_RECORD_MODE=once swift test --filter &amp;lt;test-name&amp;gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;This is deliberate.
        Accidental recording could capture credentials, PII, or session tokens.
        By requiring you to opt into recording explicitly,
        Replay ensures you’re always aware when network traffic is being captured.&lt;/p&gt;
        &lt;p&gt;So let’s do that now:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;REPLAY_RECORD_MODE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;once swift &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--filter&lt;/span&gt; fetch&lt;wbr&gt;&lt;/wbr&gt;User
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;This hits the real API, captures the response, and saves it to &lt;code&gt;Replays/fetch&lt;wbr&gt;&lt;/wbr&gt;User.har&lt;/code&gt;.
        From then on, the test runs instantly against the recorded fixture.
        There’s something deeply satisfying about watching a test suite that used to take minutes finish in seconds.&lt;/p&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;whats-in-a-har-file&quot; href=&quot;#whats-in-a-har-file&quot;&gt;&lt;/a&gt;What’s in a HAR File&lt;/h3&gt;
        &lt;p&gt;A HAR file is just JSON:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;JSON&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;log&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;1.2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;creator&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Replay&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;1.0&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;entries&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;request&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;method&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;GET&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://api.example.com/users/42&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;headers&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Accept&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;application/json&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;response&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;mime&lt;wbr&gt;&lt;/wbr&gt;Type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;application/json&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;{&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:42,&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Alice&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;}&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;Human-readable.
        Editable.
        Compatible with a vast ecosystem of tools.
        🧑‍🍳💋&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;handling-sensitive-data&quot; href=&quot;#handling-sensitive-data&quot;&gt;&lt;/a&gt;Handling Sensitive Data&lt;/h2&gt;
        &lt;p&gt;HAR files have a way of accumulating secrets.
        Session cookies, authorization headers, API keys —
        all captured faithfully alongside the responses you actually care about.&lt;/p&gt;
        &lt;p&gt;Replay addresses this with filters that strip sensitive data during recording:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;@Test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;replay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;fetch&lt;wbr&gt;&lt;/wbr&gt;User&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;filters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;removing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Authorization&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Cookie&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;query&lt;wbr&gt;&lt;/wbr&gt;Parameters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;removing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;token&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;api_key&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fetch&lt;wbr&gt;&lt;/wbr&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;The general principle:
        configure filters before recording, not after.&lt;/p&gt;
        &lt;aside class=&quot;admonition warning&quot;&gt;
        &lt;p&gt;Always review HAR fixtures before committing.&lt;/p&gt;
        &lt;p&gt;In October 2023,
        &lt;a href=&quot;https://www.nightfall.ai/blog/okta-data-breach-what-happened-impact-and-security-lessons-learned&quot;&gt;Okta suffered a breach&lt;/a&gt;
        after attackers obtained HAR files containing session tokens.
        In response,
        Cloudflare released a &lt;a href=&quot;https://har-sanitizer.pages.dev&quot;&gt;HAR sanitizer&lt;/a&gt;
        and Chrome added &lt;a href=&quot;https://developer.chrome.com/docs/devtools/network/reference&quot;&gt;built-in sanitization&lt;/a&gt; to DevTools.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;flexible-matching&quot; href=&quot;#flexible-matching&quot;&gt;&lt;/a&gt;Flexible Matching&lt;/h2&gt;
        &lt;p&gt;By default, Replay matches requests by HTTP method and full URL.
        For APIs with volatile query parameters
        (pagination cursors, timestamps, cache-busters),
        you can configure looser matching:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;@Test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;replay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;fetch&lt;wbr&gt;&lt;/wbr&gt;User&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;matching&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fetch&lt;wbr&gt;&lt;/wbr&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;Available matchers include
        &lt;code&gt;.method&lt;/code&gt;, &lt;code&gt;.url&lt;/code&gt;, &lt;code&gt;.host&lt;/code&gt;, &lt;code&gt;.path&lt;/code&gt;, &lt;code&gt;.query&lt;/code&gt;, &lt;code&gt;.headers([...])&lt;/code&gt;, &lt;code&gt;.body&lt;/code&gt;,
        and &lt;code&gt;.custom(...)&lt;/code&gt; for arbitrary logic.&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;inline-stubs&quot; href=&quot;#inline-stubs&quot;&gt;&lt;/a&gt;Inline Stubs&lt;/h2&gt;
        &lt;p&gt;Replay also supports inline stubs:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;@Test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;replay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;stubs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://api.example.com/health&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Content-Type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;application/json&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;cp&quot;&gt;#&quot;{&quot;status&quot;: &quot;ok&quot;}&quot;#&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test&lt;wbr&gt;&lt;/wbr&gt;Health&lt;wbr&gt;&lt;/wbr&gt;Check&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;URLSession&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://api.example.com/health&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;cp&quot;&gt;#expect(String(data: data, encoding: .utf8) == #&quot;{&quot;status&quot;: &quot;ok&quot;}&quot;#)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;This is useful for testing error handling, edge cases,
        or scenarios where the response content matters less than the status code.&lt;/p&gt;
        &lt;aside class=&quot;admonition info&quot;&gt;
        &lt;p&gt;Martin Fowler’s 2006 article
        &lt;a href=&quot;https://martinfowler.com/articles/mocksArentStubs.html&quot;&gt;“Mocks Aren’t Stubs”&lt;/a&gt;
        introduces a taxonomy of &lt;em&gt;test doubles&lt;/em&gt;:
        &lt;em&gt;dummies&lt;/em&gt; (passed but never used),
        &lt;em&gt;fakes&lt;/em&gt; (working but simplified implementations),
        &lt;em&gt;stubs&lt;/em&gt; (canned responses),
        &lt;em&gt;spies&lt;/em&gt; (stubs that record calls), and
        &lt;em&gt;mocks&lt;/em&gt; (objects with built-in expectations).&lt;/p&gt;
        &lt;p&gt;According to this ontology,
        Replay’s fixtures are &lt;em&gt;stubs&lt;/em&gt; —
        they provide predetermined responses without verifying how they’re called.
        But unlike hand-rolled stubs that drift from reality,
        these are captured from real API traffic,
        so they stay honest.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;hr&gt;
        &lt;p&gt;Fifteen years of refinement across
        Ruby, Python, JavaScript, and other ecosystems
        have established clear best practices for HTTP recording:
        capture real traffic,
        strip sensitive data,
        fail fast when fixtures are missing,
        provide good error messages when things go wrong.
        Replay brings all of that to Swift.&lt;/p&gt;
        &lt;p&gt;If you’ve been struggling with flaky API tests,
        or putting off testing your network code because the overhead felt too high,
        resolve to give Replay a try.&lt;/p&gt;
        &lt;aside class=&quot;parenthetical&quot;&gt;
        &lt;p&gt;And if you’re reading this on New Year’s Eve,
        consider it a gift — patterns that have proven themselves,
        carried forward into a new year. 🥂&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;&lt;a href=&quot;https://github.com/mattt/Replay&quot;&gt;Replay is open source on GitHub.&lt;/a&gt;
        Let me know what you think!&lt;/p&gt;
      </content>
      <author>
        <name>Mattt</name>
        <email>mattt@nshipster.com</email>
        <uri>https://nshipster.com/authors/mattt/</uri>
      </author>
      <category term="Miscellaneous" />
      <summary type="html">&lt;p&gt;Fast, reliable API tests without mocks or stale JSON fixtures. Replay records real HTTP traffic once (as HAR) and replays it instantly with Swift Testing so your networking code stays honest and your test suite stays fast.&lt;/p&gt;</summary>
    </entry>
    <entry>
      <title type="html">Manim</title>
      <link href="https://nshipster.com/manim/" rel="alternate" type="text/html" title="Manim" />
      <published>2025-10-01T00:00:00-07:00</published>
      <updated>2025-10-01T00:00:00-07:00</updated>
      <id>https://nshipster.com/manim</id>
      <content type="html" xml:base="https://nshipster.com/manim/">
        &lt;p&gt;A few years ago,
        Twitter user &lt;a href=&quot;https://x.com/38mo1/&quot;&gt;@38mo1&lt;/a&gt;,
        a chemistry teacher from Japan,
        posted a &lt;a href=&quot;https://x.com/38mo1/status/1320004943542009857&quot;&gt;Halloween × Boolean logic meme&lt;/a&gt;
        that I liked enough to save to &lt;code&gt;~/Downloads&lt;/code&gt;.
        And ever since,
        I’ve had a yearly reminder every October 1st
        to open the image and get a seasonal chuckle 🎃&lt;/p&gt;
        &lt;p&gt;More recently,
        I wanted to teach my kids some advanced snake maths
        (&lt;a href=&quot;https://www.youtube.com/watch?v=ysaIAwxl7fc&quot;&gt;long story&lt;/a&gt; 🐍)
        and remembered that the software
        &lt;a href=&quot;https://www.youtube.com/c/3blue1brown&quot;&gt;3blue1brown&lt;/a&gt; uses for their videos was open-source.&lt;/p&gt;
        &lt;p&gt;Which is all to say that this year for Halloween,
        NSHipster is dressing up as a beloved YouTuber.
        How’d I do?&lt;/p&gt;
        &lt;video preload=&quot;none&quot; width=&quot;1040&quot; controls=&quot;&quot; poster=&quot;/assets/TrickXORTreat-poster-ed2a0cfb0602129783a2d432601b7864d1fdf6b37bcb0dd091c991f62c72dfc3fdcf7547373e1daff2adca66628bcd2fbb0d2f1c89da9946a3f0da045b79097a.png&quot;&gt;
        &lt;source src=&quot;/assets/TrickXORTreat-188e3263cc00aadf31d1251d178a7e35702c83407adc6f46c311d7df0fe9f6a24c951b72471d42f95a5bcdd1ade39042856497a5672ee531404c590326fedbd5.mp4&quot; type=&quot;video/mp4&quot;&gt;&lt;/source&gt;
        &lt;track kind=&quot;subtitles&quot; src=&quot;/assets/TrickXORTreat-e674f6fcbd62ba120d79d7c04b60396e2593e09921fcf992c95ad39e382f626702425e01ac3be63cc17b82fe0dccd2baad121ec7f6175213a99f33dc6263f8e2.srt&quot; srclang=&quot;en&quot; label=&quot;English Subtitles&quot; default=&quot;&quot;&gt;&lt;/track&gt;
        &lt;/video&gt;
        &lt;p&gt;&lt;em&gt;Neat, right?&lt;/em&gt;
        Everything used to create that video
        &lt;a href=&quot;https://github.com/nshipster/trick-xor-treat&quot;&gt;available on GitHub&lt;/a&gt;.
        Read on to learn more about how to get started on your next great explainer.&lt;/p&gt;
        &lt;hr&gt;&lt;a id=&quot;get-on-with-it&quot;&gt;&lt;/a&gt;
        &lt;p&gt;Back in 2015, Grant Sanderson found himself at a hackathon
        with a desire to practice his Python skills.
        What emerged was “very scrappy code for visualizing functions as transformations” —
        a playful experiment that would eventually become the foundation of both
        the 3Blue1Brown YouTube channel
        (now 6.5+ million subscribers strong)
        and Manim itself.&lt;/p&gt;
        &lt;aside class=&quot;admonition info&quot;&gt;
        &lt;p&gt;By 2020, the community wanted stability and documentation.
        A fork emerged: &lt;strong&gt;Manim Community Edition (ManimCE)&lt;/strong&gt; for general use,
        while Sanderson’s version became &lt;strong&gt;ManimGL&lt;/strong&gt; for his own experimentation.
        Today both versions thrive with distinct purposes.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;0-to-1&quot; href=&quot;#0-to-1&quot;&gt;&lt;/a&gt;0 to 1&lt;/h2&gt;
        &lt;p&gt;Manim has a reputation for being difficult to install.
        Some of this is a natural consequence for a tool
        whose audience extends to self-described non-programmers.
        Some of this is intrinsic to working with motion graphics.
        And being written in Python doesn’t do it any favors
        (though &lt;code&gt;uv&lt;/code&gt; pretty much solves all the complaints anyone could have).&lt;/p&gt;
        &lt;p&gt;Docker was more or less invented to solve the problem of
        packaging Python applications with system dependencies,
        so it’s entirely appropriate to wash your hands of everything and
        &lt;a href=&quot;https://docs.manim.community/en/stable/installation/docker.html&quot;&gt;run Manim with Docker&lt;/a&gt;:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;shell&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/full/path/to/your/directory:/manim&quot;&lt;/span&gt; manimcommunity/manim manim &lt;span class=&quot;nt&quot;&gt;-qm&lt;/span&gt; scene.py My&lt;wbr&gt;&lt;/wbr&gt;Scene&lt;wbr&gt;&lt;/wbr&gt;Name
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;…but that feels like giving up.&lt;/p&gt;
        &lt;p&gt;And besides,
        you’ll appreciate having a proper Python development environment
        once you’re up-and-running.
        Stick with me,
        and I promise everything will be A-OK (pinky swear 🤙).&lt;/p&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;an-opinionated-setup-guide-for-manim-on-macos-in-2025&quot; href=&quot;#an-opinionated-setup-guide-for-manim-on-macos-in-2025&quot;&gt;&lt;/a&gt;An opinionated setup guide for Manim on macOS in 2025&lt;/h3&gt;
        &lt;p&gt;First,
        let’s do some &lt;em lang=&quot;fr&quot;&gt;mise en place&lt;/em&gt;:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;shell&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Install mise&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;mise
        &lt;span class=&quot;c&quot;&gt;# Install Python and uv&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mise use &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; python@3.13 uv@latest
        &lt;/code&gt;&lt;/pre&gt;
        &lt;ul&gt;
        &lt;li&gt;
        &lt;a href=&quot;https://brew.sh&quot;&gt;Homebrew&lt;/a&gt; is a package manager for macOS.
        It’s the best way to install the system dependencies we need to run Manim.&lt;/li&gt;
        &lt;li&gt;
        &lt;a href=&quot;https://mise.jdx.dev&quot;&gt;Mise&lt;/a&gt; is a polyglot tool manager.
        While you &lt;em&gt;could&lt;/em&gt; use Homebrew to install Python,
        you often need to keep a few versions around to work across different projects.
        So that’s what we’ll recommend here.
        &lt;aside class=&quot;parenthetical&quot;&gt;
        &lt;p&gt;Mise is slick. 
        I like it way more than anything else I’ve tried,
        and I think you’ll like it, too.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;/li&gt;
        &lt;li&gt;
        &lt;a href=&quot;https://docs.astral.sh/uv/&quot;&gt;uv&lt;/a&gt; is a Python package manager.
        It’s wicked fast and &lt;em&gt;just works™&lt;/em&gt;.
        &lt;aside class=&quot;parenthetical&quot;&gt;
        &lt;p&gt;It’s hard to say too many nice things about &lt;code&gt;uv&lt;/code&gt;. 
        It really is that good.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;/li&gt;
        &lt;/ul&gt;
        &lt;p&gt;Now,
        let’s create our project and make ourselves at home:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;shell&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Create a new project&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;uv init my-explainer
        &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;my-explainer
        &lt;span class=&quot;c&quot;&gt;# Now open with your preferred $EDITOR&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;Next,
        go ahead and install Manim’s system dependencies:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;shell&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Install Manim dependencies&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;pkg-config cairo &lt;span class=&quot;c&quot;&gt;# for graphics&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--cask&lt;/span&gt; mactex-no-gui &lt;span class=&quot;c&quot;&gt;# for ƒοrmυℓαѕ&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;sox &lt;span class=&quot;c&quot;&gt;# for voiceovers&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;ul&gt;
        &lt;li&gt;
        &lt;a href=&quot;https://www.cairographics.org&quot;&gt;Cairo&lt;/a&gt; is a 2D graphics library.
        You need &lt;code&gt;pkg-config&lt;/code&gt; to get the Pycairo bindings working properly.&lt;/li&gt;
        &lt;li&gt;
        &lt;a href=&quot;https://www.tug.org/mactex/&quot;&gt;MacTex&lt;/a&gt; is a LaTeX distribution for macOS.
        You’ll need this to make a proper maths explainer with impressive-looking formulas.
        We recommend downloading &lt;code&gt;mactex-no-gui&lt;/code&gt;,
        which foregoes the GUI apps that ship in the full version.&lt;/li&gt;
        &lt;li&gt;
        &lt;a href=&quot;https://sourceforge.net/projects/sox/&quot;&gt;SoX&lt;/a&gt; is a utility for
        converting audio files to different formats.
        Manim has some nice-_ish_ affordances for putting voice-overs into your scenes,
        and you’ll need SoX to take advantage of them.&lt;/li&gt;
        &lt;/ul&gt;
        &lt;p&gt;Finally,
        let’s run a health check to see if we’re still on the happy path:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;shell&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Is everything working? (🫣)&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;uv run manim checkhealth
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;&lt;em&gt;Huzzah!&lt;/em&gt;&lt;/p&gt;
        &lt;aside class=&quot;parenthetical&quot;&gt;
        &lt;p&gt;I hope that’s what you exclaimed, at least. 
        If luck’s not on your side, there’s always Docker 🤷🏻‍♂️&lt;/p&gt;
        &lt;/aside&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;setting-the-scene&quot; href=&quot;#setting-the-scene&quot;&gt;&lt;/a&gt;Setting the Scene&lt;/h2&gt;
        &lt;p&gt;The Manim API is &lt;a href=&quot;https://docs.manim.community/en/stable/tutorials_guides.html&quot;&gt;rich and well-documented&lt;/a&gt;,
        with an &lt;a href=&quot;https://docs.manim.community/en/stable/examples.html&quot;&gt;extensive collection of examples&lt;/a&gt;.
        Rather than attempt to explain everything here,
        let’s look at one concrete example to get a sense of how it all works.&lt;/p&gt;
        &lt;p&gt;Here’s a standalone “Trick XOR Treat” scene:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Python&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;manim&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Trick&lt;wbr&gt;&lt;/wbr&gt;XORTreat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Scene&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;construct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Panel background
        &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;panel_bg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Rounded&lt;wbr&gt;&lt;/wbr&gt;Rectangle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;corner_radius&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_fill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;GREY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Title
        &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Trick XOR Treat&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;move_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;panel_bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DOWN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Two circles for the Venn diagram
        &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;c1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Circle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;radius&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BLACK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;move_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LEFT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;c2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Circle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;radius&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BLACK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;move_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RIGHT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Create individual fill shapes for XOR (exclusive OR)
        &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;left_only&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Difference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_fill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ORANGE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;right_only&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Difference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_fill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ORANGE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;center&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Intersection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_fill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GREY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# XOR excludes center
        &lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Create faces on left and right sections
        &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;face&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VGroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Left face
        &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;left_eye&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Circle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;radius&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BLACK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fill_opacity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;left_eye&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;move_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;left_only&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;left_mouth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Parametric&lt;wbr&gt;&lt;/wbr&gt;Function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.15&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PI&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t_range&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_stroke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BLACK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;left_mouth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;move_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;left_only&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DOWN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Right face
        &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;right_eye&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Circle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;radius&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BLACK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fill_opacity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;right_eye&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;move_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;right_only&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;right_mouth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Parametric&lt;wbr&gt;&lt;/wbr&gt;Function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.15&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PI&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t_range&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_stroke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BLACK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;right_mouth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;move_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;right_only&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DOWN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;face&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;left_eye&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;left_mouth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right_eye&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right_mouth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Combine everything
        &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;panel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VGroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;panel_bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;left_only&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;right_only&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;VGroup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Circle outlines
        &lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;face&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;panel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;move_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ORIGIN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Animate the panel appearing with smooth scaling
        &lt;/span&gt;        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;play&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Fade&lt;wbr&gt;&lt;/wbr&gt;In&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;panel_bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scale&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run_time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run_time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Draw circles sequentially
        &lt;/span&gt;        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;play&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run_time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;play&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run_time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Dramatic filling animations with smooth rate functions
        &lt;/span&gt;        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;play&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;left_only&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;animate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_fill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ORANGE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;run_time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;rate_func&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;smooth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;play&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;right_only&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;animate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_fill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ORANGE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;run_time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;rate_func&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;smooth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Animate faces appearing on top of fills with bounce
        &lt;/span&gt;        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;play&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Fade&lt;wbr&gt;&lt;/wbr&gt;In&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;face&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shift&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UP&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scale&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run_time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Final pause
        &lt;/span&gt;        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;The Manim API is refreshingly procedural—
        a nice break from the declarative nature of SwiftUI, if you ask me.
        You create objects, position them, and then explicitly tell them what to do.
        The &lt;code&gt;.animate&lt;/code&gt; syntax provides some syntactic sugar for transformations,
        but at its core, this is imperative programming at its finest.&lt;/p&gt;
        &lt;aside class=&quot;admonition warning&quot;&gt;
        &lt;p&gt;As far as I can tell, &lt;code&gt;Scene&lt;/code&gt; objects aren’t composable.
        Or at least there wasn’t an immediately obvious way to do so
        (please correct me if I’m wrong).
        Rather than fussing over that,
        I plowed ahead with writing a giant &lt;code&gt;construct&lt;/code&gt; method.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;enter-the-development-loop&quot; href=&quot;#enter-the-development-loop&quot;&gt;&lt;/a&gt;Enter the Development Loop&lt;/h2&gt;
        &lt;p&gt;Our example project includes a Mise task for quickly previewing our scene.
        It runs Manim at a low
        &lt;a href=&quot;https://www.youtube.com/watch?v=1unkluyh2Ks&quot;&gt;resolution&lt;/a&gt; (480p) and
        &lt;a href=&quot;https://www.youtube.com/watch?v=DyqjTZHRdRs&quot;&gt;frame rate&lt;/a&gt; (15 fps),
        and then opens the generated file in QuickTime Player.&lt;/p&gt;
        &lt;!-- ☝️ Shout-out to another favorite YouTube channel. Love ya, Captain --&gt;
        &lt;aside class=&quot;parenthetical&quot;&gt;
        &lt;p&gt;It also does a &lt;code&gt;killall&lt;/code&gt; first to make sure the file opens fresh.
        Something about the contents of an open file changing doesn’t sit well with
        ‘ole bluey &lt;!-- QuickTime, I mean --&gt;&lt;/p&gt;
        &lt;/aside&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;shell&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mise run preview
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;The project also has a &lt;code&gt;render&lt;/code&gt; task for when you’re ready to share it around:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;shell&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mise run render
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;If everything works as intended, you should see something like this:&lt;/p&gt;
        &lt;video preload=&quot;none&quot; width=&quot;1040&quot; poster=&quot;/assets/TrickORTreat-poster-9044eb0055f168263a99190dcf469f15b6c560a87be925533f460f24b23a2eba3be5ddfad63da7bc2e066e25e42baacdd22b7afd6c268edd5b03354bcf55195f.png&quot; controls=&quot;&quot;&gt;
        &lt;source src=&quot;/assets/TrickORTreat-32dfe3bced27d23322074169a592d0345c26ff50dac74c4a0cc35511fd8768832129d1cd4ac2f1086297ac53c069d2b001901d73deb71ca679ae23702df75700.mp4&quot; type=&quot;video/mp4&quot;&gt;&lt;/source&gt;
        &lt;/video&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;voiceover&quot; href=&quot;#voiceover&quot;&gt;&lt;/a&gt;(Voiceover)&lt;/h2&gt;
        &lt;p&gt;No 3blue1brown explainer video would be complete
        without the dulcet baritone of its creator.
        Alas,
        Mr. Sanderson had previous obligations that took him away from our costume party,
        so we’ll have to improvise.
        Let’s crank up the spook factor and have an AI… &lt;em&gt;ghost? I guess?&lt;/em&gt; narrate our flick.&lt;/p&gt;
        &lt;p&gt;&lt;a href=&quot;https://elevenlabs.io&quot;&gt;ElevenLabs&lt;/a&gt; has some scary-good text-to-speech models.
        While &lt;code&gt;manim-voiceover&lt;/code&gt; provides integration,
        it’s currently a bit temperamental with Python 3.13
        and doesn’t support the latest
        &lt;a href=&quot;https://elevenlabs.io/v3&quot;&gt;v3 models&lt;/a&gt;
        for hyper-realistic voiceovers.&lt;/p&gt;
        &lt;aside class=&quot;admonition error&quot;&gt;
        &lt;p&gt;The official &lt;code&gt;manim-voiceover&lt;/code&gt; package doesn’t play nicely with Python 3.13,
        and doesn’t support ElevenLabs’ &lt;abbr title=&quot;State of the Art&quot;&gt;SOTA&lt;/abbr&gt; v3 models.
        I found &lt;a href=&quot;https://pypi.org/project/manim-voiceover-fixed/&quot;&gt;a fork&lt;/a&gt;
        that got me what I needed, but YMMV.&lt;/p&gt;
        &lt;p&gt;Here’s the error message I wrestled with for the better part of an hour, for posterity:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;go&quot;&gt;uv add manim-voiceover[elevenlabs,transcribe] openai-whisper
        × Failed to build `openai-whisper==20230314`
        ├─▶ The build backend returned an error
        ╰─▶ Call to `setuptools.build_meta:__legacy__.build_wheel` failed (exit status: 1)
        &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
        &lt;/aside&gt;
        &lt;p&gt;To get started, you import from &lt;code&gt;manim_voiceover&lt;/code&gt; (&lt;code&gt;_fixed&lt;/code&gt;)
        and update the scene to inherit from &lt;code&gt;Voiceover&lt;wbr&gt;&lt;/wbr&gt;Scene&lt;/code&gt;.&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Python&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;manim_voiceover_fixed&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Voiceover&lt;wbr&gt;&lt;/wbr&gt;Scene&lt;/span&gt;
        &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;manim_voiceover_fixed.services.elevenlabs&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Eleven&lt;wbr&gt;&lt;/wbr&gt;Labs&lt;wbr&gt;&lt;/wbr&gt;Service&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Trick&lt;wbr&gt;&lt;/wbr&gt;XORTreat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Voiceover&lt;wbr&gt;&lt;/wbr&gt;Scene&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;construct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_speech_service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Eleven&lt;wbr&gt;&lt;/wbr&gt;Labs&lt;wbr&gt;&lt;/wbr&gt;Service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;voice_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Liam&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;eleven_v3&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;transcription_model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# &amp;lt;-- workaround for https://github.com/Manim&lt;wbr&gt;&lt;/wbr&gt;Community/manim-voiceover/issues/114
        &lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;voiceover&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;[annoyingly high-pitch nasal pedantic] Well, actually,
        it's an exclusive or, also known as XOR...&quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# This wait() automatically waits until the voiceover finishes!
        &lt;/span&gt;            &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;The &lt;code&gt;wait()&lt;/code&gt; inside the context manager waits until the voiceover finishes —
        no manual timing required.
        For recorded voiceovers especially,
        this dramatically cuts down on how much time you spend in post
        getting the timing right.
        In fact, the finished video at the top was entirely rendered by Manim—
        without any touch-ups in Final Cut or Premiere!&lt;/p&gt;
        &lt;aside class=&quot;parenthetical&quot;&gt;
        &lt;p&gt;It’s genuinely unnerving how good these frontier text-to-speech models have gotten.
        The fact that you can add annotations like &lt;code&gt;[kid sing-songy]&lt;/code&gt; or 
        &lt;code&gt;[annoyingly high-pitch nasal pedantic]&lt;/code&gt; 
        and have the model &lt;em&gt;actually deliver&lt;/em&gt; is… &lt;em&gt;(dare I say it?)&lt;/em&gt; spooky&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;The first time you run this code,
        Manim will helpfully (albeit unexpectedly) prompt you to enter an API token,
        which you can get &lt;a href=&quot;https://elevenlabs.io/app/developers&quot;&gt;in your account dashboard&lt;/a&gt;.
        That’ll get saved to an &lt;a href=&quot;https://nshipster.com/1password-cli/&quot;&gt;&lt;code&gt;.env&lt;/code&gt; file&lt;/a&gt;
        and that should be the end of it.&lt;/p&gt;
        &lt;hr&gt;
        &lt;p&gt;The best explainer videos don’t just teach,
        they spark curiosity, they delight, they make complex ideas feel approachable.
        That’s what drew me to 3blue1brown in the first place,
        and why I’ve kept that silly meme in my Downloads folder all these years.&lt;/p&gt;
        &lt;p&gt;So if you’ve been sitting on a meme in your &lt;code&gt;~/Downloads&lt;/code&gt; folder,
        or just want an excuse to dust off those Python skills,
        maybe this Halloween &lt;em&gt;you&lt;/em&gt; dress up as a math YouTuber, too.
        The costume’s open source, and honestly?
        It’s a pretty good look.&lt;/p&gt;
      </content>
      <author>
        <name>Mattt</name>
        <email>mattt@nshipster.com</email>
        <uri>https://nshipster.com/authors/mattt/</uri>
      </author>
      <category term="Miscellaneous" />
      <summary type="html">&lt;p&gt;This year for Halloween, NSHipster is dressing up as 3blue1brown. And thanks to his open-source math animation library, we’re &lt;em&gt;totally&lt;/em&gt; pulling it off.&lt;/p&gt;</summary>
    </entry>
    <entry>
      <title type="html">@isolated(any)</title>
      <link href="https://nshipster.com/isolated-any/" rel="alternate" type="text/html" title="@isolated(any)" />
      <published>2025-08-04T00:00:00-07:00</published>
      <updated>2025-08-04T00:00:00-07:00</updated>
      <id>https://nshipster.com/isolated-any</id>
      <content type="html" xml:base="https://nshipster.com/isolated-any/">
        &lt;p&gt;Ahh, &lt;code&gt;@isolated(any)&lt;/code&gt;.
        It’s an attribute of contradictions.
        You might see it a lot, but it’s ok to ignore it.
        You don’t need to use it, but I think it should be used more.
        It must always take an argument, but that argument cannot vary.&lt;/p&gt;
        &lt;p&gt;Confusing? Definitely.
        But we’ll get to it all.&lt;/p&gt;
        &lt;hr&gt;&lt;a id=&quot;get-on-with-it&quot;&gt;&lt;/a&gt;
        &lt;p&gt;To understand why &lt;code&gt;@isolated(any)&lt;/code&gt; was introduced,
        we need to take a look at async functions.&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;respond&lt;wbr&gt;&lt;/wbr&gt;To&lt;wbr&gt;&lt;/wbr&gt;Emergency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;This is about as simple a function type as we can get.
        But, things start to get a little more interesting
        when we look at how a function like this is used.
        A variable with this type must always be invoked with &lt;code&gt;await&lt;/code&gt;.&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;respond&lt;wbr&gt;&lt;/wbr&gt;To&lt;wbr&gt;&lt;/wbr&gt;Emergency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;This, of course, makes sense.
        All async functions must be called with &lt;code&gt;await&lt;/code&gt;.
        But! Consider this:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;send&lt;wbr&gt;&lt;/wbr&gt;Ambulance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;@Main&lt;wbr&gt;&lt;/wbr&gt;Actor&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;🚑 WEE-OOO WEE-OOO!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;respond&lt;wbr&gt;&lt;/wbr&gt;To&lt;wbr&gt;&lt;/wbr&gt;Emergency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;send&lt;wbr&gt;&lt;/wbr&gt;Ambulance&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;respond&lt;wbr&gt;&lt;/wbr&gt;To&lt;wbr&gt;&lt;/wbr&gt;Emergency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;The explicit types are there to help make what’s going on clear.
        We first define a &lt;strong&gt;synchronous&lt;/strong&gt; function that &lt;em&gt;&lt;strong&gt;must&lt;/strong&gt;&lt;/em&gt; run on the &lt;code&gt;Main&lt;wbr&gt;&lt;/wbr&gt;Actor&lt;/code&gt;.
        And then we assign that to a plain old,
        non-&lt;code&gt;Main&lt;wbr&gt;&lt;/wbr&gt;Actor&lt;/code&gt; async function.
        We’ve changed so much that you might find it surprising this even compiles.&lt;/p&gt;
        &lt;p&gt;Remember what &lt;code&gt;await&lt;/code&gt; actually does. It allows the current task to suspend. That doesn’t just let the task wait for future work to complete. It also is an opportunity to change isolation. This makes async functions very flexible!&lt;/p&gt;
        &lt;p&gt;Just like a dispatcher doesn’t sit there doing nothing while waiting for the ambulance to arrive, a suspended task doesn’t block its thread. When the dispatcher puts you on hold to coordinate with the ambulance team, that’s the isolation switch - they’re transferring your request to a different department that specializes in that type of work.&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;but-change-to-where-exactly&quot; href=&quot;#but-change-to-where-exactly&quot;&gt;&lt;/a&gt;But change to where, exactly?&lt;/h2&gt;
        &lt;p&gt;Ok, so we know that async functions, because they must always be &lt;code&gt;await&lt;/code&gt;ed, gain a lot of flexibility. We are close, but have to go just a little further to find the motivation for this attribute.&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;dispatch&lt;wbr&gt;&lt;/wbr&gt;Responder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;responder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;responder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dispatch&lt;wbr&gt;&lt;/wbr&gt;Responder&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// no explicit isolation =&amp;gt; nonisolated&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;🚒 HONK HOOOOONK!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;air&lt;wbr&gt;&lt;/wbr&gt;Support&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;🚁 SOI SOI SOI SOI SOI!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dispatch&lt;wbr&gt;&lt;/wbr&gt;Responder&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;@Main&lt;wbr&gt;&lt;/wbr&gt;Actor&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;🚑 WEE-OOO WEE-OOO!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;We now have a function that accepts &lt;strong&gt;other&lt;/strong&gt; functions as arguments. It’s possible to pass in lots of different kinds of functions to &lt;code&gt;dispatch&lt;wbr&gt;&lt;/wbr&gt;Responder&lt;/code&gt;. They could be async functions themselves, or even be synchronous. And they can be isolated to any actor. All thanks to the power of &lt;code&gt;await&lt;/code&gt;.&lt;/p&gt;
        &lt;p&gt;Except there’s a little problem now.
        Have a look at &lt;code&gt;dispatch&lt;wbr&gt;&lt;/wbr&gt;Responder&lt;/code&gt; on its own:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;dispatch&lt;wbr&gt;&lt;/wbr&gt;Responder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;responder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;responder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;The type of &lt;code&gt;responder&lt;/code&gt; fully describes everything about this function,
        &lt;strong&gt;except&lt;/strong&gt; for one thing.
        We have no way to know its isolation.
        That information is only available at callsites.
        The isolation is still present,
        so the right thing happens at runtime.
        It’s just not possible to inspect it statically or even programmatically.
        If you’ve encountered type erasure before,
        this should seem familiar.
        The flexibility of &lt;code&gt;async&lt;/code&gt; has come with a price -
        a loss of information.&lt;/p&gt;
        &lt;p&gt;This is where &lt;code&gt;@isolated(any)&lt;/code&gt; comes in.&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;using-isolatedany&quot; href=&quot;#using-isolatedany&quot;&gt;&lt;/a&gt;Using &lt;code&gt;@isolated(any)&lt;/code&gt;
        &lt;/h2&gt;
        &lt;p&gt;We can change the definition of &lt;code&gt;dispatch&lt;wbr&gt;&lt;/wbr&gt;Responder&lt;/code&gt; to fix this.&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;dispatch&lt;wbr&gt;&lt;/wbr&gt;Responder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;responder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;@isolated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;responder isolation:&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;responder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isolation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;responder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;When you apply &lt;code&gt;@isolated(any)&lt;/code&gt; to a function type, it does two things. Most importantly, it gives you access to a special &lt;code&gt;isolation&lt;/code&gt; property. You can use this property to inspect the isolation of the function. The isolation could be an actor. Or it could be non-isolated. This is expressible in the type system with &lt;code&gt;(any Actor)?&lt;/code&gt;.&lt;/p&gt;
        &lt;p&gt;Functions with properties felt really strange to me at first.
        But, after thinking for a minute,
        it became quite natural.
        Why not?
        It’s just a type like any other.
        In fact, we can simulate how this all works with another feature:
        &lt;a href=&quot;/callable&quot;&gt;&lt;code&gt;call&lt;wbr&gt;&lt;/wbr&gt;As&lt;wbr&gt;&lt;/wbr&gt;Function&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Isolated&lt;wbr&gt;&lt;/wbr&gt;Any&lt;wbr&gt;&lt;/wbr&gt;Function&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;isolation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Actor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)?&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;call&lt;wbr&gt;&lt;/wbr&gt;As&lt;wbr&gt;&lt;/wbr&gt;Function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Isolated&lt;wbr&gt;&lt;/wbr&gt;Any&lt;wbr&gt;&lt;/wbr&gt;Function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;isolation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Main&lt;wbr&gt;&lt;/wbr&gt;Actor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// isolated work goes here&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;This analogy is certainly not &lt;strong&gt;perfect&lt;/strong&gt;,
        but it’s close enough that it might help.&lt;/p&gt;
        &lt;p&gt;There is one other subtle change that &lt;code&gt;@isolated(any)&lt;/code&gt; makes to a function
        that you should be aware of.
        Its whole purpose is to capture the isolation of a function.
        Since that could be anything,
        callsites need an opportunity to switch.
        And that means an &lt;code&gt;@isolated(any)&lt;/code&gt; function must be called with an &lt;code&gt;await&lt;/code&gt; —
        even if it isn’t itself explicitly async.&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;dispatch&lt;wbr&gt;&lt;/wbr&gt;Responder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;responder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;@isolated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;responder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// note the function is synchronous&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;This makes synchronous functions marked with &lt;code&gt;@isolated(any)&lt;/code&gt; a little strange.
        They still must be called with &lt;code&gt;await&lt;/code&gt;,
        yet they aren’t allowed to suspend internally?&lt;/p&gt;
        &lt;p&gt;As it turns out, there are some valid (if rare) situations
        where such an arrangement can make sense.
        But adding this kind of constraint to your API
        should at least merit some extra documentation.&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;how-isolatedany-affects-callers&quot; href=&quot;#how-isolatedany-affects-callers&quot;&gt;&lt;/a&gt;How @isolated(any) Affects Callers&lt;/h2&gt;
        &lt;p&gt;All of the task creation APIs —
        &lt;code&gt;Task&lt;/code&gt; initializers and &lt;code&gt;Task&lt;wbr&gt;&lt;/wbr&gt;Group&lt;/code&gt; —
        make use of &lt;code&gt;@isolated(any)&lt;/code&gt;.
        These are used a lot
        and are usually encountered very early on when learning about concurrency.
        So, it’s completely natural to run into this attribute and think:&lt;/p&gt;
        &lt;p&gt;&lt;em&gt;“Ugh another thing to understand!”&lt;/em&gt;&lt;/p&gt;
        &lt;p&gt;It’s reasonable because
        the components of a function type dictate how it can be used.
        They are all essential qualities for API consumers.
        They &lt;em&gt;&lt;strong&gt;are&lt;/strong&gt;&lt;/em&gt; the interface.&lt;/p&gt;
        &lt;ul&gt;
        &lt;li&gt;Parameters&lt;/li&gt;
        &lt;li&gt;Return value&lt;/li&gt;
        &lt;li&gt;Does it throw?&lt;/li&gt;
        &lt;li&gt;Is it async?&lt;/li&gt;
        &lt;/ul&gt;
        &lt;p&gt;This is not an exhaustive list,
        but what’s important is all of these are things callers must care about.
        Except for &lt;code&gt;@isolated(any)&lt;/code&gt;, which is the &lt;strong&gt;opposite&lt;/strong&gt;.
        It doesn’t affect callers at all.&lt;/p&gt;
        &lt;p&gt;This, I think, is the root of a lot of confusion around &lt;code&gt;@isolated(any)&lt;/code&gt;.
        Unlike other qualities of a function,
        this attribute is used to capture information for the API producer.&lt;/p&gt;
        &lt;p&gt;I’m so close to saying &lt;em&gt;“you can and should just ignore &lt;code&gt;@isolated(any)&lt;/code&gt;“&lt;/em&gt;.
        But I just cannot quite go that far,
        because there is one situation you should be aware of.&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;scheduling&quot; href=&quot;#scheduling&quot;&gt;&lt;/a&gt;Scheduling&lt;/h2&gt;
        &lt;p&gt;To help understand when you should be thinking about using &lt;code&gt;@isolated(any)&lt;/code&gt;,
        I’m going to quote
        &lt;a href=&quot;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0431-isolated-any-functions.md&quot;&gt;the proposal&lt;/a&gt;:&lt;/p&gt;
        &lt;blockquote&gt;
        &lt;p&gt;This allows the API to make more &lt;strong&gt;intelligent scheduling&lt;/strong&gt; decisions about the function.&lt;/p&gt;
        &lt;/blockquote&gt;
        &lt;p&gt;I’ve highlighted “intelligent scheduling”,
        because this is the key component of &lt;code&gt;@isolated(any)&lt;/code&gt;.
        The attribute gives you access to the isolation of a function argument.
        But what would you use that for?&lt;/p&gt;
        &lt;p&gt;Did you know that, before Swift 6.0, the ordering of the following code was undefined?&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;@Main&lt;wbr&gt;&lt;/wbr&gt;Actor&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;three&lt;wbr&gt;&lt;/wbr&gt;Alarm&lt;wbr&gt;&lt;/wbr&gt;Fire&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;🚒 Truck A reporting!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;🚒 Truck B checking in!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;🚒 Truck C on the case!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;Ordering turns out to be a very tricky topic when working with unstructured tasks.
        And while it will always require care, Swift 6.0 did improve the situation.
        We now have some stronger guarantees about scheduling work on the &lt;code&gt;Main&lt;wbr&gt;&lt;/wbr&gt;Actor&lt;/code&gt;,
        and &lt;code&gt;@isolated(any)&lt;/code&gt; was needed to make that possible.&lt;/p&gt;
        &lt;aside class=&quot;admonition warning&quot;&gt;
        &lt;p&gt;Anytime you use &lt;code&gt;Task&lt;/code&gt;,
        think about &lt;em&gt;when&lt;/em&gt; that work will start and &lt;em&gt;how&lt;/em&gt; that could matter.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;Take a look at this:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;@Main&lt;wbr&gt;&lt;/wbr&gt;Actor&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;send&lt;wbr&gt;&lt;/wbr&gt;Ambulance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;🚑 WEE-OOO WEE-OOO!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;nonisolated&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;dispatch&lt;wbr&gt;&lt;/wbr&gt;Responders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// synchronously enqueued&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;@Main&lt;wbr&gt;&lt;/wbr&gt;Actor&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;send&lt;wbr&gt;&lt;/wbr&gt;Ambulance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// synchronously enqueued&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;operation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;send&lt;wbr&gt;&lt;/wbr&gt;Ambulance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// not synchronously enqueued!&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;send&lt;wbr&gt;&lt;/wbr&gt;Ambulance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;These are three ways to achieve the same goal.
        But, there is a subtle difference in how the last form is scheduled.
        &lt;code&gt;Task&lt;/code&gt; takes an &lt;code&gt;@isolated(any)&lt;/code&gt; function
        so it can look at its isolation
        and &lt;strong&gt;synchronously submit it to an actor&lt;/strong&gt;.
        This is how ordering can be preserved!
        But, it cannot do that in the last case.
        That closure passed into &lt;code&gt;Task&lt;/code&gt; isn’t actually itself &lt;code&gt;Main&lt;wbr&gt;&lt;/wbr&gt;Actor&lt;/code&gt; —
        it has inherited nonisolated from the enclosing function.&lt;/p&gt;
        &lt;p&gt;I think it might help to translate this into
        &lt;abbr title=&quot;Grand Central Dispatch&quot;&gt;GCD&lt;/abbr&gt;.&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;dispatch&lt;wbr&gt;&lt;/wbr&gt;Responders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// synchronously enqueued&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;Dispatch&lt;wbr&gt;&lt;/wbr&gt;Queue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;send&lt;wbr&gt;&lt;/wbr&gt;Ambulance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// synchronously enqueued&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;Dispatch&lt;wbr&gt;&lt;/wbr&gt;Queue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;async&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;send&lt;wbr&gt;&lt;/wbr&gt;Ambulance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// not synchronously enqueued!&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;Dispatch&lt;wbr&gt;&lt;/wbr&gt;Queue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;global&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;Dispatch&lt;wbr&gt;&lt;/wbr&gt;Queue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;send&lt;wbr&gt;&lt;/wbr&gt;Ambulance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;Look really closely at that last one!
        What we are doing there is introducing a new async closure
        that then calls our &lt;code&gt;Main&lt;wbr&gt;&lt;/wbr&gt;Actor&lt;/code&gt; function.
        There are &lt;strong&gt;two&lt;/strong&gt; steps.
        This doesn’t always matter,
        but it certainly could.
        And if you need to precisely schedule asynchronous work,
        &lt;code&gt;@isolated(any)&lt;/code&gt; can help.&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;isolatedall&quot; href=&quot;#isolatedall&quot;&gt;&lt;/a&gt;isolated(all)&lt;/h2&gt;
        &lt;p&gt;All this talk about &lt;code&gt;@isolated(any)&lt;/code&gt; got me thinking…&lt;/p&gt;
        &lt;p&gt;It’s kinda strange that only &lt;em&gt;some&lt;/em&gt; functions get to have this &lt;code&gt;isolation&lt;/code&gt; property.
        It would certainly feel more consistent to me if &lt;em&gt;all&lt;/em&gt; functions had it.
        In fact, I think we can go further.
        I can imagine a future where an explicit &lt;code&gt;@isolated(any)&lt;/code&gt;
        isn’t even necessary for async functions.
        As far as I can tell, there is no downside.&lt;/p&gt;
        &lt;p&gt;And a little less syntactic noise would be nice.
        Perhaps one day!&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;isolatedsome&quot; href=&quot;#isolatedsome&quot;&gt;&lt;/a&gt;isolated(some)&lt;/h2&gt;
        &lt;p&gt;We do have to talk about that &lt;code&gt;any&lt;/code&gt;.
        It’s surprising that this attribute requires an argument,
        yet permits only one possible value.
        The reason here comes down to future considerations.&lt;/p&gt;
        &lt;p&gt;The &lt;strong&gt;concrete&lt;/strong&gt; actor type that this &lt;code&gt;isolation&lt;/code&gt; property returns
        is always &lt;code&gt;(any Actor)?&lt;/code&gt;.
        This is the most generic type for isolation and matches the &lt;code&gt;#isolation&lt;/code&gt; macro.
        Today, there is no way to constrain a function to only &lt;strong&gt;specific&lt;/strong&gt; actor types,
        such as &lt;code&gt;@isolated(My&lt;wbr&gt;&lt;/wbr&gt;Actor)&lt;/code&gt;.
        The &lt;code&gt;any&lt;/code&gt; keyword here was chosen to mirror how protocols handle this.
        But accepting an argument leaves the door open
        to more sophisticated features in the future.&lt;/p&gt;
        &lt;p&gt;And that really fits the spirit of &lt;code&gt;@isolated(any)&lt;/code&gt;.
        Doing a little work now in exchange for flexibility down the road.&lt;/p&gt;
        &lt;p&gt;Because you’ll see it in many foundational concurrency APIs,
        it’s very natural to feel like you must understand &lt;code&gt;@isolated(any)&lt;/code&gt;.
        I’m 100% behind technical curiosity!
        In this case, however, it is not required.
        For the most part, you can just ignore this attribute.
        You will rarely, if ever, need to use it yourself.&lt;/p&gt;
        &lt;p&gt;But if you ever find yourself capturing isolated functions
        and passing them along to &lt;strong&gt;other&lt;/strong&gt; APIs that use &lt;code&gt;@isolated(any)&lt;/code&gt;,
        you should consider adopting it.
        It could prove useful.
        It’s even a source-compatible change
        to add or remove this attribute from an async function.&lt;/p&gt;
        &lt;hr&gt;
        &lt;p&gt;So there you have it.&lt;/p&gt;
        &lt;p&gt;As with many parts of the concurrency system,
        there’s a surprising depth to &lt;code&gt;@isolated(any)&lt;/code&gt;.
        Thankfully, from a practical perspective,
        we can enjoy the ordering guarantees of task creation
        that it enables without needing to master it.
        And one less thing on this journey is most welcome.&lt;/p&gt;
        &lt;p&gt;Isolated maybe, but never alone.&lt;/p&gt;
      </content>
      <author>
        <name>Matt Massicotte</name>
        <uri>https://nshipster.com/authors/matt-massicotte/</uri>
      </author>
      <category term="Swift" />
      <summary type="html">&lt;p&gt;There are cases where just a little more visibility and control over how to schedule asynchronous work can make all the difference.&lt;/p&gt;</summary>
    </entry>
    <entry>
      <title type="html">Uncertain⟨T⟩</title>
      <link href="https://nshipster.com/uncertainty/" rel="alternate" type="text/html" title="Uncertain⟨T⟩" />
      <published>2025-07-25T00:00:00-07:00</published>
      <updated>2025-07-25T00:00:00-07:00</updated>
      <id>https://nshipster.com/uncertainty</id>
      <content type="html" xml:base="https://nshipster.com/uncertainty/">
        &lt;p&gt;You know what’s wrong with people?
        They’re too sure of themselves.&lt;/p&gt;
        &lt;p&gt;Better to be wrong and own it than be right with caveats.
        Hard to build a personal brand out of nuance these days.
        People are attracted to confidence — however misplaced.&lt;/p&gt;
        &lt;p&gt;But can you blame them? (People, that is)
        Working in software,
        the most annoying part of reaching Senior level
        is having to say &lt;em&gt;“it depends”&lt;/em&gt; all the time.
        Much more fun getting to say
        &lt;em&gt;“let’s ship it and iterate”&lt;/em&gt; as Staff or
        &lt;em&gt;“that won’t scale”&lt;/em&gt; as a Principal.&lt;/p&gt;
        &lt;p&gt;Yet, for all of our intellectual humility,
        why do we &lt;del&gt;write&lt;/del&gt; vibe code like this?&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current&lt;wbr&gt;&lt;/wbr&gt;Location&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;distance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;You've arrived!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// But have you, really? 🤨&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;GPS coordinates aren’t exact.
        They’re noisy. They’re approximate. They’re probabilistic.
        That &lt;code&gt;horizontal&lt;wbr&gt;&lt;/wbr&gt;Accuracy&lt;/code&gt; property tucked away in your &lt;code&gt;CLLocation&lt;/code&gt; object
        is trying to tell you something important:
        you’re &lt;em&gt;probably&lt;/em&gt; within that radius.
        &lt;em&gt;Probably.&lt;/em&gt;&lt;/p&gt;
        &lt;p&gt;A &lt;code&gt;Bool&lt;/code&gt;, meanwhile, can be only &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;.
        That &lt;code&gt;if&lt;/code&gt; statement needs to make a choice one way or another,
        but code like this doesn’t capture the uncertainty of the situation.
        If truth is light,
        then current programming models collapse the wavefunction too early.&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;picking-the-right-abstraction&quot; href=&quot;#picking-the-right-abstraction&quot;&gt;&lt;/a&gt;Picking the Right Abstraction&lt;/h2&gt;
        &lt;p&gt;In 2014, researchers at the University of Washington and Microsoft Research
        proposed a radical idea:
        What if uncertainty were encoded directly into the type system?
        Their paper,
        &lt;em&gt;&lt;a href=&quot;https://www.microsoft.com/en-us/research/publication/uncertaint-a-first-order-type-for-uncertain-data-2/&quot;&gt;Uncertain&amp;lt;T&amp;gt;: A First-Order Type for Uncertain Data&lt;/a&gt;&lt;/em&gt;
        introduced a probabilistic programming approach that’s both
        mathematically rigorous and surprisingly practical.&lt;/p&gt;
        &lt;aside class=&quot;parenthetical&quot;&gt;
        &lt;p&gt;I found a copy of this paper while cleaning out my &lt;code&gt;~/Downloads&lt;/code&gt; folder over the weekend.
        I remember seeing it right around when Swift was announced,
        thinking it would be perfect for testing the new language’s generics.
        But I never got around to it, until now 🥲&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;As you’d expect for something from Microsoft in the 2010s,
        the paper is implemented in C#.
        But the concepts translate beautifully to Swift.&lt;/p&gt;
        &lt;p&gt;You can find &lt;a href=&quot;https://github.com/mattt/Uncertain&quot;&gt;my port on GitHub&lt;/a&gt;:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Uncertain&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Core&lt;wbr&gt;&lt;/wbr&gt;Location&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;uncertain&lt;wbr&gt;&lt;/wbr&gt;Location&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Uncertain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;CLLocation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current&lt;wbr&gt;&lt;/wbr&gt;Location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nearby&lt;wbr&gt;&lt;/wbr&gt;Evidence&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uncertain&lt;wbr&gt;&lt;/wbr&gt;Location&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;distance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nearby&lt;wbr&gt;&lt;/wbr&gt;Evidence&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;probability&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;exceeds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.95&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;You've arrived!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// With 2σ confidence 🤓&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;When you compare two &lt;code&gt;Uncertain&lt;/code&gt; values,
        you don’t get a definitive &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;.
        You get an &lt;code&gt;Uncertain&amp;lt;Bool&amp;gt;&lt;/code&gt; that represents the &lt;em&gt;probability&lt;/em&gt; of the comparison being &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
        &lt;aside class=&quot;admonition info&quot;&gt;
        &lt;p&gt;Under the hood, &lt;code&gt;Uncertain&amp;lt;T&amp;gt;&lt;/code&gt; models GPS uncertainty using a
        &lt;a href=&quot;https://en.wikipedia.org/wiki/Rayleigh_distribution&quot;&gt;Rayleigh distribution&lt;/a&gt;.
        GPS errors are typically circular around the true position,
        with error magnitude following this distribution.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;The same is true for other operators, too:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// How fast did we run around the track?&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;distance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Double&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;400&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// meters&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Uncertain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;normal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;standard&lt;wbr&gt;&lt;/wbr&gt;Deviation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;5.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// seconds&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;running&lt;wbr&gt;&lt;/wbr&gt;Speed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;distance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Uncertain&amp;lt;Double&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// How much air resistance?&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;air&lt;wbr&gt;&lt;/wbr&gt;Density&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Uncertain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;normal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.225&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;standard&lt;wbr&gt;&lt;/wbr&gt;Deviation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// kg/m³&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;drag&lt;wbr&gt;&lt;/wbr&gt;Coefficient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Uncertain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;kumaraswamy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;beta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// slightly right-skewed distribution&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;frontal&lt;wbr&gt;&lt;/wbr&gt;Area&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Uncertain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;normal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.45&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;standard&lt;wbr&gt;&lt;/wbr&gt;Deviation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.05&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// m²&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;air&lt;wbr&gt;&lt;/wbr&gt;Resistance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;air&lt;wbr&gt;&lt;/wbr&gt;Density&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frontal&lt;wbr&gt;&lt;/wbr&gt;Area&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drag&lt;wbr&gt;&lt;/wbr&gt;Coefficient&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;running&lt;wbr&gt;&lt;/wbr&gt;Speed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;running&lt;wbr&gt;&lt;/wbr&gt;Speed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;This code builds a computation graph,
        sampling only when you ask for concrete results.
        The library uses
        &lt;a href=&quot;https://en.wikipedia.org/wiki/Sequential_probability_ratio_test&quot;&gt;Sequential Probability Ratio Testing (SPRT)&lt;/a&gt;
        to efficiently determine how many samples are needed —
        maybe a few dozen times for simple comparisons,
        scaling up automatically for complex calculations.&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Sampling happens only when we need to evaluate&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;running&lt;wbr&gt;&lt;/wbr&gt;Speed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;6.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Great pace for a 400m sprint!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// SPRT might only need a dozen samples for this simple comparison&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;sustainable&lt;wbr&gt;&lt;/wbr&gt;For5K&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;running&lt;wbr&gt;&lt;/wbr&gt;Speed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;6.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;air&lt;wbr&gt;&lt;/wbr&gt;Resistance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;50.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Can sustain for 5K: &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sustainable&lt;wbr&gt;&lt;/wbr&gt;For5K&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;probability&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;exceeds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Might use 100+ samples for this compound condition&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;Using an abstraction like &lt;code&gt;Uncertain&amp;lt;T&amp;gt;&lt;/code&gt; forces you to deal with uncertainty as a first-class concept
        rather than pretending it doesn’t exist.
        And in doing so, you end up with much smarter code.&lt;/p&gt;
        &lt;p&gt;To quote &lt;a href=&quot;https://en.wikipedia.org/wiki/Alan_Kay&quot;&gt;Alan Kay&lt;/a&gt;:&lt;/p&gt;
        &lt;blockquote&gt;
        &lt;p&gt;Point of view is worth 80 IQ points
        &lt;cite hidden=&quot;&quot;&gt;Alan Kay&lt;/cite&gt;&lt;/p&gt;
        &lt;/blockquote&gt;
        &lt;hr&gt;&lt;a id=&quot;get-on-with-it&quot;&gt;&lt;/a&gt;
        &lt;p&gt;Before we dive deeper into probability distributions,
        let’s take a detour to Monaco and talk about
        &lt;a href=&quot;https://en.wikipedia.org/wiki/Monte_Carlo_method&quot;&gt;Monte Carlo sampling&lt;/a&gt;.&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;the-monte-carlo-method&quot; href=&quot;#the-monte-carlo-method&quot;&gt;&lt;/a&gt;The Monte Carlo Method&lt;/h2&gt;
        &lt;p&gt;Behold, a classic slot machine (or “fruit machine” for our UK readers 🇬🇧):&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Slot&lt;wbr&gt;&lt;/wbr&gt;Machine&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;symbols&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;◻️&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;◻️&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;◻️&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// blanks&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;🍒&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;🍋&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;🍊&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;🍇&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;💎&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Spin three reels independently&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;reel1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;symbols&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;random&lt;wbr&gt;&lt;/wbr&gt;Element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;reel2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;symbols&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;random&lt;wbr&gt;&lt;/wbr&gt;Element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;reel3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;symbols&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;random&lt;wbr&gt;&lt;/wbr&gt;Element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reel1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reel2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reel3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;💎&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;💎&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;💎&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// Jackpot!&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;🍒&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;🍒&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;🍒&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;🍇&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;🍇&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;🍇&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;🍊&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;🍊&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;🍊&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;🍋&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;🍋&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;🍋&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;🍒&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Any cherry&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;🍒&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;🍒&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// Better luck next time&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;Should we play it?&lt;/p&gt;
        &lt;aside class=&quot;parenthetical&quot;&gt;
        &lt;p&gt;Are you feeling lucky?&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;Now, we &lt;em&gt;could&lt;/em&gt; work out these probabilities analytically —
        counting combinations,
        calculating conditional probabilities,
        maybe even busting out some combinatorics.&lt;/p&gt;
        &lt;p&gt;Or we could just let the computer pull the lever a bunch and see what happens.&lt;/p&gt;
        &lt;aside class=&quot;parenthetical&quot;&gt;
        &lt;p&gt;Are you feeling… lazy?&lt;/p&gt;
        &lt;/aside&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;expected&lt;wbr&gt;&lt;/wbr&gt;Payout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Uncertain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;Slot&lt;wbr&gt;&lt;/wbr&gt;Machine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;expected&lt;wbr&gt;&lt;/wbr&gt;Value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;sample&lt;wbr&gt;&lt;/wbr&gt;Count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10_000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Expected value per spin: $&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expected&lt;wbr&gt;&lt;/wbr&gt;Payout&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Expected value per spin: ≈ $0.56&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;At least we know one thing for certain:
        &lt;em&gt;The house always wins.&lt;/em&gt;&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;beyond-simple-distributions&quot; href=&quot;#beyond-simple-distributions&quot;&gt;&lt;/a&gt;Beyond Simple Distributions&lt;/h2&gt;
        &lt;p&gt;While one-armed bandits demonstrate pure randomness,
        real-world applications often deal with more predictable uncertainty.&lt;/p&gt;
        &lt;p&gt;&lt;code&gt;Uncertain&amp;lt;T&amp;gt;&lt;/code&gt; provides a
        &lt;a href=&quot;https://github.com/mattt/Uncertain?tab=readme-ov-file#distribution-constructors&quot;&gt;rich set of probability distributions&lt;/a&gt;:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Modeling sensor noise&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;raw&lt;wbr&gt;&lt;/wbr&gt;Gyro&lt;wbr&gt;&lt;/wbr&gt;Data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.85&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// rad/s&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;gyro&lt;wbr&gt;&lt;/wbr&gt;Reading&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Uncertain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;normal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;raw&lt;wbr&gt;&lt;/wbr&gt;Gyro&lt;wbr&gt;&lt;/wbr&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;standard&lt;wbr&gt;&lt;/wbr&gt;Deviation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.05&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// Typical gyroscope noise in rad/s&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// User behavior modeling&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;user&lt;wbr&gt;&lt;/wbr&gt;Will&lt;wbr&gt;&lt;/wbr&gt;Tap&lt;wbr&gt;&lt;/wbr&gt;Button&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Uncertain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bernoulli&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;probability&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Network latency with long tail&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;api&lt;wbr&gt;&lt;/wbr&gt;Response&lt;wbr&gt;&lt;/wbr&gt;Time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Uncertain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;exponential&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Coffee shop visit times (bimodal: morning rush + afternoon break)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;morning&lt;wbr&gt;&lt;/wbr&gt;Rush&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Uncertain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;normal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;8.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;standard&lt;wbr&gt;&lt;/wbr&gt;Deviation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// 8:30 AM&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;afternoon&lt;wbr&gt;&lt;/wbr&gt;Break&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Uncertain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;normal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;15.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;standard&lt;wbr&gt;&lt;/wbr&gt;Deviation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// 3:00 PM&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;visit&lt;wbr&gt;&lt;/wbr&gt;Time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Uncertain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mixture&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;morning&lt;wbr&gt;&lt;/wbr&gt;Rush&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;afternoon&lt;wbr&gt;&lt;/wbr&gt;Break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;weights&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// Slightly prefer morning coffee&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;aside class=&quot;admonition info&quot;&gt;
        &lt;p&gt;I wanted to develop an intuitive sense of how these probability distributions work,
        so I built &lt;a href=&quot;https://github.com/mattt/Uncertain-Distribution-Visualizer/&quot;&gt;this companion project&lt;/a&gt;
        with interactive visualizations for each one.
        It also serves as a nifty showcase for
        &lt;a href=&quot;https://developer.apple.com/documentation/charts&quot;&gt;Swift Charts&lt;/a&gt;.
        So definitely check that out if you’re uninitiated.&lt;/p&gt;
        &lt;picture id=&quot;visualization-screenshot&quot;&gt;
        &lt;source srcset=&quot;/assets/uncertainty-screenshot--dark-de54ef5af4d17ba5e73758c17ace82f727811fb90bbd32a49397b9a391b724c80460adbf713075b3d96bca31eade7be6509fb345c204382f9a31716d4b2b54af.png&quot; media=&quot;(prefers-color-scheme: dark)&quot;&gt;
        &lt;img src=&quot;/assets/uncertainty-screenshot--light-f8b9978efc20936028f4a011e7706349b09339ee889c91d589f398017e96e5cd4dde514eeed20c3454f97b89a88c81e63792412eb8c16d38039ef093a1c9efff.png&quot; alt=&quot;iMCP&quot; onclick=&quot;window.location.href='https://iMCP.app';&quot;&gt;
        &lt;/source&gt;&lt;/picture&gt;
        &lt;/aside&gt;
        &lt;p&gt;&lt;code&gt;Uncertain&amp;lt;T&amp;gt;&lt;/code&gt; also provides comprehensive
        &lt;a href=&quot;https://github.com/mattt/Uncertain?tab=readme-ov-file#statistical-operations&quot;&gt;statistical operations&lt;/a&gt;:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Basic statistics&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;temperature&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Uncertain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;normal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;23.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;standard&lt;wbr&gt;&lt;/wbr&gt;Deviation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;avg&lt;wbr&gt;&lt;/wbr&gt;Temp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;temperature&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;expected&lt;wbr&gt;&lt;/wbr&gt;Value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// about 23°C&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;temp&lt;wbr&gt;&lt;/wbr&gt;Spread&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;temperature&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;standard&lt;wbr&gt;&lt;/wbr&gt;Deviation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// about 1°C&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Confidence intervals&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;upper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;temperature&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;confidence&lt;wbr&gt;&lt;/wbr&gt;Interval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.95&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;95% of temperatures between &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;°C and &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upper&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;°C&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Distribution shape analysis&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;network&lt;wbr&gt;&lt;/wbr&gt;Delay&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Uncertain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;exponential&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;skew&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;network&lt;wbr&gt;&lt;/wbr&gt;Delay&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;skewness&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// right skew&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;kurt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;network&lt;wbr&gt;&lt;/wbr&gt;Delay&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;kurtosis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// heavy tail&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Working with discrete distributions&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dice&lt;wbr&gt;&lt;/wbr&gt;Roll&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Uncertain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;categorical&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;dice&lt;wbr&gt;&lt;/wbr&gt;Roll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;entropy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// Randomness measure (~2.57)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dice&lt;wbr&gt;&lt;/wbr&gt;Roll&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dice&lt;wbr&gt;&lt;/wbr&gt;Roll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Most frequent outcome (7, perhaps?)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Cumulative probability&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;temperature&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cdf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;25.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// P(temp ≤ 25°C) &amp;lt; 20%&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Unlikely to be 25°C or cooler&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;The statistics are computed through sampling.
        The number of samples is configurable, letting you trade computation time for accuracy.&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;putting-theory-to-practice&quot; href=&quot;#putting-theory-to-practice&quot;&gt;&lt;/a&gt;Putting Theory to Practice&lt;/h2&gt;
        &lt;p&gt;Users don’t notice when things work correctly,
        but they definitely notice impossible behavior.
        When your running app claims they just sprinted at 45 mph,
        or your IRL meetup app shows someone 500 feet away when GPS accuracy is ±1000 meters,
        that’s a bad look 🤡&lt;/p&gt;
        &lt;p&gt;So where do we go from here?
        Let’s channel our Senior+ memes from before for guidance.&lt;/p&gt;
        &lt;p&gt;That Staff engineer saying &lt;em&gt;“let’s ship it and iterate”&lt;/em&gt;
        is right about the incremental approach.
        You can migrate uncertain calculations piecemeal
        rather than rewriting everything at once:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CLLocation&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;uncertain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Uncertain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;CLLocation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;Uncertain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;CLLocation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Gradually migrate critical paths&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;is&lt;wbr&gt;&lt;/wbr&gt;Nearby&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;current&lt;wbr&gt;&lt;/wbr&gt;Location&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uncertain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;distance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destination&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;threshold&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;probability&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;exceeds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.68&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;And we should consider the Principal engineer’s warning of &lt;em&gt;“that won’t scale”&lt;/em&gt;.
        Sampling has a cost, and you should understand the
        computational overhead for probabilistic accuracy:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Fast approximation for UI updates&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;quick&lt;wbr&gt;&lt;/wbr&gt;Estimate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;speed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;probability&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;exceeds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;walking&lt;wbr&gt;&lt;/wbr&gt;Speed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;max&lt;wbr&gt;&lt;/wbr&gt;Samples&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// High precision for critical decisions&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;precise&lt;wbr&gt;&lt;/wbr&gt;Result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;speed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;probability&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;exceeds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;walking&lt;wbr&gt;&lt;/wbr&gt;Speed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;confidence&lt;wbr&gt;&lt;/wbr&gt;Level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.99&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;max&lt;wbr&gt;&lt;/wbr&gt;Samples&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10_000&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;aside class=&quot;admonition warning&quot;&gt;
        &lt;p&gt;&lt;abbr title=&quot;On the other hand 💁‍♀️&quot;&gt;OTOH&lt;/abbr&gt;,
        modern devices are pretty amazing.&lt;/p&gt;
        &lt;p&gt;Remember kids, &lt;code&gt;Instruments.app&lt;/code&gt; is your friend.
        Use profiling to guide your optimizations.&lt;/p&gt;
        &lt;p&gt;Senior 🤝 Staff 🤝 Principal&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;Start small.
        Pick one feature where GPS glitches cause user complaints.
        Replace your distance calculations with uncertain versions.
        Measure the impact.&lt;/p&gt;
        &lt;p&gt;Remember:
        the goal isn’t to eliminate uncertainty —
        it’s to acknowledge that it exists and handle it gracefully.
        Because in the real world,
        nothing is certain except uncertainty itself.&lt;/p&gt;
        &lt;p&gt;And perhaps,
        with better tools,
        we can finally stop pretending otherwise.&lt;/p&gt;
      </content>
      <author>
        <name>Mattt</name>
        <email>mattt@nshipster.com</email>
        <uri>https://nshipster.com/authors/mattt/</uri>
      </author>
      <category term="Miscellaneous" />
      <summary type="html">&lt;p&gt;GPS coordinates aren’t exact. Sensor readings have noise. User behavior is probabilistic. Yet we write code that pretends uncertainty doesn’t exist, forcing messy real-world data through clean Boolean logic.&lt;/p&gt;</summary>
    </entry>
    <entry>
      <title type="html">Model Context Protocol (MCP)</title>
      <link href="https://nshipster.com/model-context-protocol/" rel="alternate" type="text/html" title="Model Context Protocol (MCP)" />
      <published>2025-03-07T00:00:00-08:00</published>
      <updated>2025-03-07T00:00:00-08:00</updated>
      <id>https://nshipster.com/model-context-protocol</id>
      <content type="html" xml:base="https://nshipster.com/model-context-protocol/">
        &lt;p&gt;Language Server Protocol (LSP)
        revolutionized how programming languages integrate with developer tools.
        Model Context Protocol (MCP)
        aims to do the same for a new generation of AI tools.&lt;/p&gt;
        &lt;p&gt;But before we lay our scene of two protocols (both alike in dignity),
        let’s take a moment to motivate the problem a bit more.&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;tool-use-agents&quot; href=&quot;#tool-use-agents&quot;&gt;&lt;/a&gt;Tool Use &amp;amp; Agents&lt;/h2&gt;
        &lt;p&gt;Today’s frontier models are extraordinary. 
        But they’re limited in two key ways:&lt;/p&gt;
        &lt;ol&gt;
        &lt;li&gt;They don’t know anything outside their training data&lt;/li&gt;
        &lt;li&gt;They can’t do anything outside of predicting the next token&lt;/li&gt;
        &lt;/ol&gt;
        &lt;p&gt;To their credit, LLMs &lt;em&gt;(kinda, sorta)&lt;/em&gt; understand these limitations, 
        and have been trained to ask for what they need. 
        We (humans) have settled on a practice called &lt;dfn&gt;tool use&lt;/dfn&gt; 
        that lets AI do just that.&lt;/p&gt;
        &lt;p&gt;Here’s an example:&lt;/p&gt;
        &lt;!-- 
        - When a user sends a message, 
        they may include a list of tools made available to the model.
        - When the AI assistant responds, 
        it may ask to call one or more of those tools.
        - The client asks the user to approve or deny this to request.
        - If approved, the client execute the tool, 
        and returns the result in a follow up message to the model.
        - The AI assistant generates a response based on this information. 
        --&gt;
        &lt;dl&gt;
        &lt;dt class=&quot;user&quot;&gt;User&lt;/dt&gt;
        &lt;dd class=&quot;user&quot;&gt;Write a limerick about today's weather in Portland, Oregon.&lt;/dd&gt;
        &lt;dt class=&quot;client&quot;&gt;Client, to Assistant →&lt;/dt&gt;
        &lt;dd class=&quot;client&quot;&gt;
        Also, there's this &quot;Get Weather&quot; tool available if you need it.
        It takes a set of coordinates and returns the current temperature and conditions.
        &lt;/dd&gt;
        &lt;dt class=&quot;assistant&quot;&gt;Assistant&lt;/dt&gt;
        &lt;dd class=&quot;assistant&quot;&gt;
        &lt;code&gt;&amp;lt;thinking&amp;gt;&lt;/code&gt;
        &lt;em&gt;To write an accurate poem, I should get the weather.
        From my training, &lt;wbr&gt;&lt;/wbr&gt;I know Portland's coordinates to be 
        45.5155° N, 122.6789° W&lt;/em&gt;
        &lt;code&gt;&amp;lt;/thinking&amp;gt;&lt;/code&gt;
        &lt;/dd&gt;
        &lt;dd class=&quot;assistant&quot;&gt;
        Tool call:
        &lt;code&gt;{tool: &quot;Get Weather&quot;, latitude: 45.5155, longitude: -122.6789}&lt;/code&gt;
        &lt;/dd&gt;
        &lt;dt class=&quot;client&quot;&gt;← Client, to User&lt;/dt&gt;
        &lt;dd class=&quot;client&quot;&gt;Is it alright to make that tool call?&lt;/dd&gt;
        &lt;dt class=&quot;user&quot;&gt;User&lt;/dt&gt;
        &lt;dd class=&quot;user&quot;&gt;&lt;span class=&quot;big&quot;&gt;👍&lt;/span&gt;&lt;/dd&gt;
        &lt;dt class=&quot;client&quot;&gt;Client, to Assistant →&lt;/dt&gt;
        &lt;dd class=&quot;client&quot;&gt;
        Tool result:
        &lt;code&gt;{temperature: 12, conditions: 'cloudy', humidity: 85%}&lt;/code&gt;
        &lt;/dd&gt;
        &lt;dt class=&quot;assistant&quot;&gt;Assistant&lt;/dt&gt;
        &lt;dd class=&quot;assistant&quot;&gt;Here's your limerick about Portland's weather:&lt;/dd&gt;
        &lt;dd&gt;
        &lt;blockquote&gt;
        There once was a city called Portland &lt;br&gt;
        Where clouds made the skies quite importland &lt;br&gt;
        At twelve degrees C &lt;br&gt;
        It's as gray as can be &lt;br&gt;
        With a dampness that's truly absorbland! &lt;br&gt;
        &lt;/blockquote&gt;
        &lt;/dd&gt;
        &lt;/dl&gt;
        &lt;p&gt;Pretty clever, right? &lt;br&gt;
        But then again, &lt;em&gt;so what?&lt;/em&gt;&lt;/p&gt;
        &lt;p&gt;On its face, this is a very slow, expensive way to do something 
        better-served by a quick Google search — 
        or sticking your head out a window, for that matter.&lt;/p&gt;
        &lt;p&gt;But here’s the thing: &lt;br&gt;
        &lt;strong&gt;Tool use gives rise to agency&lt;/strong&gt;
        &lt;span aria-label=&quot;emergence&quot; role=&quot;text&quot;&gt;
        (✨𝓮𝓶𝓮𝓻𝓰𝓮𝓷𝓬𝓮✨)
        &lt;/span&gt;&lt;/p&gt;
        &lt;p&gt;As the saying goes, 
        &lt;q&gt;Quantity has a quality all its own&lt;/q&gt;.
        Give a language model a dozen… a hundred… a thousand tools —
        hell, give it &lt;em&gt;a tool for making more tools&lt;/em&gt;.
        How confident are you that you could find a problem 
        that couldn’t be solved by such a system?&lt;/p&gt;
        &lt;p&gt;We’re only just starting to see what’s possible.&lt;/p&gt;
        &lt;hr&gt;&lt;a id=&quot;get-on-with-it&quot;&gt;&lt;/a&gt;
        &lt;p&gt;But back to more practical matters: &lt;br&gt;
        Let’s talk about where we are today with Model Context Protocol.&lt;/p&gt;
        &lt;hr&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;the-new-m-n-problem&quot; href=&quot;#the-new-m-n-problem&quot;&gt;&lt;/a&gt;The New M × N Problem&lt;/h2&gt;
        &lt;p&gt;We’ve &lt;a href=&quot;https://nshipster.com/language-server-protocol&quot;&gt;written previously&lt;/a&gt; 
        about Language Server Protocol, 
        and the &lt;dfn&gt;M × N problem&lt;/dfn&gt;.
        LSP’s challenge was connecting &lt;code&gt;M&lt;/code&gt; editors with &lt;code&gt;N&lt;/code&gt; programming languages
        MCP faces a similar challenge, of connecting &lt;code&gt;M&lt;/code&gt; clients with &lt;code&gt;N&lt;/code&gt; resources.
        Without MCP, 
        each AI application must implement custom integrations 
        for every data source it wants to access.&lt;/p&gt;
        &lt;!-- ![Diagram of M x N grid](...) --&gt;
        &lt;p&gt;This creates the same kind of fragmented ecosystem that plagued development tools before LSP:&lt;/p&gt;
        &lt;ul&gt;
        &lt;li&gt;Some AI applications offer deep integration with specific data sources but limited support for others&lt;/li&gt;
        &lt;li&gt;Different applications implement similar integrations in incompatible ways&lt;/li&gt;
        &lt;li&gt;Improvements to one integration rarely benefit the broader ecosystem&lt;/li&gt;
        &lt;/ul&gt;
        &lt;p&gt;Like LSP, 
        MCP transforms this M × N problem into an &lt;dfn&gt;M + N&lt;/dfn&gt; problem through standardization.
        Rather than each AI application implementing custom integrations, 
        it only needs to support the MCP standard. 
        In doing so, 
        it gains access to all MCP-compatible data sources and tools 🌈&lt;/p&gt;
        &lt;!-- ![Diagram of M + N](...) --&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;how-model-context-protocol-works&quot; href=&quot;#how-model-context-protocol-works&quot;&gt;&lt;/a&gt;How Model Context Protocol Works&lt;/h2&gt;
        &lt;p&gt;MCP follows a client-server architecture similar to LSP:&lt;/p&gt;
        &lt;ul&gt;
        &lt;li&gt;The &lt;em&gt;client&lt;/em&gt; is typically an AI application or development environment &lt;br&gt;
        For example, 
        &lt;a href=&quot;https://claude.ai/download&quot;&gt;Claude Desktop&lt;/a&gt;,
        &lt;a href=&quot;https://zed.dev&quot;&gt;Zed&lt;/a&gt;, and 
        &lt;a href=&quot;https://www.cursor.com&quot;&gt;Cursor&lt;/a&gt;.&lt;/li&gt;
        &lt;li&gt;The &lt;em&gt;server&lt;/em&gt; is a program that provides access to data and/or tools&lt;/li&gt;
        &lt;/ul&gt;
        &lt;p&gt;Requests and responses are encoded according to the
        &lt;a href=&quot;https://www.jsonrpc.org/&quot;&gt;JSON-RPC&lt;/a&gt; 2.0 specification.
        Communication between client and server happens over 
        Stdio (&lt;code&gt;stdin&lt;/code&gt;/&lt;code&gt;stdout&lt;/code&gt;) or HTTP with Server-Sent Events 
        &lt;a href=&quot;https://modelcontextprotocol.io/docs/concepts/architecture#transport-layer&quot;&gt;transports&lt;/a&gt;.&lt;/p&gt;
        &lt;p&gt;Like LSP, MCP has clients and servers negotiate a set of capabilities.
        When a client connects to a server, it sends an 
        &lt;a href=&quot;https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/lifecycle/#initialization&quot;&gt;&lt;code&gt;initialize&lt;/code&gt; message&lt;/a&gt;,
        with information about what protocol version it supports.
        The server responds in kind.&lt;/p&gt;
        &lt;p&gt;From there, the client can ask the server about what features it has.
        MCP describes three different kinds of features that a server can provide:&lt;/p&gt;
        &lt;ul&gt;
        &lt;li&gt;
        &lt;strong&gt;Prompts&lt;/strong&gt;: 
        Templates that shape how language models respond. 
        They’re the difference between getting generic text and precise, useful results. 
        A good prompt is like a well-designed API - 
        it defines the contract between you and the model.&lt;/li&gt;
        &lt;li&gt;
        &lt;strong&gt;Resources&lt;/strong&gt;:
        Reference materials that ground models in reality. 
        By providing structured data alongside your query, 
        you transform a model from a creative writer into 
        an informed assistant with domain-specific knowledge.
        &lt;em&gt;(Think: databases, file systems, documents)&lt;/em&gt;
        &lt;/li&gt;
        &lt;li&gt;
        &lt;strong&gt;Tools&lt;/strong&gt;: 
        Functions that extend what models can do. 
        They allow AI to calculate, retrieve information, 
        or interact with external systems when simple text generation isn’t enough. 
        Tools bridge the gap between language understanding and practical capability.&lt;/li&gt;
        &lt;/ul&gt;
        &lt;aside class=&quot;admonition info&quot;&gt;
        &lt;p&gt;The distinction between these is admittedly fuzzy.
        After all, all they ultimately do is fill a context window with tokens.
        You could, for example, implement everything as a tool.&lt;/p&gt;
        &lt;aside class=&quot;parenthetical&quot;&gt;
        &lt;p&gt;In practice, that’s what clients tend to support best&lt;/p&gt;
        &lt;/aside&gt;
        &lt;/aside&gt;
        &lt;p&gt;Our previous example handwaved the existence of a “Get Weather” tool.
        MCP gives our client a standard way to consult various connected services.&lt;/p&gt;
        &lt;p&gt;To get a list of available tools on an MCP, 
        the client would send a &lt;code&gt;tools/list&lt;/code&gt; request to the server:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;JSON&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;jsonrpc&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;2.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; 
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; 
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;method&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;tools/list&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; 
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;params&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;In our example, the server would respond:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;JSON&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;jsonrpc&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;2.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;result&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;tools&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;get_weather&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Returns current weather conditions for the specified coordinates.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;input&lt;wbr&gt;&lt;/wbr&gt;Schema&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; 
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;latitude&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;number&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;longitude&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;number&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;required&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;latitude&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;longitude&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;The client can share this list of tools with the language model
        in a system prompt or a user message.
        When the model responds wanting to invoke the &lt;code&gt;get_weather&lt;/code&gt; tool,
        the client asks the user to confirm tool use.
        If the human-in-the-loop says 🆗,
        the client sends a &lt;code&gt;tools/call&lt;/code&gt; request:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;JSON&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;jsonrpc&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;2.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; 
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;method&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;tools/call&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; 
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;params&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; 
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;get_weather&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;arguments&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;latitude&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;45.5155&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;longitude&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;-122.6789&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;In response, the server sends:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;JSON&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;jsonrpc&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;2.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;{&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;temperature&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;: 12, &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;conditions&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;cloudy&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;humidity&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;: 85}&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;annotations&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;audience&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;assistant&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;The client then passes that result to the AI assistant,
        the assistant generates a response with this information,
        and the client passes that along to the user.&lt;/p&gt;
        &lt;hr&gt;
        &lt;p&gt;That’s pretty much all there is to it.
        There are plenty of details to get bogged down with.
        But that’s what LLMs are for.
        Now is the time for vibes coding. &lt;br&gt;
        MCP is &lt;a href=&quot;https://www.itsnicethat.com/features/toby-mott-oh-so-pretty-punk-in-print-phaidon-111016&quot;&gt;punk rock&lt;/a&gt;.&lt;/p&gt;
        &lt;p&gt;&lt;img integrity=&quot;sha512-q3ZRMGpNQ40rPFLnWCFnsRsBzYArG5R7Ru9D/cowteCNms6HLzzsAZjW9/NQ7NPgO5L14/lPcvUSJij8+zakqA==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/model-context-protocol-now-form-a-band-ab7651306a4d438d2b3c52e7582167b11b01cd802b1b947b46ef43fdca30b5e08d9ace872f3cec0198d6f7f350ecd3e03b92f5e3f94f72f5122628fcfb36a4a8.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;how-do-i-start&quot; href=&quot;#how-do-i-start&quot;&gt;&lt;/a&gt;How do I start?&lt;/h2&gt;
        &lt;p&gt;MCP is an emerging standard from Anthropic.
        So it’s no surprise that &lt;a href=&quot;https://claude.ai/download&quot;&gt;Claude Desktop&lt;/a&gt;
        is most capable of showing off what it can do.&lt;/p&gt;
        &lt;p&gt;Once you have Claude Desktop installed,
        you can peruse the 
        &lt;a href=&quot;https://modelcontextprotocol.io/examples&quot;&gt;myriad example servers&lt;/a&gt; available.&lt;/p&gt;
        &lt;p&gt;Or, if you want to skip straight to la &lt;em lang=&quot;fr&quot;&gt;crème de la crème&lt;/em&gt;,
        then have a taste of what we’ve been cooking up with MCP lately:&lt;/p&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;imcp&quot; href=&quot;#imcp&quot;&gt;&lt;/a&gt;iMCP&lt;/h3&gt;
        &lt;p&gt;Fun fact! The word &lt;em&gt;“paradise”&lt;/em&gt; derives from an old word for &lt;em&gt;“walled garden”&lt;/em&gt;.&lt;/p&gt;
        &lt;aside class=&quot;parenthetical&quot;&gt;
        &lt;p&gt;The English word “paradise” comes from Old French “paradis”, 
        which derives from Latin “paradisus”, 
        which was borrowed from Greek &lt;span title=&quot;paradeisos&quot;&gt;“παράδεισος”&lt;/span&gt;, 
        which itself was adopted from Old Persian &lt;span title=&quot;paridaida&quot;&gt;“𐎱𐎼𐎭𐎹𐎭𐎠𐎶”&lt;/span&gt;&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;Ironic how Apple has a way of making your digital life a living hell sometimes.&lt;/p&gt;
        &lt;p&gt;For many of us who exist in Apple’s walled garden, 
        we’re often frustrated by the product design and software quality 
        that gets between us and our data.
        Spotlight search is stuck in the ‘00s. 
        Apple Intelligence &lt;a href=&quot;https://nshipster.com/ollama&quot;&gt;didn’t live up to the hype&lt;/a&gt;. 
        Siri seems doomed to suck forever.&lt;/p&gt;
        &lt;p&gt;That was our motivation for building &lt;a href=&quot;https://iMCP.app&quot;&gt;iMCP&lt;/a&gt;.&lt;/p&gt;
        &lt;picture id=&quot;imcp-logo&quot;&gt;
        &lt;source srcset=&quot;/assets/model-context-protocol-imcp--dark-7e00f8dcaa9ec34104bee046dd5855fb364c966784e4da9b7b5d3459faa787f6dccb219a698e636b4f71feaf3a22dc5138a2e7d9703e49693b3abebf6e89f7d4.svg&quot; media=&quot;(prefers-color-scheme: dark)&quot;&gt;
        &lt;img src=&quot;/assets/model-context-protocol-imcp--light-31ea0f8a3163944f2c9b9a6fa91a32b92e87cf7eaa60a10ea12387f5862983f9fff00ba4001014b373edefc4596936c463f26998d10b59c8baeef83e939c8b03.svg&quot; alt=&quot;iMCP&quot; onclick=&quot;window.location.href='https://iMCP.app';&quot; role=&quot;img&quot;&gt;
        &lt;/source&gt;&lt;/picture&gt;
        &lt;p&gt;iMCP is a macOS app for connecting your digital life with AI. 
        It works with Claude Desktop and a growing list of clients that support MCP.
        It gives MCP access to your calendars, contacts, even messages —
        &lt;a href=&quot;https://github.com/loopwork-ai/iMCP?tab=readme-ov-file#imessage-database-access&quot;&gt;no small feat&lt;/a&gt;!&lt;/p&gt;
        &lt;p&gt;&lt;a href=&quot;https://iMCP.app/download&quot;&gt;Download it today&lt;/a&gt;
        and get a taste of some &lt;em&gt;real&lt;/em&gt; Apple intelligence.&lt;/p&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;mcp-swift-sdk&quot; href=&quot;#mcp-swift-sdk&quot;&gt;&lt;/a&gt;mcp-swift-sdk&lt;/h3&gt;
        &lt;p&gt;In the process of building iMCP,
        we built a &lt;a href=&quot;https://github.com/loopwork-ai/mcp-swift-sdk&quot;&gt;Swift SDK&lt;/a&gt;
        for Model Context Protocol servers and clients.&lt;/p&gt;
        &lt;p&gt;If you’re inspired to build your own MCP app
        and like working in Swift more than Python or TypeScript,
        definitely give this a try!&lt;/p&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;hype&quot; href=&quot;#hype&quot;&gt;&lt;/a&gt;hype&lt;/h3&gt;
        &lt;p&gt;If, however, you have accepted Python into your heart as I have,
        then I’d recommend checking out another project I’ve been working on:
        &lt;a href=&quot;https://github.com/loopwork-ai/hype&quot;&gt;hype&lt;/a&gt;.&lt;/p&gt;
        &lt;p&gt;My goal with hype is to eliminate every barrier between writing Python code
        and calling it in a way that’s useful.
        Add the &lt;code&gt;@hype.up&lt;/code&gt; decorator to a function
        to instantly generate an HTTP API, a CLI, a GUI, or an MCP.&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Python&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# example.py
        &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;hype&lt;/span&gt;
        &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pydantic&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;up&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;divide&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
        Divides one number by another.
        :param x: The numerator
        :param y: The denominator
        :return: The quotient
        &quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;Start up an MCP server with the &lt;code&gt;hype&lt;/code&gt; command:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;hype mcp example.py
        &lt;/code&gt;&lt;/pre&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;emcee&quot; href=&quot;#emcee&quot;&gt;&lt;/a&gt;emcee&lt;/h3&gt;
        &lt;p&gt;But really, the best code is code you don’t have to write.
        If you already have a web application with an
        &lt;a href=&quot;https://www.openapis.org&quot;&gt;OpenAPI specification&lt;/a&gt;,
        you can use another tool we built —
        &lt;a href=&quot;https://emcee.sh&quot;&gt;emcee&lt;/a&gt; —
        to instantly spin up an MCP server to it.&lt;/p&gt;
        &lt;p&gt;&lt;img src=&quot;/assets/model-context-protocol-emcee-871c814a97243a12f890b8db83094b8311ec299d2cc85e5c32ef831313b42785dab37c681b695579f0e420d483dcfeba3751ea49178f7eca6c0d70ef6a42a381.png&quot; alt=&quot;emcee&quot; onclick=&quot;window.location.href='https://emcee.sh';&quot;&gt;&lt;/p&gt;
        &lt;p&gt;We think emcee is a convenient way to connect to services 
        that don’t have an existing MCP server implementation — 
        &lt;em&gt;especially for services you’re building yourself&lt;/em&gt;. 
        Got a web app with an OpenAPI spec? 
        You might be surprised how far you can get without a dashboard or client library.&lt;/p&gt;
        &lt;hr&gt;
        &lt;p&gt;In case it’s not abundantly clear,
        we here at NSHipster dot com are pretty bought into the promise of
        Model Context Protocol.
        And we’re excited to see where everything goes in the coming months.&lt;/p&gt;
        &lt;p&gt;If you’re building in this space, 
        I’d love to &lt;a href=&quot;mailto:mattt@nshipster.com&quot;&gt;hear from you&lt;/a&gt;
        ✌️&lt;/p&gt;
        &lt;style rel=&quot;stylesheet&quot; type=&quot;text/css&quot; integrity=&quot;sha512-eWhOOIp+YeMoAgmnMNNa1m7IaZgpGk5gKtoz3ANKzKMQMpv5Iyy9lFxHYaKZw2tl2tODn1J4onQupcS5JMThHQ==&quot; crossorigin=&quot;anonymous&quot;&gt;ol{list-style-type:decimal !important}@media (min-width: 768px){dl{margin-left:auto;margin-right:auto;width:85%}dt,dd{padding-left:2rem;padding-right:2rem}}dl{border:1px solid #b7b7b7;padding:1rem;margin-top:0.25rem;margin-bottom:3rem;font-size:0.8rem}dl dt,dl dd{padding-left:1rem;padding-right:1rem}dl dd{margin-left:0}dl dt{padding-top:1rem;margin-bottom:0.125rem}dl dt:first-of-type{padding-top:0}.user{text-align:left}.client{text-align:center}.assistant{text-align:right}.assistant blockquote{text-align:right !important;border-left:0}[role=&quot;article&quot;] .content dl blockquote{text-align:right !important;border-left:0 !important;margin:0;font-style:italic}span.big{font-size:2rem;padding-top:0.5rem;display:inline-block}picture img[src$=&quot;.svg&quot;]{filter:none !important}#imcp-logo{max-width:480px;display:block;margin:0 auto;cursor:pointer}#emcee-logo{max-width:480px;display:block;margin:0 auto;cursor:pointer}
        /*# sourceMappingURL=/assets/source-maps/articles/model-context-protocol.scss.map */
        /*# sourceURL=assets/css/articles/model-context-protocol.scss */
        &lt;/style&gt;
      </content>
      <author>
        <name>Mattt</name>
        <email>mattt@nshipster.com</email>
        <uri>https://nshipster.com/authors/mattt/</uri>
      </author>
      <category term="Miscellaneous" />
      <summary type="html">&lt;p&gt;Language Server Protocol (LSP) revolutionized how programming languages integrate with developer tools. Model Context Protocol (MCP) aims to do the same for a new generation of AI tools.&lt;/p&gt;</summary>
    </entry>
    <entry>
      <title type="html">Ollama</title>
      <link href="https://nshipster.com/ollama/" rel="alternate" type="text/html" title="Ollama" />
      <published>2025-02-14T00:00:00-08:00</published>
      <updated>2025-02-14T00:00:00-08:00</updated>
      <id>https://nshipster.com/ollama</id>
      <content type="html" xml:base="https://nshipster.com/ollama/">
        &lt;blockquote&gt;
        &lt;p&gt;“Only Apple can do this” 
        &lt;cite&gt;Variously attributed to Tim Cook&lt;/cite&gt;&lt;/p&gt;
        &lt;/blockquote&gt;
        &lt;p&gt;Apple introduced &lt;a href=&quot;https://www.apple.com/apple-intelligence/&quot;&gt;Apple Intelligence&lt;/a&gt; at WWDC 2024.
        After waiting almost a year for Apple to, 
        in Craig Federighi’s words, &lt;em&gt;“get it right”&lt;/em&gt;, 
        its promise of “AI for the rest of us” feels just as distant as ever.&lt;/p&gt;
        &lt;aside class=&quot;parenthetical&quot;&gt;
        &lt;p&gt;Can we take a moment to appreciate the name?
        &lt;strong&gt;A&lt;/strong&gt;pple &lt;strong&gt;I&lt;/strong&gt;ntelligence. 
        AI.
        That’s some S-tier semantic appropriation.
        On the level of jumping on “podcast” before anyone knew what else to call that.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;While we wait for Apple Intelligence to arrive on our devices,
        something remarkable is already running on our Macs.
        Think of it as a locavore approach to artificial intelligence:
        homegrown, sustainable, and available year-round.&lt;/p&gt;
        &lt;p&gt;This week on NSHipster,
        we’ll look at how you can use Ollama to run 
        &lt;abbr title=&quot;large language models&quot;&gt;LLMs&lt;/abbr&gt; locally on your Mac —
        both as an end-user and as a developer.&lt;/p&gt;
        &lt;hr&gt;&lt;a id=&quot;get-on-with-it&quot;&gt;&lt;/a&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;what-is-ollama&quot; href=&quot;#what-is-ollama&quot;&gt;&lt;/a&gt;What is Ollama?&lt;/h2&gt;
        &lt;p&gt;Ollama is the easiest way to run large language models on your Mac. 
        You can think of it as “Docker for LLMs” - 
        a way to pull, run, and manage AI models as easily as containers.&lt;/p&gt;
        &lt;p&gt;Download Ollama with &lt;a href=&quot;https://brew.sh/&quot;&gt;Homebrew&lt;/a&gt; 
        or directly from &lt;a href=&quot;https://ollama.com/download&quot;&gt;their website&lt;/a&gt;.
        Then pull and run &lt;a href=&quot;https://ollama.com/library/llama3.2&quot;&gt;llama3.2&lt;/a&gt; (2GB).&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Terminal&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--cask&lt;/span&gt; ollama
        &lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;ollama run llama3.2
        &lt;span class=&quot;gp&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; Tell me a joke about Swift programming.
        &lt;span class=&quot;go&quot;&gt;What's a Apple developer's favorite drink? 
        The Kool-Aid.
        &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;Under the hood, 
        Ollama is powered by &lt;a href=&quot;https://github.com/ggerganov/llama.cpp&quot;&gt;llama.cpp&lt;/a&gt;.
        But where llama.cpp provides the engine,
        Ollama gives you a vehicle you’d actually want to drive —
        handling all the complexity of model management, optimization, and inference.&lt;/p&gt;
        &lt;p&gt;Similar to how Dockerfiles define container images, 
        Ollama uses &lt;dfn&gt;Modelfiles&lt;/dfn&gt; to configure model behavior:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;dockerfile&quot;&gt;&lt;code&gt;
        &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; mistral:latest&lt;/span&gt;
        PARAMETER temperature 0.7
        TEMPLATE &quot;&quot;&quot;
        {{- if .First }}
        You are a helpful assistant.
        {{- end }}
        &lt;span class=&quot;k&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;: {{.Prompt}}&lt;/span&gt;
        Assistant: &quot;&quot;&quot;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;Ollama uses the &lt;a href=&quot;https://opencontainers.org&quot;&gt;Open Container Initiative (OCI)&lt;/a&gt;
        standard to distribute models. 
        Each model is split into layers and described by a manifest,
        the same approach used by Docker containers:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;JSON&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;media&lt;wbr&gt;&lt;/wbr&gt;Type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;application/vnd.oci.image.manifest.v1+json&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;config&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;media&lt;wbr&gt;&lt;/wbr&gt;Type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;application/vnd.ollama.image.config.v1+json&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;digest&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;sha256:...&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;layers&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;media&lt;wbr&gt;&lt;/wbr&gt;Type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;application/vnd.ollama.image.layer.v1+json&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;digest&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;sha256:...&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;size&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4019248935&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;Overall, Ollama’s approach is thoughtful and well-engineered.
        And best of all, &lt;em&gt;it just works&lt;/em&gt;.&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;whats-the-big-deal-about-running-models-locally&quot; href=&quot;#whats-the-big-deal-about-running-models-locally&quot;&gt;&lt;/a&gt;What’s the big deal about running models locally?&lt;/h2&gt;
        &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Jevons_paradox&quot;&gt;Jevons paradox&lt;/a&gt; states that, 
        as something becomes more efficient, we tend to use &lt;em&gt;more&lt;/em&gt; of it, not less.&lt;/p&gt;
        &lt;p&gt;Having AI on your own device changes everything.
        When computation becomes essentially free,
        you start to see intelligence differently.&lt;/p&gt;
        &lt;p&gt;While frontier models like GPT-4 and Claude are undeniably miraculous, 
        there’s something to be said for the small miracle of running open models locally.&lt;/p&gt;
        &lt;ul&gt;
        &lt;li&gt;
        &lt;strong&gt;Privacy&lt;/strong&gt;: 
        Your data never leaves your device. 
        Essential for working with sensitive information.&lt;/li&gt;
        &lt;li&gt;
        &lt;strong&gt;Cost&lt;/strong&gt;: 
        Run 24/7 without usage meters ticking. 
        No more rationing prompts like ’90s cell phone minutes.
        Just a fixed, up-front cost for unlimited inference.&lt;/li&gt;
        &lt;li&gt;
        &lt;strong&gt;Latency&lt;/strong&gt;: 
        No network round-trips means faster responses. 
        Your &lt;code&gt;/M\d Mac((Book( Pro| Air)?)|Mini|Studio)/&lt;/code&gt; can easily generate dozens of tokens per second. 
        (Try to keep up!)&lt;/li&gt;
        &lt;li&gt;
        &lt;strong&gt;Control&lt;/strong&gt;: 
        No black-box &lt;a href=&quot;https://knowyourmeme.com/photos/2546581-shoggoth-with-smiley-face-artificial-intelligence&quot;&gt;&lt;abbr title=&quot;Reinforcement Learning from Human Feedback&quot;&gt;RLHF&lt;/abbr&gt;&lt;/a&gt; or censorship. 
        The AI works for you, not the other way around.&lt;/li&gt;
        &lt;li&gt;
        &lt;strong&gt;Reliability&lt;/strong&gt;: 
        No outages or API quota limits.
        100% uptime for your &lt;a href=&quot;https://en.wiktionary.org/wiki/exocortex&quot;&gt;exocortex&lt;/a&gt;.
        Like having Wikipedia on a thumb drive.&lt;/li&gt;
        &lt;/ul&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;building-macos-apps-with-ollama&quot; href=&quot;#building-macos-apps-with-ollama&quot;&gt;&lt;/a&gt;Building macOS Apps with Ollama&lt;/h2&gt;
        &lt;p&gt;Ollama also exposes an &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/api.md&quot;&gt;HTTP API&lt;/a&gt; on port 11434
        (&lt;a href=&quot;https://en.wikipedia.org/wiki/Leet&quot;&gt;leetspeak&lt;/a&gt; for llama 🦙).
        This makes it easy to integrate with any programming language or tool.&lt;/p&gt;
        &lt;p&gt;To that end, we’ve created the &lt;a href=&quot;https://github.com/mattt/ollama-swift&quot;&gt;Ollama Swift package&lt;/a&gt;
        to help developers integrate Ollama into their apps.&lt;/p&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;text-completions&quot; href=&quot;#text-completions&quot;&gt;&lt;/a&gt;Text Completions&lt;/h3&gt;
        &lt;p&gt;The simplest way to use a language model is to generate text from a prompt:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Ollama&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;generate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;llama3.2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;prompt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Tell me a joke about Swift programming.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;temperature&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// How many Apple engineers does it take to document an API? &lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// None - that's what WWDC videos are for.&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;chat-completions&quot; href=&quot;#chat-completions&quot;&gt;&lt;/a&gt;Chat Completions&lt;/h3&gt;
        &lt;p&gt;For more structured interactions, 
        you can use the chat API to maintain a conversation with multiple messages and different roles:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;initial&lt;wbr&gt;&lt;/wbr&gt;Response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;llama3.2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;You are a helpful assistant.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;What city is Apple located in?&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;initial&lt;wbr&gt;&lt;/wbr&gt;Response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Apple's headquarters, known as the Apple Park campus, is located in Cupertino, California.&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// The company was originally founded in Los Altos, California, and later moved to Cupertino in 1997.&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;follow&lt;wbr&gt;&lt;/wbr&gt;Up&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;llama3.2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;You are a helpful assistant.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;What city is Apple located in?&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;assistant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;initial&lt;wbr&gt;&lt;/wbr&gt;Response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Please summarize in a single word&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;follow&lt;wbr&gt;&lt;/wbr&gt;Up&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Cupertino&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;generating-text-embeddings&quot; href=&quot;#generating-text-embeddings&quot;&gt;&lt;/a&gt;Generating text embeddings&lt;/h3&gt;
        &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Word_embedding&quot;&gt;Embeddings&lt;/a&gt; 
        convert text into high-dimensional vectors that capture semantic meaning. 
        These vectors can be used to find similar content or perform semantic search.&lt;/p&gt;
        &lt;p&gt;For example, if you wanted to find documents similar to a user’s query:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;documents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;&lt;var class=&quot;placeholder&quot;&gt;…&lt;/var&gt;&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Convert text into vectors we can compare for similarity&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;embeddings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;embeddings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;nomic-embed-text&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
        &lt;span class=&quot;nv&quot;&gt;texts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;documents&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;/// Finds relevant documents&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;find&lt;wbr&gt;&lt;/wbr&gt;Relevant&lt;wbr&gt;&lt;/wbr&gt;Documents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
        &lt;span class=&quot;nv&quot;&gt;threshold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Float&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// cutoff for matching, tunable&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Get embedding for the query&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query&lt;wbr&gt;&lt;/wbr&gt;Embedding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;embeddings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;llama3.2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;texts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// See: https://en.wikipedia.org/wiki/Cosine_similarity&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;cosine&lt;wbr&gt;&lt;/wbr&gt;Similarity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Float&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dot&lt;wbr&gt;&lt;/wbr&gt;Product&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;magnitude&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sqrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dot&lt;wbr&gt;&lt;/wbr&gt;Product&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;magnitude&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;magnitude&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Find documents above similarity threshold&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ranked&lt;wbr&gt;&lt;/wbr&gt;Documents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;embeddings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;documents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;embedding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;document&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;in&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;similarity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;cosine&lt;wbr&gt;&lt;/wbr&gt;Similarity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;embedding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;query&lt;wbr&gt;&lt;/wbr&gt;Embedding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;similarity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;threshold&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sorted&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;similarity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;similarity&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;prefix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ranked&lt;wbr&gt;&lt;/wbr&gt;Documents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(\&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;aside class=&quot;admonition info&quot;&gt;
        &lt;p&gt;For simple use cases, 
        you can also use Apple’s 
        &lt;a href=&quot;https://developer.apple.com/documentation/naturallanguage/&quot;&gt;Natural Language framework&lt;/a&gt;
        for text embeddings.
        They’re fast and don’t require additional dependencies.&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Natural&lt;wbr&gt;&lt;/wbr&gt;Language&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;embedding&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NLEmbedding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;word&lt;wbr&gt;&lt;/wbr&gt;Embedding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;english&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;vector&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;embedding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;vector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;swift&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;/aside&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;building-a-rag-system&quot; href=&quot;#building-a-rag-system&quot;&gt;&lt;/a&gt;Building a RAG System&lt;/h3&gt;
        &lt;p&gt;Embeddings really shine when combined with text generation in a 
        &lt;abbr title=&quot;Retrieval Augmented Generation&quot;&gt;RAG&lt;/abbr&gt; (Retrieval Augmented Generation) workflow. 
        Instead of asking the model to generate information from its training data, 
        we can ground its responses in our own documents by:&lt;/p&gt;
        &lt;ol&gt;
        &lt;li&gt;Converting documents into embeddings&lt;/li&gt;
        &lt;li&gt;Finding relevant documents based on the query&lt;/li&gt;
        &lt;li&gt;Using those documents as context for generation&lt;/li&gt;
        &lt;/ol&gt;
        &lt;p&gt;Here’s a simple example:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;query&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;What were AAPL's earnings in Q3 2024?&quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;relevant&lt;wbr&gt;&lt;/wbr&gt;Docs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;find&lt;wbr&gt;&lt;/wbr&gt;Relevant&lt;wbr&gt;&lt;/wbr&gt;Documents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;context&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
        Use the following documents to answer the question. 
        If the answer isn't contained in the documents, say so.
        Documents:
        &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;relevant&lt;wbr&gt;&lt;/wbr&gt;Docs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;joined&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;separator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
        Question: &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
        &quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;generate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;llama3.2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;prompt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;hr&gt;
        &lt;p&gt;To summarize:
        Different models have different capabilities.&lt;/p&gt;
        &lt;ul&gt;
        &lt;li&gt;Models like &lt;a href=&quot;https://ollama.com/library/llama3.2&quot;&gt;llama3.2&lt;/a&gt; 
        and &lt;a href=&quot;https://ollama.com/library/deepseek-r1&quot;&gt;deepseek-r1&lt;/a&gt; 
        generate text.
        &lt;ul&gt;
        &lt;li&gt;Some text models have “base” or “instruct” variants,
        suitable for fine-tuning or chat completion, respectively.&lt;/li&gt;
        &lt;li&gt;Some text models are tuned to support &lt;a href=&quot;https://ollama.com/blog/tool-support&quot;&gt;tool use&lt;/a&gt;,
        which let them perform more complex tasks and interact with the outside world.&lt;/li&gt;
        &lt;/ul&gt;
        &lt;/li&gt;
        &lt;li&gt;
        &lt;p&gt;Models like &lt;a href=&quot;https://ollama.com/library/llama3.2-vision&quot;&gt;llama3.2-vision&lt;/a&gt;
        can take images along with text as inputs.&lt;/p&gt;
        &lt;/li&gt;
        &lt;li&gt;Models like &lt;a href=&quot;https://ollama.com/library/nomic-embed-text&quot;&gt;nomic-embed-text&lt;/a&gt;
        create numerical vectors that capture semantic meaning.&lt;/li&gt;
        &lt;/ul&gt;
        &lt;p&gt;With Ollama, 
        you get unlimited access to a wealth of these and many more open-source language models.&lt;/p&gt;
        &lt;hr&gt;
        &lt;p&gt;So, what can you build with all of this?&lt;br&gt;
        Here’s just one example:&lt;/p&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;nominateapp&quot; href=&quot;#nominateapp&quot;&gt;&lt;/a&gt;Nominate.app&lt;/h3&gt;
        &lt;p&gt;&lt;a href=&quot;https://github.com/nshipster/nominate&quot;&gt;Nominate&lt;/a&gt; 
        is a macOS app that uses Ollama to intelligently rename PDF files based on their contents.&lt;/p&gt;
        &lt;p&gt;Like many of us striving for a paperless lifestyle,
        you might find yourself scanning documents only to end up with 
        cryptically-named PDFs like &lt;code&gt;Scan2025-02-03_123456.pdf&lt;/code&gt;.
        Nominate solves this by combining AI with traditional NLP techniques
        to automatically generate descriptive filenames based on document contents.&lt;/p&gt;
        &lt;video width=&quot;831&quot; autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot; playsinline=&quot;&quot;&gt;
        &lt;source src=&quot;/assets/ollama-nominate-screen-recording-9dede9f6805d5cc71680a0fd7fb970edc0eb576b5b8fb8a2233dcf7e55c7ccf9f7c59b5fe749685249e6a541cab70cb460d31e42b531e81f5ecfb020fc045390.mov&quot; type=&quot;video/mp4&quot;&gt;&lt;/source&gt;
        &lt;/video&gt;
        &lt;p&gt;&lt;br&gt;&lt;/p&gt;
        &lt;p&gt;The app leverages several technologies we’ve discussed:&lt;/p&gt;
        &lt;ul&gt;
        &lt;li&gt;Ollama’s API for content analysis via the &lt;code&gt;ollama-swift&lt;/code&gt; package&lt;/li&gt;
        &lt;li&gt;Apple’s PDFKit for OCR&lt;/li&gt;
        &lt;li&gt;The Natural Language framework for text processing&lt;/li&gt;
        &lt;li&gt;Foundation’s &lt;code&gt;Date&lt;wbr&gt;&lt;/wbr&gt;Formatter&lt;/code&gt; for parsing dates&lt;/li&gt;
        &lt;/ul&gt;
        &lt;aside class=&quot;admonition info&quot;&gt;
        &lt;p&gt;Nominate performs all processing locally. Your documents never leave your computer. This is a key advantage of running models locally versus using cloud APIs.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;looking-ahead&quot; href=&quot;#looking-ahead&quot;&gt;&lt;/a&gt;Looking Ahead&lt;/h2&gt;
        &lt;blockquote&gt;
        &lt;p&gt;“The future is already here – it’s just not evenly distributed yet.”
        &lt;cite&gt;William Gibson&lt;/cite&gt;&lt;/p&gt;
        &lt;/blockquote&gt;
        &lt;p&gt;Think about the timelines:&lt;/p&gt;
        &lt;ul&gt;
        &lt;li&gt;Apple Intelligence was announced last year.&lt;/li&gt;
        &lt;li&gt;Swift came out 10 years ago.&lt;/li&gt;
        &lt;li&gt;SwiftUI 6 years ago.&lt;/li&gt;
        &lt;/ul&gt;
        &lt;p&gt;If you wait for Apple to deliver on its promises, 
        &lt;strong&gt;you’re going to miss out on the most important technological shift in a generation&lt;/strong&gt;.&lt;/p&gt;
        &lt;p&gt;The future is here today.
        You don’t have to wait.
        With Ollama, you can start building the next generation of AI-powered apps 
        &lt;em&gt;right now&lt;/em&gt;.&lt;/p&gt;
      </content>
      <author>
        <name>Mattt</name>
        <email>mattt@nshipster.com</email>
        <uri>https://nshipster.com/authors/mattt/</uri>
      </author>
      <category term="Miscellaneous" />
      <summary type="html">&lt;p&gt;While we wait for Apple Intelligence to arrive on our devices, something remarkable is already running on our Macs. Think of it as a locavore approach to artificial intelligence: homegrown, sustainable, and available year-round.&lt;/p&gt;</summary>
    </entry>
    <entry>
      <title type="html">op run</title>
      <link href="https://nshipster.com/1password-cli/" rel="alternate" type="text/html" title="op run" />
      <published>2025-01-01T00:00:00-08:00</published>
      <updated>2025-01-01T00:00:00-08:00</updated>
      <id>https://nshipster.com/1password-cli</id>
      <content type="html" xml:base="https://nshipster.com/1password-cli/">
        &lt;p&gt;&lt;code&gt;.env&lt;/code&gt; files.
        If you’ve worked on a web application,
        you’ve probably seen one.&lt;/p&gt;
        &lt;p&gt;While they certainly get the job done,
        &lt;code&gt;.env&lt;/code&gt; files have shortcomings that can create friction in development workflows.&lt;/p&gt;
        &lt;p&gt;We’ve touched on &lt;code&gt;.env&lt;/code&gt; files in past articles about
        &lt;a href=&quot;https://nshipster.com/xcconfig/&quot;&gt;xcconfig&lt;/a&gt; files and 
        &lt;a href=&quot;https://nshipster.com/secrets/&quot;&gt;secret management on iOS&lt;/a&gt;.
        But this week on NSHipster we’re taking a deeper look,
        exploring how the lesser-known
        &lt;a href=&quot;https://developer.1password.com/docs/cli/get-started/&quot;&gt;1Password CLI&lt;/a&gt; (&lt;code&gt;op&lt;/code&gt;)
        can solve some problems many of us face managing secrets day-to-day.&lt;/p&gt;
        &lt;hr&gt;&lt;a id=&quot;get-on-with-it&quot;&gt;&lt;/a&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;the-problem-of-configuration&quot; href=&quot;#the-problem-of-configuration&quot;&gt;&lt;/a&gt;The Problem of Configuration&lt;/h2&gt;
        &lt;p&gt;Around 2011, Adam Wiggins published
        &lt;a href=&quot;https://12factor.net&quot;&gt;“The Twelve-Factor App”&lt;/a&gt;,
        a methodology for building modern web applications
        that has since become canon in our industry.&lt;/p&gt;
        &lt;p&gt;The third of those twelve factors,
        &lt;a href=&quot;https://12factor.net/config&quot;&gt;“Config”&lt;/a&gt;,
        prescribes storing configuration in environment variables:&lt;/p&gt;
        &lt;blockquote&gt;
        &lt;p&gt;“Apps sometimes store config as constants in the code.
        This is a violation of twelve-factor,
        which requires &lt;strong&gt;strict separation of config from code&lt;/strong&gt;.
        Config varies substantially across deploys, code does not.”&lt;/p&gt;
        &lt;/blockquote&gt;
        &lt;p&gt;This core insight — that configuration should be separate from code —
        led to the widespread adoption of &lt;code&gt;.env&lt;/code&gt; files.&lt;/p&gt;
        &lt;aside class=&quot;admonition info&quot;&gt;
        &lt;p&gt;The convention of &lt;code&gt;.env&lt;/code&gt; files also came out of Heroku at that time,
        by way of David Dollar’s &lt;a href=&quot;https://github.com/ddollar/foreman&quot;&gt;Foreman&lt;/a&gt; tool.
        Brandon Keepers’ standalone &lt;a href=&quot;https://github.com/bkeepers/dotenv&quot;&gt;dotenv&lt;/a&gt; Ruby gem
        came a couple years later.
        Both projects have inspired myriad ports to other languages.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;A typical &lt;code&gt;.env&lt;/code&gt; file looks something like this:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;plaintext&quot;&gt;&lt;code&gt;DATABASE_URL=postgres://localhost:5432/myapp_development
        REDIS_URL=redis://localhost:6379/0
        AWS_ACCESS_KEY_ID=AKIA...
        AWS_SECRET_ACCESS_KEY=w&lt;wbr&gt;&lt;/wbr&gt;Ja...
        STRIPE_SECRET_KEY=sk_test_...
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;You add this file to &lt;code&gt;.gitignore&lt;/code&gt; to keep it out of version control,
        and load these variables into your environment at runtime with a tool or library.&lt;/p&gt;
        &lt;p&gt;Simple enough. 
        So what’s the problem?&lt;/p&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;env-files-in-practice&quot; href=&quot;#env-files-in-practice&quot;&gt;&lt;/a&gt;.env Files in Practice&lt;/h3&gt;
        &lt;p&gt;Despite their apparent simplicity,
        &lt;code&gt;.env&lt;/code&gt; files introduce several points of friction in development workflows:&lt;/p&gt;
        &lt;p&gt;First, there’s the perennial issue of onboarding:
        How does a new team member get what they need to run the app locally?
        The common solution is to have a &lt;code&gt;.env.sample&lt;/code&gt; / &lt;code&gt;.env.example&lt;/code&gt; file in version control,
        but this creates a maintenance burden to keep it in sync with the actual requirements.
        And in any case,
        developers still need to go on a scavenger hunt to fill it out 
        before they can be productive.&lt;/p&gt;
        &lt;p&gt;Then there’s the multi-environment problem:
        As soon as you need different configurations for development, staging, and production,
        you end up with a proliferation of files:
        &lt;code&gt;.env.development&lt;/code&gt;, &lt;code&gt;.env.test&lt;/code&gt;, &lt;code&gt;.env.staging&lt;/code&gt;…
        Each requiring its own &lt;code&gt;.sample&lt;/code&gt; / &lt;code&gt;.example&lt;/code&gt; counterpart.&lt;/p&gt;
        &lt;p&gt;But perhaps most pernicious is the challenge of managing changes to configuration over time.
        Because &lt;code&gt;.env&lt;/code&gt; files aren’t in version control,
        changes aren’t, you know… &lt;em&gt;tracked anywhere&lt;/em&gt; 🥲&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;enter-the-1password-cli-op&quot; href=&quot;#enter-the-1password-cli-op&quot;&gt;&lt;/a&gt;Enter the 1Password CLI (&lt;code&gt;op&lt;/code&gt;)&lt;/h2&gt;
        &lt;p&gt;You may already use &lt;a href=&quot;https://1password.com&quot;&gt;1Password&lt;/a&gt; 
        to manage your passwords and other secrets.
        But what you might not know is that 1Password also has a CLI
        that can integrate directly with your development workflow.&lt;/p&gt;
        &lt;p&gt;&lt;code&gt;op&lt;/code&gt; lets you manage 1Password from the command-line.
        You can do all the 
        &lt;abbr title=&quot;Create-Read-Update-Delete&quot;&gt;CRUD&lt;/abbr&gt;
        operations you’d expect for items in your vault.
        But its killer features is the &lt;code&gt;op run&lt;/code&gt; subcommand,
        which can dynamically inject secrets from your 1Password vault
        into your application’s environment.&lt;/p&gt;
        &lt;p&gt;Instead of storing sensitive values directly in your &lt;code&gt;.env&lt;/code&gt; file,
        you reference them using special &lt;code&gt;op://&lt;/code&gt; URLs:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;shell&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# .env&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;IRC_USERNAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;op://development/chatroom/username
        &lt;span class=&quot;nv&quot;&gt;IRC_PASSWORD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;op://development/chatroom/password
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;&lt;span&gt;&lt;/span&gt; &lt;!-- Empty span prevents adjacent code blocks from being combined --&gt;&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Foundation&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;guard&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;username&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Process&lt;wbr&gt;&lt;/wbr&gt;Info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;process&lt;wbr&gt;&lt;/wbr&gt;Info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;IRC_USERNAME&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Process&lt;wbr&gt;&lt;/wbr&gt;Info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;process&lt;wbr&gt;&lt;/wbr&gt;Info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;IRC_PASSWORD&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;fatal&lt;wbr&gt;&lt;/wbr&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Missing required environment variables&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// For testing only - never print credentials in production code&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;Run this on its own, 
        and you’ll fail in proper 12 Factor fashion:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Terminal&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;swift run
        &lt;span class=&quot;go&quot;&gt;❗️ &quot;Missing required environment variables&quot;
        &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;But by prepending &lt;code&gt;op run&lt;/code&gt;
        we read in that &lt;code&gt;.env&lt;/code&gt; file,
        resolve each vault item reference,
        and injects those values into the evironment:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Terminal&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;op run &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; swift run
        &lt;span class=&quot;go&quot;&gt;hunter2
        &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
        &lt;aside class=&quot;admonition warning&quot;&gt;
        &lt;p&gt;The double dash (&lt;code&gt;--&lt;/code&gt;) after &lt;code&gt;op run&lt;/code&gt; is important!
        It tells the shell to pass all subsequent arguments to the command being run,
        rather than interpreting them as options to &lt;code&gt;op run&lt;/code&gt; itself.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;You’re even prompted to authorize with Touch ID the first time you invoke &lt;code&gt;op run&lt;/code&gt;.&lt;/p&gt;
        &lt;figure&gt;
        &lt;picture&gt;
        &lt;source srcset=&quot;/assets/1password-authorize--dark-688f1be83edffc1bdb919ab35b0a411b2ce6a37dfed96667039a0ba6ecf4dddbdbec0decd9e49956b625d1a968b3395e3142bae118d223dbb383b7e2437ee947.png&quot; media=&quot;(prefers-color-scheme: dark)&quot;&gt;
        &lt;img src=&quot;/assets/1password-authorize--light-a603cb0d66d88414549464ef558e4d72b30cb6b6ce0bd0507a9b2d4a936dfb11a8822079dea904d843875e48f8d9dc2a906d9d82b8177e9e2fe9a9320e2b4e03.png&quot; alt=&quot;1Password Create Vault dialog&quot; loading=&quot;lazy&quot; style=&quot;width: 400px;&quot;&gt;
        &lt;/source&gt;&lt;/picture&gt;
        &lt;/figure&gt;
        &lt;hr&gt;
        &lt;p&gt;Ready to give this a test drive?
        Here’s how to get started:&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;a-step-by-step-guide-to-using-the-1password-cli-in-env-files&quot; href=&quot;#a-step-by-step-guide-to-using-the-1password-cli-in-env-files&quot;&gt;&lt;/a&gt;A Step-By-Step Guide to Using the 1Password CLI in .env Files&lt;/h2&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;step-1-install-and-configure-the-1password-cli&quot; href=&quot;#step-1-install-and-configure-the-1password-cli&quot;&gt;&lt;/a&gt;Step 1: Install and Configure the 1Password CLI&lt;/h3&gt;
        &lt;p&gt;On macOS, you can install the CLI with &lt;a href=&quot;https://brew.sh/&quot;&gt;homebrew&lt;/a&gt;:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Terminal&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;1password-cli
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;Then, in the 1Password app, 
        open Settings (&lt;kbd&gt;⌘&lt;/kbd&gt;&lt;kbd&gt;,&lt;/kbd&gt;),
        go to the Developer section,
        and check the box labeled “Integrate with 1Password CLI”.&lt;/p&gt;
        &lt;figure id=&quot;enable-cli-settings&quot;&gt;
        &lt;picture&gt;
        &lt;source srcset=&quot;/assets/1password-settings--dark-5e4819e1ac249e35c747538704e58f5d058a416974ac0f7b41596929eff9797f667f71caa6220e384d7a1650027d0bc43d3d64cd4e003c6b0284ad0dfbd52515.png&quot; media=&quot;(prefers-color-scheme: dark)&quot;&gt;
        &lt;img src=&quot;/assets/1password-settings--light-d793948bc993ebd4d35317ef922a401cf9a06e6155ab312ac4c0e9fb3e45e52cb83eca546c8ce6b3ae3249d8052b23ddd8f8c39d57d626b897ac50d7fed0fb23.png&quot; alt=&quot;1Password Settings&quot; loading=&quot;lazy&quot; style=&quot;width: 100%;  margin: 0 !important;&quot;&gt;
        &lt;/source&gt;&lt;/picture&gt;
        &lt;/figure&gt;
        &lt;p&gt;Running any &lt;code&gt;op&lt;/code&gt; subcommand should prompt you to connect to the app.&lt;/p&gt;
        &lt;p&gt;If you get off the happy path,
        consult &lt;a href=&quot;https://developer.1password.com/docs/cli/get-started/&quot;&gt;the official docs&lt;/a&gt;
        to get back on track.&lt;/p&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;step-2-create-a-shared-vault&quot; href=&quot;#step-2-create-a-shared-vault&quot;&gt;&lt;/a&gt;Step 2: Create a Shared Vault&lt;/h3&gt;
        &lt;p&gt;Create a new vault in 1Password specifically for development secrets.
        Give it a clear name like “Development” and a useful description.&lt;/p&gt;
        &lt;figure id=&quot;create-vault-dialog&quot;&gt;
        &lt;picture&gt;
        &lt;source srcset=&quot;/assets/1password-create-vault--dark-1fc86db9e0a51376c5e20a80c3e76d85eb2408ab828eb5e77ab4531d92a01b4bf8cb8541383905b7db7ad0a349cbe836587bdb57d6192ceb641a25f51b279176.png&quot; media=&quot;(prefers-color-scheme: dark)&quot;&gt;
        &lt;img src=&quot;/assets/1password-create-vault--light-14040f422f6b39b6b84e9266dea5859f944f65344948dd8b373cc3734de98ace845fc1c7590aaf270c0295ff296420ce9bccb6aafa7b3d0ae879b58e6f673a33.png&quot; alt=&quot;1Password Create Vault dialog&quot; loading=&quot;lazy&quot; style=&quot;width: 100%;  margin: 0 !important;&quot;&gt;
        &lt;/source&gt;&lt;/picture&gt;
        &lt;/figure&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;step-3-migrate-existing-secrets&quot; href=&quot;#step-3-migrate-existing-secrets&quot;&gt;&lt;/a&gt;Step 3: Migrate Existing Secrets&lt;/h3&gt;
        &lt;p&gt;For each entry in your &lt;code&gt;.env&lt;/code&gt; file,
        create a corresponding item in 1Password.
        Choose the appropriate item type:&lt;/p&gt;
        &lt;div style=&quot;display: flex; align-items: center; margin-bottom: 1rem;&quot;&gt;
        &lt;div style=&quot;margin-right: 1rem;&quot;&gt;
        &lt;img src=&quot;/assets/1password-api-credential-f848f27796dc0008b214bed990e11a0c521e0ae427b8cf3e9b54ce97895c5275b9c02b4ef9d6aae4800de2d0695c85c6d640e627332ee29b15951c886ea96520.png&quot; alt=&quot;&quot; width=&quot;64&quot;&gt;
        &lt;/div&gt;
        &lt;div&gt;
        &lt;strong&gt;API Credential&lt;/strong&gt;
        &lt;div&gt;For third-party service API keys&lt;/div&gt;
        &lt;div class=&quot;fields&quot;&gt;
        Fields:
        &lt;span class=&quot;field&quot;&gt;username&lt;/span&gt;,
        &lt;span class=&quot;field&quot;&gt;credential&lt;/span&gt;
        &lt;/div&gt;
        &lt;/div&gt;
        &lt;/div&gt;
        &lt;div style=&quot;display: flex; align-items: center; margin-bottom: 1rem;&quot;&gt;
        &lt;div style=&quot;margin-right: 1rem;&quot;&gt;
        &lt;img src=&quot;/assets/1password-password-61b2ba71f1864985527199951225465adacab9415813e76ff6de67a0522f7da58c8bf6724e1fc0a1e426a419e8eaba81acbe9ee3ca16bd36f84957e58d5fd61f.png&quot; alt=&quot;&quot; width=&quot;64&quot;&gt;
        &lt;/div&gt;
        &lt;div&gt;
        &lt;strong&gt;Password&lt;/strong&gt;
        &lt;div&gt;For first-party secrets, like encryption keys&lt;/div&gt;
        &lt;div class=&quot;fields&quot;&gt;
        Fields:
        &lt;span class=&quot;field&quot;&gt;username&lt;/span&gt;,
        &lt;span class=&quot;field&quot;&gt;password&lt;/span&gt;
        &lt;/div&gt;
        &lt;/div&gt;
        &lt;/div&gt;
        &lt;div style=&quot;display: flex; align-items: center; margin-bottom: 1rem;&quot;&gt;
        &lt;div style=&quot;margin-right: 1rem;&quot;&gt;
        &lt;img src=&quot;/assets/1password-database-9109b5422bd1ce3792c53fb8c44d1b7893738b10dbcd0fe39e471dae36ca5f6385832d2e6982c614c013741a0ab9da4c7c44b464c1756a08cd88c11880478b41.png&quot; alt=&quot;&quot; width=&quot;64&quot;&gt;
        &lt;/div&gt;
        &lt;div&gt;
        &lt;strong&gt;Database&lt;/strong&gt;
        &lt;div&gt;For hosted PostgreSQL databases and the like&lt;/div&gt;
        &lt;div class=&quot;fields&quot;&gt;
        Fields:
        &lt;span class=&quot;field&quot;&gt;type&lt;/span&gt;,
        &lt;span class=&quot;field&quot;&gt;server&lt;/span&gt;,
        &lt;span class=&quot;field&quot;&gt;port&lt;/span&gt;,
        &lt;span class=&quot;field&quot;&gt;database&lt;/span&gt;,
        &lt;span class=&quot;field&quot;&gt;username&lt;/span&gt;,
        &lt;span class=&quot;field&quot;&gt;password&lt;/span&gt;
        &lt;/div&gt;
        &lt;/div&gt;
        &lt;/div&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;step-4-update-your-env-file&quot; href=&quot;#step-4-update-your-env-file&quot;&gt;&lt;/a&gt;Step 4: Update Your .env File&lt;/h3&gt;
        &lt;p&gt;Replace raw values in your &lt;code&gt;.env&lt;/code&gt; file
        with &lt;code&gt;op://&lt;/code&gt; references using the following format:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;plaintext&quot;&gt;&lt;code&gt;op://&lt;var class=&quot;placeholder&quot;&gt;vault&lt;/var&gt;/&lt;var class=&quot;placeholder&quot;&gt;item&lt;/var&gt;/&lt;var class=&quot;placeholder&quot;&gt;field&lt;/var&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;Each reference consists of three components:&lt;/p&gt;
        &lt;ul&gt;
        &lt;li&gt;The vault name (e.g., “development”)&lt;/li&gt;
        &lt;li&gt;The item name or UUID&lt;/li&gt;
        &lt;li&gt;The field name from the item&lt;/li&gt;
        &lt;/ul&gt;
        &lt;p&gt;For example, here’s how you might reference credentials for various services:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;shell&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Reference by item name (case-insensitive)&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;op://development/AWS/username
        &lt;span class=&quot;nv&quot;&gt;AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;op://development/Work&lt;wbr&gt;&lt;/wbr&gt;OS/credential
        &lt;span class=&quot;c&quot;&gt;# Reference by item UUID&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;STRIPE_SECRET_KEY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;op://development/abc123xyz789defghijklmnop/password
        &lt;span class=&quot;c&quot;&gt;# Using different field names based on item type&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;DATABASE_HOST&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;op://development/db/server
        &lt;span class=&quot;nv&quot;&gt;DATABASE_USER&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;op://development/db/username
        &lt;span class=&quot;nv&quot;&gt;DATABASE_PASSWORD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;op://development/db/password
        &lt;span class=&quot;nv&quot;&gt;DATABASE_NAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;op://development/db/database
        &lt;/code&gt;&lt;/pre&gt;
        &lt;div style=&quot;display: flex; align-items: flex-start; gap: 1.5em; margin-bottom: 1em; padding-top: 0.5em;&quot;&gt;
        &lt;div style=&quot;flex: 1;&quot;&gt;
        &lt;p&gt;
        You can locate the UUID for any item in 1Password by 
        clicking the &quot;More actions&quot; button (&lt;kbd title=&quot;actions menu&quot;&gt;⋮&lt;/kbd&gt;, &lt;em&gt;whatever you want to call that&lt;/em&gt;) 
        and selecting &quot;Copy item UUID&quot;.
        &lt;/p&gt;
        &lt;p&gt;
        Both item name and UUID references work,
        but using UUIDs can be more reliable in automation contexts
        since they're guaranteed to be unique and won't change if you rename the item.
        &lt;/p&gt;
        &lt;/div&gt;
        &lt;picture&gt;
        &lt;source srcset=&quot;/assets/1password-copy-uuid--dark-fbda5528fb43cf416087ad87c6da9e20dc5b40cb8374086c435695a45fbac5a5e8a56f100debcde46355132d69b269efdbc0cfaffd97aac1295d4b1b922da3e0.png&quot; media=&quot;(prefers-color-scheme: dark)&quot;&gt;
        &lt;img src=&quot;/assets/1password-copy-uuid--light-a6301b3bfce557550474188650f4c4860327b1f84560d414bb6f284262c82fc97f3db2418a61c249cb7b4e764b45881a96266bc943d1fc1633c05da8a43b81f2.png&quot; alt=&quot;1Password Copy Item UUID&quot; loading=&quot;lazy&quot; style=&quot;width: 150px; margin: 0 !important;&quot;&gt;
        &lt;/source&gt;&lt;/picture&gt;
        &lt;/div&gt;
        &lt;p&gt;Once you’ve replaced all sensitive values with &lt;code&gt;op://&lt;/code&gt; references,
        you can safely commit your &lt;code&gt;.env&lt;/code&gt; file to version control.
        The references themselves don’t contain any sensitive information –
        they’re just pointers to your 1Password vault.&lt;/p&gt;
        &lt;aside class=&quot;admonition info&quot;&gt;
        &lt;p&gt;You might find that &lt;code&gt;.env&lt;/code&gt; files are excluded by your global Git configuration.
        To override this, add the following to your repository’s &lt;code&gt;.gitignore&lt;/code&gt;:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;shell&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Override global .gitignore to allow .env containing op:// references&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;.env
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;The exclamation point (&lt;code&gt;!&lt;/code&gt;) &lt;a href=&quot;https://git-scm.com/docs/gitignore#_pattern_format&quot;&gt;negates a previous pattern&lt;/a&gt;,
        allowing you to explicitly include a file that would otherwise be ignored.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;step-5-update-your-development-script&quot; href=&quot;#step-5-update-your-development-script&quot;&gt;&lt;/a&gt;Step 5. Update Your Development Script&lt;/h3&gt;
        &lt;p&gt;Whatever command you normally run to kick off your development server,
        you’ll need to prepend &lt;code&gt;op run --&lt;/code&gt; to that.&lt;/p&gt;
        &lt;p&gt;For example, if you follow the 
        &lt;a href=&quot;https://github.com/github/scripts-to-rule-them-all&quot;&gt;“Scripts to Rule Them All”&lt;/a&gt; pattern,
        you’d update &lt;code&gt;script/start&lt;/code&gt; like so:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;diff&quot;&gt;&lt;code&gt;&lt;span class=&quot;err&quot;&gt;#!/bin/sh&lt;/span&gt;
        &lt;span class=&quot;gd&quot;&gt;- swift run
        &lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+ op run -- swift run
        &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
        &lt;aside class=&quot;admonition info&quot;&gt;
        &lt;p&gt;&lt;code&gt;op run&lt;/code&gt; does a neat trick by creating a 
        &lt;a href=&quot;https://en.wikipedia.org/wiki/Pseudoterminal&quot;&gt;pseudoterminal (PTY)&lt;/a&gt; pair
        to redact secrets if printed out directly to &lt;code&gt;stdout&lt;/code&gt;:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Terminal&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;op run &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;env&lt;/span&gt;
        &lt;span class=&quot;go&quot;&gt;LANG=en_US.UTF-8
        &lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;IRC_USERNAME=&amp;lt;concealed by 1Password&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;IRC_PASSWORD=&amp;lt;concealed by 1Password&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;This behavior can be turned off with the &lt;code&gt;--no-masking&lt;/code&gt; option.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;advantages-over-traditional-env-files&quot; href=&quot;#advantages-over-traditional-env-files&quot;&gt;&lt;/a&gt;Advantages Over Traditional .env Files&lt;/h3&gt;
        &lt;p&gt;&lt;code&gt;op run&lt;/code&gt; solves many of the problems inherent to &lt;code&gt;.env&lt;/code&gt; files:&lt;/p&gt;
        &lt;ul&gt;
        &lt;li&gt;
        &lt;p&gt;&lt;strong&gt;No More Cold Start Woes&lt;/strong&gt;:
        New team members get access to all required configuration
        simply by joining the appropriate 1Password vault.&lt;/p&gt;
        &lt;/li&gt;
        &lt;li&gt;
        &lt;p&gt;&lt;strong&gt;Automatic Updates&lt;/strong&gt;:
        When credentials change,
        they’re automatically updated for everyone on the team.
        No more out-of-sync configuration.&lt;/p&gt;
        &lt;/li&gt;
        &lt;li&gt;
        &lt;p&gt;&lt;strong&gt;Proper Secret Management&lt;/strong&gt;:
        1Password provides features
        like access controls, versioning, and integration with
        &lt;a href=&quot;https://haveibeenpwned.com/&quot;&gt;Have I Been Pwned&lt;/a&gt;.&lt;/p&gt;
        &lt;/li&gt;
        &lt;/ul&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;potential-gotchas&quot; href=&quot;#potential-gotchas&quot;&gt;&lt;/a&gt;Potential Gotchas&lt;/h2&gt;
        &lt;p&gt;Like any technical solution,
        there are some trade-offs to consider:&lt;/p&gt;
        &lt;ul&gt;
        &lt;li&gt;
        &lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt;:
        &lt;code&gt;op run&lt;/code&gt; adds a small overhead to command startup time
        (typically less than a second).
        &lt;sup&gt;&lt;a href=&quot;https://1password.community/discussion/145854/op-read-is-pretty-slow-700ms-per-invocation&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
        &lt;/li&gt;
        &lt;li&gt;
        &lt;p&gt;&lt;strong&gt;stdout/stderr Handling&lt;/strong&gt;:
        As mentioned above,
        &lt;code&gt;op run&lt;/code&gt; modifies &lt;code&gt;stdout&lt;/code&gt;/&lt;code&gt;stderr&lt;/code&gt; to implement secret masking,
        which can interfere with some terminal applications.
        &lt;sup&gt;&lt;a href=&quot;https://1password.community/discussion/145938/op-run-changes-stdout-and-stderr-to-not-be-ttys-when-masking&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
        &lt;/li&gt;
        &lt;li&gt;
        &lt;p&gt;&lt;strong&gt;Dev Container Support&lt;/strong&gt;:
        If you use &lt;a href=&quot;https://containers.dev/overview&quot;&gt;VSCode Dev Containers&lt;/a&gt;,
        you may encounter some friction with the 1Password CLI.
        &lt;sup&gt;&lt;a href=&quot;https://1password.community/discussion/147554/feature-request-first-class-support-for-dev-containers-and-op-cli&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
        &lt;/li&gt;
        &lt;/ul&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;driving-technical-change&quot; href=&quot;#driving-technical-change&quot;&gt;&lt;/a&gt;Driving Technical Change&lt;/h2&gt;
        &lt;p&gt;The implementation is often the easy part.
        The real challenge can be getting your team on board with the change.&lt;/p&gt;
        &lt;p&gt;First, state the problem you’re trying to solve.
        Change for change’s sake is rarely helpful.&lt;/p&gt;
        &lt;p&gt;Next, figure out who you need to get buy-in from.
        Talk to them.
        Articulate specific pain point that everyone recognizes,
        like the frustration of onboarding new team members
        or the time wasted debugging configuration-related issues.&lt;/p&gt;
        &lt;aside class=&quot;parenthetical&quot;&gt;
        &lt;p&gt;Feel free to link them to this article 😉&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;Once you’ve gotten the green light,
        move slowly but deliberately.
        Start small by migrating a single credential,
        or maybe all of the credentials in a smaller project.
        Build up confidence that this approach is a good fit —
        both technically and socially.&lt;/p&gt;
        &lt;hr&gt;
        &lt;p&gt;Managing development secrets is one of those problems
        that seems trivial at first but can become a significant source of friction
        as your team and application grow.&lt;/p&gt;
        &lt;p&gt;The 1Password CLI offers a more sophisticated approach
        that integrates with tools developers already use and trust.&lt;/p&gt;
        &lt;p&gt;While it may not be the right solution for every team,
        it’s worth considering if you’re feeling the pain of traditional &lt;code&gt;.env&lt;/code&gt; files.&lt;/p&gt;
        &lt;style rel=&quot;stylesheet&quot; type=&quot;text/css&quot; integrity=&quot;sha512-g7bvzuWX2Ivpcr+SqJoOA7RYIAcmCr88iBozdZGS04Dm37+UkDi4vxWWcW0hfBvqU05DiWl6Zh/7sF0A8j0EHQ==&quot; crossorigin=&quot;anonymous&quot;&gt;figure#create-vault-dialog{display:block;width:360px !important;border-radius:10px;box-shadow:0 0 10px rgba(0,0,0,0.1);margin:0 auto;display:block;padding:10px;background-color:#fff;border:1px solid #ccc}@media (prefers-color-scheme: dark){figure#create-vault-dialog{border-color:#777;background-color:#262626}}span.field{font-family:&quot;SFMono-Regular&quot;, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;border:1px solid #0370eb;padding:0.1rem 0.2rem;border-radius:0.2rem}div.fields{margin-top:0.5rem;font-size:0.8rem}figure#authorization-modal{display:block;width:360px !important;margin:0 auto}.highlight .gd{background-color:rgba(255,59,48,0.5)}.highlight .gi{background-color:rgba(52,199,89,0.5)}
        /*# sourceMappingURL=/assets/source-maps/articles/1password-cli.scss.map */
        /*# sourceURL=assets/css/articles/1password-cli.scss */
        &lt;/style&gt;
      </content>
      <author>
        <name>Mattt</name>
        <email>mattt@nshipster.com</email>
        <uri>https://nshipster.com/authors/mattt/</uri>
      </author>
      <category term="Miscellaneous" />
      <summary type="html">&lt;p&gt;&lt;code&gt;.env&lt;/code&gt; files can create friction in development workflows — especially as teams and projects grow over time. If you’re feeling this pain, the 1Password CLI (&lt;code&gt;op&lt;/code&gt;) might be just what you need.&lt;/p&gt;</summary>
    </entry>
    <entry>
      <title type="html">As We May Code</title>
      <link href="https://nshipster.com/as-we-may-code/" rel="alternate" type="text/html" title="As We May Code" />
      <published>2020-07-07T00:00:00-07:00</published>
      <updated>2020-07-07T00:00:00-07:00</updated>
      <id>https://nshipster.com/as-we-may-code</id>
      <content type="html" xml:base="https://nshipster.com/as-we-may-code/">
        &lt;p&gt;Chris Lattner often describes &lt;a href=&quot;http://llvm.org/&quot;&gt;LLVM&lt;/a&gt; as a process of &lt;dfn&gt;lowering&lt;/dfn&gt;.&lt;/p&gt;
        &lt;p&gt;&lt;img alt=&quot;Swift Compiler Architecture Diagram&quot; integrity=&quot;sha512-MvWo9RsyLM49AU+3pZXFxcgbuG8Lax3B/Q2HmReMrR9sOTWyMgLzjO1dH/zhxqYrFPLk7zOqaKaOo4MBYuRRZg==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/swift-compilation-diagram-32f5a8f51b322cce3d014fb7a595c5c5c81bb86f0b6b1dc1fd0d8799178cad1f6c3935b23202f38ced5d1ffce1c6a62b14f2e4ef33aa68a68ea3830162e45166.png&quot;&gt;&lt;/p&gt;
        &lt;p&gt;You start at the highest level of abstraction,
        source code written in a programming language like Swift or Objective-C.
        That code is parsed into an abstract syntax tree,
        (&lt;abbr title=&quot;Abstract Syntax Tree&quot;&gt;AST&lt;/abbr&gt;),
        which is progressively transformed into
        lower-level, intermediate representations
        until it finally becomes executable binary.&lt;/p&gt;
        &lt;p&gt;What if,
        instead of lowering source code down for the purpose of execution,
        &lt;!-- *bong rip* --&gt;
        we &lt;em&gt;raised&lt;/em&gt; source code for the purpose of understanding?&lt;/p&gt;
        &lt;aside class=&quot;parenthetical&quot;&gt;
        &lt;p&gt;It’s a weird premise, I know. Bear with me.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;You could say that we already do this to some degree with
        &lt;a href=&quot;/swiftsyntax/#highlighting-swift-code&quot;&gt;syntax highlighting&lt;/a&gt; &lt;br&gt;
        (&lt;span class=&quot;nohighlight&quot;&gt;&lt;code&gt;func f()&lt;/code&gt;&lt;/span&gt; → &lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;/code&gt;),
        &lt;a href=&quot;/swiftsyntax/&quot;&gt;structured editing&lt;/a&gt;, and
        &lt;a href=&quot;/swift-documentation/&quot;&gt;documentation generation&lt;/a&gt;.
        But how far could we take it?&lt;/p&gt;
        &lt;hr&gt;&lt;a id=&quot;get-on-with-it&quot;&gt;&lt;/a&gt;
        &lt;p&gt;In this article,
        I’d like to share an idea that I’ve been kicking around for a while.
        It’s something that’s come into greater focus with
        my recent work on &lt;a href=&quot;https://github.com/SwiftDocOrg/swift-doc/&quot;&gt;&lt;code&gt;swift-doc&lt;/code&gt;&lt;/a&gt;,
        but first started to form during tenure in Apple Developer Publications,
        back in 2015.&lt;/p&gt;
        &lt;p&gt;The idea is this: &lt;br&gt;
        &lt;strong&gt;What if we took the lessons of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Semantic_Web&quot;&gt;semantic web&lt;/a&gt;
        and applied them to source code?&lt;/strong&gt;&lt;/p&gt;
        &lt;p&gt;Specifically:&lt;/p&gt;
        &lt;ul&gt;
        &lt;li&gt;
        &lt;strong&gt;Representation&lt;/strong&gt;:
        Software components should be represented by
        a common, language-agnostic data format.&lt;/li&gt;
        &lt;li&gt;
        &lt;strong&gt;Addressability&lt;/strong&gt;:
        Packages, modules, and their constituent APIs
        should each have a unique URL identifier.&lt;/li&gt;
        &lt;li&gt;
        &lt;strong&gt;Decentralization&lt;/strong&gt;:
        Information should be distributed across a federated network of data sources,
        which can cross-reference one another by URL.&lt;/li&gt;
        &lt;/ul&gt;
        &lt;p&gt;I grew up with the Internet,
        and got to see it, first-hand,
        go from an obscure technology to &lt;em&gt;the&lt;/em&gt; dominant cultural force.
        So much of what I see in software development today
        reminds me of what I remember about the web from 20 years ago.
        And if you’ll forgive the extended wind-up,
        I think there’s a lot we can learn by looking at that evolution.&lt;/p&gt;
        &lt;aside class=&quot;parenthetical&quot;&gt;
        &lt;p&gt;As I wrote in my article about &lt;a href=&quot;/cross-pollination&quot;&gt;cross-pollination&lt;/a&gt;,
        great ideas often arise from unlikely connections.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;aside class=&quot;admonition warning&quot;&gt;
        &lt;p&gt;If you’re already familiar with semantic web
        or aren’t all that interested in a history lesson
        feel free to &lt;a href=&quot;#skip&quot;&gt;skip ahead to the technical details&lt;/a&gt;.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;hr&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;web-10-the-web-of-documents&quot; href=&quot;#web-10-the-web-of-documents&quot;&gt;&lt;/a&gt;&lt;small&gt;Web 1.0&lt;/small&gt; The Web of Documents&lt;/h2&gt;
        &lt;p&gt;Tim Berners-Lee launched the World Wide Web
        from a NeXT workstation 27 years ago.
        His vision for a
        globally-distributed, decentralized network of inter-connected documents
        gave rise to the Internet as we know it today.
        But it was also part of an intellectual tradition dating back to the 1940s,
        which includes
        Vannevar Bush’s &lt;em&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Memex&quot;&gt;Memex&lt;/a&gt;&lt;/em&gt;,
        Ted Nelson’s &lt;em&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Project_Xanadu&quot;&gt;Xanadu&lt;/a&gt;&lt;/em&gt;, and
        Doug Engelbart’s &lt;em&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/The_Mother_of_All_Demos&quot;&gt;Mother of All Demos&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
        &lt;aside class=&quot;admonition info&quot;&gt;
        &lt;p&gt;Dr. Bush coined the term &lt;dfn&gt;memex&lt;/dfn&gt; in an essay titled
        &lt;a href=&quot;https://www.theatlantic.com/magazine/archive/1945/07/as-we-may-think/303881/&quot;&gt;“As We May Think”&lt;/a&gt;,
        published in the July 1945 issue of &lt;em&gt;The Atlantic&lt;/em&gt;.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;In those early days,
        the knowledge being shared was primarily academic.
        As the userbase grew over time,
        so too did the breadth and diversity of the information available.
        And, for a time,
        that’s what the Internet was:
        &lt;a href=&quot;http://www.automaticbeyondbelief.org&quot;&gt;fan sites&lt;/a&gt; for Sunbeam toasters,
        &lt;a href=&quot;http://www.varasanos.com/PizzaRecipe.htm&quot;&gt;recipes&lt;/a&gt; for Neapolitan-style pizza, and
        &lt;a href=&quot;https://www.spacejam.com&quot;&gt;the official website&lt;/a&gt; for the 1996 film &lt;em&gt;Space Jam&lt;/em&gt;.&lt;/p&gt;
        &lt;p&gt;But the web of documents had limits.&lt;/p&gt;
        &lt;p&gt;If you wanted to
        shop for appliances,
        see the menu of a pizza shop, or
        get local showtimes for a movie,
        you &lt;em&gt;might&lt;/em&gt; be able to do that on the early Internet.
        But you really had to work at it.&lt;/p&gt;
        &lt;p&gt;Back then,
        you’d start by going to a directory like &lt;a href=&quot;https://en.wikipedia.org/wiki/Yahoo!_Directory&quot;&gt;Yahoo!&lt;/a&gt; or &lt;a href=&quot;https://en.wikipedia.org/wiki/DMOZ&quot;&gt;DMOZ&lt;/a&gt;,
        navigate to the relevant topic,
        and click around until you found a promising lead.
        Most of the time, you wouldn’t find what you were looking for;
        instead, you’d disconnect your modem to free up your landline
        and consult the &lt;a href=&quot;https://en.wikipedia.org/wiki/Yellow_pages&quot;&gt;yellow pages&lt;/a&gt;.&lt;/p&gt;
        &lt;aside class=&quot;admonition info&quot;&gt;
        &lt;p&gt;As it were,
        the difficulty of finding information on the web
        gave us the term &lt;a href=&quot;https://en.wikipedia.org/wiki/Sherlock_(software)#Sherlocked_as_a_term&quot;&gt;&lt;dfn&gt;Sherlocked&lt;/dfn&gt;&lt;/a&gt;.
        Apple’s v3 release of the eponymous system software
        was widely seen to have killed Karelia Software’s
        &lt;a href=&quot;https://en.wikipedia.org/wiki/Karelia_Watson&quot;&gt;Watson&lt;/a&gt;:
        a similar (paid) application for Mac OS X
        that offered a uniform interface to information like stocks, movies, and flights.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;This started to change in the early ’00s.&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;web-20-the-social-web&quot; href=&quot;#web-20-the-social-web&quot;&gt;&lt;/a&gt;&lt;small&gt;Web 2.0&lt;/small&gt; The Social Web&lt;/h2&gt;
        &lt;p&gt;With &lt;a href=&quot;https://en.wikipedia.org/wiki/Common_Gateway_Interface&quot;&gt;Perl CGI&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/PHP&quot;&gt;PHP&lt;/a&gt;,
        you could now easily generate web pages on-the-fly.
        This enabled eCommerce and the first commercial uses of the Internet.&lt;/p&gt;
        &lt;p&gt;After the ensuing &lt;a href=&quot;https://en.wikipedia.org/wiki/Dot-com_bubble&quot;&gt;dot-com bubble&lt;/a&gt;,
        you had technologies like &lt;a href=&quot;https://en.wikipedia.org/wiki/Java_applet&quot;&gt;Java applets&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Adobe_Flash&quot;&gt;Flash&lt;/a&gt;
        bring a new level of interactivity to web sites.
        Eventually, folks figured out how to use
        &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest&quot;&gt;an obscure API from Internet Explorer 5&lt;/a&gt;
        to replicate this interactivity on normal webpages —
        a technique dubbed &lt;a href=&quot;https://en.wikipedia.org/wiki/Ajax_(programming)&quot;&gt;AJAX&lt;/a&gt;.
        Interacting with a page and seeing results live, without reloading a page?
        This was &lt;em&gt;huge&lt;/em&gt;.
        Without that,
        social media might not have taken off as it did.&lt;/p&gt;
        &lt;p&gt;Anyway,
        the server-side APIs powering those AJAX interactions on the client,
        they were the secret sauce that let the Internet evolve into what it is today.&lt;/p&gt;
        &lt;p&gt;Remember &lt;dfn&gt;“&lt;a href=&quot;https://en.wikipedia.org/wiki/Mashup_(web_application_hybrid)&quot;&gt;mashups&lt;/a&gt;”&lt;/dfn&gt;?&lt;/p&gt;
        &lt;p&gt;Thanks to all of these (often unsecured) AJAX endpoints,
        developers could synthesize information across multiple sources
        in ways that nobody had ever thought to do.
        You could get someone’s location from &lt;a href=&quot;https://en.wikipedia.org/wiki/Fire_Eagle&quot;&gt;Fire Eagle&lt;/a&gt;,
        search for photos taken nearby on &lt;a href=&quot;https://www.flickr.com&quot;&gt;Flickr&lt;/a&gt;,
        and use &lt;a href=&quot;https://www.moo.com/us/&quot;&gt;MOO&lt;/a&gt; to print and deliver prints of them on-demand.&lt;/p&gt;
        &lt;aside class=&quot;parenthetical&quot;&gt;
        &lt;p&gt;Mashups felt like punk rock.
        I have a lot of fond memories from this time.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;By the end of the decade,
        the rise of social networks and the early promise of mashups
        started to coalesce into the modern Internet.&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;web-30-the-web-of-data&quot; href=&quot;#web-30-the-web-of-data&quot;&gt;&lt;/a&gt;&lt;small&gt;Web 3.0&lt;/small&gt; The Web of Data&lt;/h2&gt;
        &lt;p&gt;The term “Web 3.0” didn’t catch on like its predecessor,
        but there’s a clear delineation between
        the technologies and culture of the web between the early and late ’00s.&lt;/p&gt;
        &lt;p&gt;It’s hard to overstate how much the iPhone’s launch in 2007
        totally changed the trajectory of the Internet.
        But many other events played an important role in
        shaping the web as we know it today:&lt;/p&gt;
        &lt;ul&gt;
        &lt;li&gt;Google acquiring the company behind &lt;a href=&quot;https://en.wikipedia.org/wiki/Freebase_(database)&quot;&gt;Freebase&lt;/a&gt;,
        giving it a knowledge graph to augment its website index.&lt;/li&gt;
        &lt;li&gt;Facebook launching &lt;a href=&quot;https://ogp.me&quot;&gt;Open Graph&lt;/a&gt;,
        which meant everything could now be “Liked”
        (and everyone could be targeted for advertisements).&lt;/li&gt;
        &lt;li&gt;Yahoo releasing &lt;a href=&quot;https://en.wikipedia.org/wiki/Yahoo!_SearchMonkey&quot;&gt;SearchMonkey&lt;/a&gt; and
        &lt;a href=&quot;https://en.wikipedia.org/wiki/Yahoo!_Search_BOSS&quot;&gt;&lt;abbr title=&quot;Build your Own Search Service&quot;&gt;BOSS&lt;/abbr&gt;&lt;/a&gt;,
        two ambitious (albeit flawed) attempts
        to carve out a niche from Google’s monopoly on search.&lt;/li&gt;
        &lt;li&gt;Wolfram launching &lt;a href=&quot;https://www.wolframalpha.com&quot;&gt;Wolfram|Alpha&lt;/a&gt;,
        which far exceeded what many of us thought was possible
        for a question answering system.&lt;/li&gt;
        &lt;/ul&gt;
        &lt;p&gt;The Internet always had a lot of information on it;
        the difference now is that
        the information is accessible to machines as well as humans.&lt;/p&gt;
        &lt;p&gt;Today,
        you can ask Google
        &lt;a href=&quot;https://www.google.com/search?q=Who+was+the+first+person+to+land+on+the+moon%3F&quot;&gt;&lt;em&gt;“Who was the first person to land on the moon?”&lt;/em&gt;&lt;/a&gt;
        and get an info box saying, &lt;em&gt;“Commander Neil Armstrong”&lt;/em&gt;.
        You can post a link in Messages
        and see it represented by
        &lt;a href=&quot;/ios-13/#generate-rich-representations-of-urls&quot;&gt;a rich visual summary&lt;/a&gt;
        instead of a plain text URL.
        You can ask Siri,
        &lt;em&gt;“What is the &lt;a href=&quot;https://twitter.com/AirspeedSwift&quot;&gt;airspeed velocity&lt;/a&gt; of an unladen swallow?”&lt;/em&gt; and hear back
        &lt;del&gt;&lt;em&gt;“I can’t get the answer to that on HomePod”&lt;/em&gt;&lt;/del&gt;
        &lt;ins&gt;&lt;em&gt;About 25 miles per hour&lt;/em&gt;&lt;/ins&gt;.&lt;/p&gt;
        &lt;aside class=&quot;parenthetical&quot;&gt;
        &lt;p&gt;We’re just kidding about that last one.
        Siri has gotten a lot better in recent years.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;Think about what we take for granted about the Internet now,
        and try to imagine doing that on the web when it looked
        &lt;a href=&quot;https://www.spacejam.com&quot;&gt;like this&lt;/a&gt;.
        It’s hard to think that any of this would be possible without the semantic web.&lt;/p&gt;
        &lt;hr&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;githubcom-present-day-the-spider-and-the-octocat&quot; href=&quot;#githubcom-present-day-the-spider-and-the-octocat&quot;&gt;&lt;/a&gt;&lt;small&gt;GitHub.com, Present Day&lt;/small&gt; The Spider and The Octocat&lt;/h2&gt;
        &lt;p&gt;READMEs on GitHub.com today remind me of
        personal home pages on &lt;a href=&quot;https://en.wikipedia.org/wiki/Yahoo!_GeoCities&quot;&gt;Geocities&lt;/a&gt; back in the Web 1.0 days.&lt;/p&gt;
        &lt;aside class=&quot;admonition info&quot;&gt;
        &lt;p&gt;Compare the “build passing” SVG badges found at the top of READMEs in 2020
        to the 80×15px “XHTML 1.1 ✓” badges found at the bottom of websites in 2000.&lt;/p&gt;
        &lt;p&gt;&lt;img width=&quot;800&quot; integrity=&quot;sha512-D2lQ+av+cjKFdwHJEBHbPpENs4T+oOBm2V2zk0btT0P76Ta2yoKyQEWReAS4lKz1H+QxoCvX1x32WY0ZI90ztA==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/as-we-may-code-badges-0f6950f9abfe7232857701c91011db3e910db384fea0e066d95db39346ed4f43fbe936b6ca82b24045917804b894acf51fe431a02bd7d71df6598d1923dd33b4.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;Even with the &lt;a href=&quot;https://primer.style/css/&quot;&gt;standard coat of paint&lt;/a&gt;,
        you see an enormous degree of variance across projects and communities.
        Some are sparse; others are replete with adornment.&lt;/p&gt;
        &lt;p&gt;And yet,
        no matter what a project’s README looks like,
        onboarding onto a new tool or library entails, well &lt;em&gt;reading&lt;/em&gt;.&lt;/p&gt;
        &lt;aside class=&quot;parenthetical&quot;&gt;
        &lt;p&gt;I mean, it’s right there in capital letters: “READ ME”&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;GitHub offers some structured informational cues:
        language breakdown, license, some metadata about commit activity.
        You can search within the repo using text terms.
        And thanks to &lt;a href=&quot;https://github.com/github/semantic&quot;&gt;semantic&lt;/a&gt; / &lt;a href=&quot;https://github.com/tree-sitter&quot;&gt;tree-sitter&lt;/a&gt;,
        you can even click through to find declarations in some languages.&lt;/p&gt;
        &lt;p&gt;&lt;em&gt;But where’s a list of methods?&lt;/em&gt;
        &lt;em&gt;Where are the platform requirements?&lt;/em&gt; &lt;br&gt;
        You have to read the README to find out!
        (Better hope it’s up-to-date 😭)&lt;/p&gt;
        &lt;p&gt;The modest capabilities of browsing and searching code today
        more closely resemble &lt;a href=&quot;https://en.wikipedia.org/wiki/AltaVista&quot;&gt;AltaVista&lt;/a&gt; circa 2000 than Google circa 2020.
        Theres so much more that we could be doing.&lt;/p&gt;
        &lt;hr&gt;
        &lt;p&gt;&lt;a name=&quot;skip&quot;&gt;&lt;/a&gt;&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;rdf-vocabularies-the-owl-and-the-turtle&quot; href=&quot;#rdf-vocabularies-the-owl-and-the-turtle&quot;&gt;&lt;/a&gt;&lt;small&gt;RDF Vocabularies&lt;/small&gt; The Owl and The Turtle&lt;/h2&gt;
        &lt;p&gt;At the center of the semantic web is something called
        &lt;abbr title=&quot;Resource Description Framework&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Resource_Description_Framework&quot;&gt;RDF&lt;/a&gt;&lt;/abbr&gt;,
        the Resource Description Framework.
        It’s a collection of standards for representing and exchanging data.
        The atomic data entity in &lt;abbr&gt;RDF&lt;/abbr&gt;
        is called a &lt;dfn&gt;triple&lt;/dfn&gt;, which comprises:&lt;/p&gt;
        &lt;ul&gt;
        &lt;li&gt;a subject &lt;em&gt;(“the sky”)&lt;/em&gt;
        &lt;/li&gt;
        &lt;li&gt;a predicate &lt;em&gt;(“has the color”)&lt;/em&gt;
        &lt;/li&gt;
        &lt;li&gt;an object &lt;em&gt;(“blue”&lt;/em&gt;)&lt;/li&gt;
        &lt;/ul&gt;
        &lt;p&gt;You can organize triples according to a
        &lt;dfn&gt;vocabulary&lt;/dfn&gt;, or &lt;dfn&gt;ontology&lt;/dfn&gt;,
        which defines rules about how things are described.
        RDF vocabularies are represented by the
        Web Ontology Language
        (&lt;abbr title=&quot;Web Ontology Language&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Web_Ontology_Language&quot;&gt;OWL&lt;/a&gt;&lt;/abbr&gt;).&lt;/p&gt;
        &lt;p&gt;The ideas behind RDF are simple enough.
        Often, the hardest part is navigating
        its confusing, acronym-laden technology stack.
        The important thing to keep in mind is that
        information can be represented in several different ways
        without changing the meaning of that information.&lt;/p&gt;
        &lt;p&gt;Here’s a quick run-down:&lt;/p&gt;
        &lt;dl&gt;
        &lt;dt&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/RDF/XML&quot;&gt;RDF/XML&lt;/a&gt;&lt;/dt&gt;
        &lt;dd&gt;An XML representation format for &lt;abbr&gt;RDF&lt;/abbr&gt; graphs.&lt;/dd&gt;
        &lt;dt&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/JSON-LD&quot;&gt;JSON-LD&lt;/a&gt;&lt;/dt&gt;
        &lt;dd&gt;A JSON representation format for &lt;abbr&gt;RDF&lt;/abbr&gt; graphs.&lt;/dd&gt;
        &lt;dt&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/N-Triples&quot;&gt;N-Triples&lt;/a&gt;&lt;/dt&gt;
        &lt;dd&gt;A plain text representation format for &lt;abbr&gt;RDF&lt;/abbr&gt; graphs
        where each line encodes a subject–predicate–object triple.&lt;/dd&gt;
        &lt;dt&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Turtle_(syntax)&quot;&gt;Turtle&lt;/a&gt;&lt;/dt&gt;
        &lt;dd&gt;A human-friendly, plain text representation format for &lt;abbr&gt;RDF&lt;/abbr&gt; graphs.
        A superset of N-Triples,
        and the syntax used in &lt;abbr&gt;SPARQL&lt;/abbr&gt; queries.&lt;/dd&gt;
        &lt;dt&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/SPARQL&quot;&gt;SPARQL&lt;/a&gt;&lt;/dt&gt;
        &lt;dd&gt;A query language for &lt;abbr&gt;RDF&lt;/abbr&gt; graphs.&lt;/dd&gt;
        &lt;/dl&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;defining-a-vocabulary&quot; href=&quot;#defining-a-vocabulary&quot;&gt;&lt;/a&gt;Defining a Vocabulary&lt;/h3&gt;
        &lt;p&gt;Let’s start to define a vocabulary for the Swift programming language.
        To start,
        we’ll define the concept of a
        &lt;code&gt;Symbol&lt;/code&gt; along with two subclasses, &lt;code&gt;Structure&lt;/code&gt; and &lt;code&gt;Function&lt;/code&gt;.
        We’ll also define a &lt;code&gt;name&lt;/code&gt; property that holds a token (a string)
        that applies to any &lt;code&gt;Symbol&lt;/code&gt;.
        Finally,
        we’ll define a &lt;code&gt;returns&lt;/code&gt; property that applies to a &lt;code&gt;Function&lt;/code&gt;
        and holds a reference to another &lt;code&gt;Symbol&lt;/code&gt;.&lt;/p&gt;
        &lt;div class=&quot;highlight-group&quot;&gt;
        &lt;div role=&quot;tablist&quot; aria-label=&quot;Languages&quot;&gt;
        &lt;button role=&quot;tab&quot; id=&quot;code-listing-1-turtle-tab&quot; class=&quot;turtle&quot; aria-label=&quot;Languages&quot; aria-controls=&quot;code-listing-1-turtle&quot; aria-selected=&quot;true&quot; tabindex=&quot;-1&quot;&gt;
        Turtle
        &lt;/button&gt;
        &lt;button role=&quot;tab&quot; id=&quot;code-listing-1-xml-tab&quot; class=&quot;xml&quot; aria-label=&quot;Languages&quot; aria-controls=&quot;code-listing-1-xml&quot; aria-selected=&quot;false&quot; tabindex=&quot;-1&quot;&gt;
        XML
        &lt;/button&gt;
        &lt;/div&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Turtle&quot; id=&quot;code-listing-1-turtle&quot; role=&quot;tabpanel&quot; tabindex=&quot;0&quot; aria-labelledby=&quot;code-listing-1-turtle-tab&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;@prefix&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&amp;lt;http://www.swift.org/#&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;@prefix&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;owl:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&amp;lt;http://www.w3.org/2002/07/owl#&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;@prefix&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;rdf:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&amp;lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;@prefix&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;rdfs:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&amp;lt;http://www.w3.org/2000/01/rdf-schema#&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;@prefix&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;xsd:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&amp;lt;http://www.w3.org/2001/XMLSchema#&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Symbol&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;rdf:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;owl:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;rdf:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;owl:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Functional&lt;wbr&gt;&lt;/wbr&gt;Property&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;rdfs:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Symbol&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;rdfs:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;xsd:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Structure&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;rdfs:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sub&lt;wbr&gt;&lt;/wbr&gt;Class&lt;wbr&gt;&lt;/wbr&gt;Of&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Symbol&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;rdfs:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sub&lt;wbr&gt;&lt;/wbr&gt;Class&lt;wbr&gt;&lt;/wbr&gt;Of&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Symbol&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;returns&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;rdf:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;owl:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Functional&lt;wbr&gt;&lt;/wbr&gt;Property&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;rdfs:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;rdfs:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Symbol&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;XML&quot; id=&quot;code-listing-1-xml&quot; role=&quot;tabpanel&quot; tabindex=&quot;0&quot; aria-labelledby=&quot;code-listing-1-xml-tab&quot; hidden=&quot;hidden&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;rdf:RDF&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xmlns:rdf=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;xmlns:rdfs=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.w3.org/2000/01/rdf-schema#&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;xmlns:owl=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.w3.org/2002/07/owl#&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;owl:Class&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rdf:about=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.swift.org/#Symbol&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/owl:Class&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;owl:Functional&lt;wbr&gt;&lt;/wbr&gt;Property&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rdf:about=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.swift.org/#name&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;rdfs:domain&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rdf:resource=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.swift.org/#Symbol&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;rdfs:range&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rdf:resource=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.w3.org/2001/XMLSchema#token&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/owl:Functional&lt;wbr&gt;&lt;/wbr&gt;Property&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;rdf:Description&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rdf:about=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.swift.org/#Structure&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;rdfs:sub&lt;wbr&gt;&lt;/wbr&gt;Class&lt;wbr&gt;&lt;/wbr&gt;Of&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rdf:resource=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.swift.org/#Symbol&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/rdf:Description&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;rdf:Description&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rdf:about=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.swift.org/#Function&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;rdfs:sub&lt;wbr&gt;&lt;/wbr&gt;Class&lt;wbr&gt;&lt;/wbr&gt;Of&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rdf:resource=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.swift.org/#Symbol&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/rdf:Description&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;owl:Functional&lt;wbr&gt;&lt;/wbr&gt;Property&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rdf:about=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.swift.org/#returns&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;rdfs:domain&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rdf:resource=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.swift.org/#Function&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;rdfs:range&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rdf:resource=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.swift.org/#Symbol&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/owl:Functional&lt;wbr&gt;&lt;/wbr&gt;Property&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/rdf:RDF&amp;gt;&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;/div&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;parsing-code-declarations&quot; href=&quot;#parsing-code-declarations&quot;&gt;&lt;/a&gt;Parsing Code Declarations&lt;/h3&gt;
        &lt;p&gt;Now consider the following Swift code:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Widget&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;&lt;var class=&quot;placeholder&quot;&gt;…&lt;/var&gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Widget&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&lt;var class=&quot;placeholder&quot;&gt;…&lt;/var&gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Widget&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&lt;var class=&quot;placeholder&quot;&gt;…&lt;/var&gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;We can use &lt;a href=&quot;https://github.com/apple/swift-syntax&quot;&gt;SwiftSyntax&lt;/a&gt; to parse the code into an AST
        and &lt;a href=&quot;https://github.com/SwiftDocOrg/SwiftSemantics&quot;&gt;SwiftSemantics&lt;/a&gt; to convert those AST nodes
        into a more convenient representation.&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Swift&lt;wbr&gt;&lt;/wbr&gt;Syntax&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Swift&lt;wbr&gt;&lt;/wbr&gt;Semantics&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;collector&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Declaration&lt;wbr&gt;&lt;/wbr&gt;Collector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Syntax&lt;wbr&gt;&lt;/wbr&gt;Parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;collector&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;walk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;collector&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;functions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &quot;foo()&quot;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;collector&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;functions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &quot;Widget&quot;&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;Combining this syntactic reading with information from compiler,
        we can express facts about the code in the form of RDF triples.&lt;/p&gt;
        &lt;div class=&quot;highlight-group&quot;&gt;
        &lt;div role=&quot;tablist&quot; aria-label=&quot;Languages&quot;&gt;
        &lt;button role=&quot;tab&quot; id=&quot;code-listing-2-json-ld-tab&quot; class=&quot;json-ld&quot; aria-label=&quot;Languages&quot; aria-controls=&quot;code-listing-2-json-ld&quot; aria-selected=&quot;true&quot; tabindex=&quot;-1&quot;&gt;
        JSON-LD
        &lt;/button&gt;
        &lt;button role=&quot;tab&quot; id=&quot;code-listing-2-n-triples-tab&quot; class=&quot;n-triples&quot; aria-label=&quot;Languages&quot; aria-controls=&quot;code-listing-2-n-triples&quot; aria-selected=&quot;false&quot; tabindex=&quot;-1&quot;&gt;
        N-Triples
        &lt;/button&gt;
        &lt;button role=&quot;tab&quot; id=&quot;code-listing-2-turtle-tab&quot; class=&quot;turtle&quot; aria-label=&quot;Languages&quot; aria-controls=&quot;code-listing-2-turtle&quot; aria-selected=&quot;false&quot; tabindex=&quot;-1&quot;&gt;
        Turtle
        &lt;/button&gt;
        &lt;/div&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;JSON-LD&quot; id=&quot;code-listing-2-json-ld&quot; role=&quot;tabpanel&quot; tabindex=&quot;0&quot; aria-labelledby=&quot;code-listing-2-json-ld-tab&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;@context&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;@id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;http://www.swift.org/#name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;@type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;http://www.w3.org/2001/XMLSchema#token&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;returns&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;http://www.swift.org/#returns&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;symbols&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;@id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;E83C6A28-1E68-406E-8162-D389A04DFB27&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;@type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;http://www.swift.org/#Structure&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Widget&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;@id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;4EAE3E8C-FD96-4664-B7F7-D64D8B75ECEB&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;@type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;http://www.swift.org/#Function&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;foo()&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;@id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;2D1F49FE-86DE-4715-BD59-FA70392E41BE&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;@type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;http://www.swift.org/#Function&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;bar()&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;N-Triples&quot; id=&quot;code-listing-2-n-triples&quot; role=&quot;tabpanel&quot; tabindex=&quot;0&quot; aria-labelledby=&quot;code-listing-2-n-triples-tab&quot; hidden=&quot;hidden&quot;&gt;&lt;code&gt;_:E83C6A28-1E68-406E-8162-D389A04DFB27 &lt;span class=&quot;nt&quot;&gt;&amp;lt;http:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;//&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;www.w3.org&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/1999/02/22&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;-rdf-syntax-ns#type&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;http:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;//&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;www.swift.org&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;#Structure&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt; .
        _:E83C6A28-1E68-406E-8162-D389A04DFB27 &lt;span class=&quot;nt&quot;&gt;&amp;lt;http:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;//&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;www.swift.org&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;#name&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt; &quot;Widget&quot;^^&lt;span class=&quot;nt&quot;&gt;&amp;lt;http:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;//&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;www.w3.org&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/2001/&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;XMLSchema#token&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt; .
        _:4EAE3E8C-FD96-4664-B7F7-D64D8B75ECEB &lt;span class=&quot;nt&quot;&gt;&amp;lt;http:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;//&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;www.w3.org&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/1999/02/22&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;-rdf-syntax-ns#type&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;http:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;//&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;www.swift.org&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;#Function&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt; .
        _:4EAE3E8C-FD96-4664-B7F7-D64D8B75ECEB &lt;span class=&quot;nt&quot;&gt;&amp;lt;http:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;//&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;www.swift.org&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;#name&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt; &quot;foo()&quot;^^&lt;span class=&quot;nt&quot;&gt;&amp;lt;http:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;//&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;www.w3.org&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/2001/&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;XMLSchema#token&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt; .
        _:4EAE3E8C-FD96-4664-B7F7-D64D8B75ECEB &lt;span class=&quot;nt&quot;&gt;&amp;lt;http:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;//&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;www.swift.org&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;#returns&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt; _:E83C6A28-1E68-406E-8162-D389A04DFB27 .
        _:2D1F49FE-86DE-4715-BD59-FA70392E41BE &lt;span class=&quot;nt&quot;&gt;&amp;lt;http:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;//&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;www.w3.org&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/1999/02/22&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;-rdf-syntax-ns#type&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;http:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;//&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;www.swift.org&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;#Function&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt; .
        _:2D1F49FE-86DE-4715-BD59-FA70392E41BE &lt;span class=&quot;nt&quot;&gt;&amp;lt;http:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;//&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;www.swift.org&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;#name&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt; &quot;bar()&quot;^^&lt;span class=&quot;nt&quot;&gt;&amp;lt;http:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;//&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;www.w3.org&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/2001/&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;XMLSchema#token&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt; .
        _:2D1F49FE-86DE-4715-BD59-FA70392E41BE &lt;span class=&quot;nt&quot;&gt;&amp;lt;http:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;//&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;www.swift.org&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;#returns&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt; _:E83C6A28-1E68-406E-8162-D389A04DFB27 .
        &lt;/code&gt;&lt;/pre&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Turtle&quot; id=&quot;code-listing-2-turtle&quot; role=&quot;tabpanel&quot; tabindex=&quot;0&quot; aria-labelledby=&quot;code-listing-2-turtle-tab&quot; hidden=&quot;hidden&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;@prefix&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;swift:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&amp;lt;http://www.swift.org/#&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;@prefix&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;owl:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&amp;lt;http://www.w3.org/2002/07/owl#&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;@prefix&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;rdf:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&amp;lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;@prefix&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;rdfs:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&amp;lt;http://www.w3.org/2000/01/rdf-schema#&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;@prefix&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;xsd:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&amp;lt;http://www.w3.org/2001/XMLSchema#&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;_:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Widget&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;rdf:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Structure&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;swift:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Widget&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;^^&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;xsd:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;_:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;rdf:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;swift:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;foo()&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;^^&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;xsd:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;swift:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;returns&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;_:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Widget&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;_:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;rdf:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;swift:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;bar()&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;^^&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;xsd:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;swift:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;returns&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;_:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Widget&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
        &lt;/div&gt;
        &lt;p&gt;Encoding our knowledge into a standard format
        lets anyone access that information — however they like.
        And because these facts are encoded within an ontology,
        they can be validated for coherence and consistency.
        It’s totally language agnostic.&lt;/p&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;querying-the-results&quot; href=&quot;#querying-the-results&quot;&gt;&lt;/a&gt;Querying the Results&lt;/h3&gt;
        &lt;p&gt;With an RDF graph of facts,
        we can query it using &lt;a href=&quot;https://en.wikipedia.org/wiki/SPARQL&quot;&gt;SPARQL&lt;/a&gt;.
        Or,
        we could load the information into
        a graph database like &lt;a href=&quot;https://neo4j.com&quot;&gt;Neo4j&lt;/a&gt; or
        a relational database like &lt;a href=&quot;https://postgres.app&quot;&gt;PostgreSQL&lt;/a&gt;
        and perform the query in Cypher or SQL, respectively.&lt;/p&gt;
        &lt;div class=&quot;highlight-group&quot;&gt;
        &lt;div role=&quot;tablist&quot; aria-label=&quot;Languages&quot;&gt;
        &lt;button role=&quot;tab&quot; id=&quot;code-listing-3-sparql-tab&quot; class=&quot;sparql&quot; aria-label=&quot;Languages&quot; aria-controls=&quot;code-listing-3-sparql&quot; aria-selected=&quot;true&quot; tabindex=&quot;-1&quot;&gt;
        SPARQL
        &lt;/button&gt;
        &lt;button role=&quot;tab&quot; id=&quot;code-listing-3-cypher-tab&quot; class=&quot;cypher&quot; aria-label=&quot;Languages&quot; aria-controls=&quot;code-listing-3-cypher&quot; aria-selected=&quot;false&quot; tabindex=&quot;-1&quot;&gt;
        Cypher
        &lt;/button&gt;
        &lt;button role=&quot;tab&quot; id=&quot;code-listing-3-sql-tab&quot; class=&quot;sql&quot; aria-label=&quot;Languages&quot; aria-controls=&quot;code-listing-3-sql&quot; aria-selected=&quot;false&quot; tabindex=&quot;-1&quot;&gt;
        SQL
        &lt;/button&gt;
        &lt;/div&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;SPARQL&quot; id=&quot;code-listing-3-sparql&quot; role=&quot;tabpanel&quot; tabindex=&quot;0&quot; aria-labelledby=&quot;code-listing-3-sparql-tab&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;PREFIX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;swift:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;&amp;lt;http://www.swift.org/#&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;?function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;?name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;?function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;swift:&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;swift:&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;returns&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;?type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;swift:&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;?name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;?type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;swift:&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Widget&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ORDER&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;?function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Cypher&quot; id=&quot;code-listing-3-cypher&quot; role=&quot;tabpanel&quot; tabindex=&quot;0&quot; aria-labelledby=&quot;code-listing-3-cypher-tab&quot; hidden=&quot;hidden&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;MATCH&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;function:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;:RETURNS&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;symbol:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Symbol&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Widget'&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;})&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;RETURN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;function&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;SQL&quot; id=&quot;code-listing-3-sql&quot; role=&quot;tabpanel&quot; tabindex=&quot;0&quot; aria-labelledby=&quot;code-listing-3-sql-tab&quot; hidden=&quot;hidden&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;symbols&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UUID&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;PRIMARY&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;KEY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;TEXT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;functions&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;returns_id&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UUID&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;REFERENCES&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;symbols&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;INHERITS&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;symbols&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;--&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;functions&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;INNER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;JOIN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;symbols&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;USING&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;returns_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Widget'&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;ORDER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;/div&gt;
        &lt;p&gt;Whichever route we take,
        we get the same results:&lt;/p&gt;
        &lt;table&gt;
        &lt;thead&gt;
        &lt;tr&gt;
        &lt;th&gt;id&lt;/th&gt;
        &lt;th&gt;name&lt;/th&gt;
        &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
        &lt;tr&gt;
        &lt;td&gt;4EAE3E8C-FD96-4664-B7F7-D64D8B75ECEB&lt;/td&gt;
        &lt;td&gt;foo()&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
        &lt;td&gt;2D1F49FE-86DE-4715-BD59-FA70392E41BE&lt;/td&gt;
        &lt;td&gt;bar()&lt;/td&gt;
        &lt;/tr&gt;
        &lt;/tbody&gt;
        &lt;/table&gt;
        &lt;aside class=&quot;admonition info&quot;&gt;
        &lt;p&gt;The semantic web suffers from an admittedly weak software ecosystem.
        While there are dozens of excellent clients for SQL databases,
        you’d be hard-pressed to find much for SPARQL.
        So I was quite pleased to come across
        &lt;a href=&quot;https://github.com/paulovn/sparql-kernel&quot;&gt;this kernel&lt;/a&gt;
        by Paulo Villegas
        that adds SPARQL support to
        &lt;a href=&quot;https://jupyter.org&quot;&gt;Jupyter notebooks&lt;/a&gt;.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;answering-questions-about-your-code&quot; href=&quot;#answering-questions-about-your-code&quot;&gt;&lt;/a&gt;Answering Questions About Your Code&lt;/h3&gt;
        &lt;p&gt;&lt;em&gt;“What can you do with a knowledge graph?”&lt;/em&gt;
        That’s kind of like asking, &lt;em&gt;“What can you do with Swift?”&lt;/em&gt;
        The answer — &lt;em&gt;“Pretty much anything”&lt;/em&gt; — is as true as it is unhelpful.&lt;/p&gt;
        &lt;p&gt;Perhaps a better framing would be to consider the kinds of questions that
        a knowledge graph of code symbols can help answer:&lt;/p&gt;
        &lt;ul&gt;
        &lt;li&gt;Which methods in Foundation produce a &lt;code&gt;Date&lt;/code&gt; value?&lt;/li&gt;
        &lt;li&gt;Which public types in my project &lt;em&gt;don’t&lt;/em&gt; conform to &lt;code&gt;Codable&lt;/code&gt;?&lt;/li&gt;
        &lt;li&gt;Which methods does &lt;code&gt;Array&lt;/code&gt; inherit default implementations from &lt;code&gt;Random&lt;wbr&gt;&lt;/wbr&gt;Access&lt;wbr&gt;&lt;/wbr&gt;Collection&lt;/code&gt;?&lt;/li&gt;
        &lt;li&gt;Which APIs have documentation that includes example code?&lt;/li&gt;
        &lt;li&gt;What are the most important APIs in &lt;code&gt;Map&lt;wbr&gt;&lt;/wbr&gt;Kit&lt;/code&gt;?&lt;/li&gt;
        &lt;li&gt;Are there any unused APIs in my project?&lt;/li&gt;
        &lt;li&gt;What’s the oldest version of iOS that my app could target
        based on my current API usage?&lt;/li&gt;
        &lt;li&gt;What APIs were added to &lt;a href=&quot;https://github.com/Alamofire/Alamofire&quot;&gt;Alamofire&lt;/a&gt; between versions 4.0 and 4.2?&lt;/li&gt;
        &lt;li&gt;What APIs in our app are affected by a CVE issued for a 3rd-party dependency?&lt;/li&gt;
        &lt;/ul&gt;
        &lt;p&gt;The possibilities get even more interesting as you layer additional contexts
        by linking Swift APIs to different domains and other programming languages:&lt;/p&gt;
        &lt;ul&gt;
        &lt;li&gt;How is this Swift API exposed in Objective-C?&lt;/li&gt;
        &lt;li&gt;Who are the developers maintaining the packages
        that are pulled in as external dependencies for this project?&lt;/li&gt;
        &lt;li&gt;What’s the closest functional equivalent to this Swift package
        that’s written in Rust?&lt;/li&gt;
        &lt;/ul&gt;
        &lt;aside class=&quot;admonition info&quot;&gt;
        &lt;p&gt;My pitch for a
        &lt;a href=&quot;https://forums.swift.org/t/swift-package-registry-service/37219/2&quot;&gt;Swift Package Registry Service&lt;/a&gt;
        proposes the use of &lt;a href=&quot;https://en.wikipedia.org/wiki/JSON-LD&quot;&gt;JSON-LD&lt;/a&gt; and the
        &lt;a href=&quot;https://schema.org/SoftwareSourceCode&quot;&gt;Schema.org &lt;code&gt;Software&lt;wbr&gt;&lt;/wbr&gt;Source&lt;wbr&gt;&lt;/wbr&gt;Code&lt;/code&gt;&lt;/a&gt; vocabulary
        as a standard representation for package metadata,
        which could be easily combined with and cross-referenced against
        semantic representations of code.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;future-applications-the-promise-of-what-lies-ahead&quot; href=&quot;#future-applications-the-promise-of-what-lies-ahead&quot;&gt;&lt;/a&gt;&lt;small&gt;Future Applications&lt;/small&gt; The Promise of What Lies Ahead&lt;/h2&gt;
        &lt;blockquote&gt;
        &lt;p&gt;Any fact becomes important when it’s connected to another.&lt;/p&gt;
        &lt;p&gt;&lt;cite&gt;Umberto Eco, &lt;em&gt;Foucault’s Pendulum&lt;/em&gt;&lt;/cite&gt;&lt;/p&gt;
        &lt;/blockquote&gt;
        &lt;p&gt;Operating on code symbolically is more powerful
        than treating it as text.
        Once you’ve experienced proper refactoring tools,
        you’ll never want to go back to global find-and-replace.&lt;/p&gt;
        &lt;p&gt;The leap from symbolic to semantic understanding of code
        promises to be just as powerful.
        What follows are a few examples of potential applications of
        the knowledge graph we’ve described.&lt;/p&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;flexible-search-queries&quot; href=&quot;#flexible-search-queries&quot;&gt;&lt;/a&gt;Flexible Search Queries&lt;/h3&gt;
        &lt;p&gt;GitHub’s &lt;a href=&quot;https://github.com/search/advanced&quot;&gt;advanced search&lt;/a&gt;
        provides an interface to filter results on various
        &lt;a href=&quot;https://www.elastic.co/guide/en/app-search/current/facets-guide.html&quot;&gt;facets&lt;/a&gt;,
        but they’re limited to metadata about the projects.
        You can search for Swift code written by
        &lt;a href=&quot;https://github.com/kateinoigakukun&quot;&gt;&lt;code&gt;@kateinoigakukun&lt;/code&gt;&lt;/a&gt; in 2020,
        but you can’t, for example,
        filter for code compatible with Swift 5.1.
        You can search code for the string “record”,
        but you can’t disambiguate between type and function definitions
        (&lt;code&gt;class Record&lt;/code&gt; vs. &lt;code&gt;func record()&lt;/code&gt;).&lt;/p&gt;
        &lt;p&gt;As we showed earlier,
        the kinds of queries we can perform across a knowledge graph
        are fundamentally different from what’s possible with
        a conventional faceted, full-text search index.&lt;/p&gt;
        &lt;p&gt;For example,
        here’s a SPARQL query to find the urls of repositories
        created by &lt;code&gt;@kateinoigakukun&lt;/code&gt; and updated this year
        that contain Swift functions named &lt;code&gt;record&lt;/code&gt;:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;SPARQL&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;PREFIX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;swift:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;&amp;lt;http://www.swift.org/#&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;skos:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;&amp;lt;http://www.w3.org/2004/02/skos/core/#&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;sdo:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;&amp;lt;http://schema.org/#&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;?url&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;?function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;swift:&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;swift:&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;record&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;skos:&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;?repository&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;?repository&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;sdo:&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Software&lt;wbr&gt;&lt;/wbr&gt;Source&lt;wbr&gt;&lt;/wbr&gt;Code&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;sdo:&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;contributor&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;?contributor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;sdo:&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;?url&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;sdo:&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;date&lt;wbr&gt;&lt;/wbr&gt;Modified&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;?date&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;?contributor&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;sdo:&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;sdo:&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;kateinoigakukun&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;FILTER&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;?date&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;2020-01-01&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ORDER&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;?url&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
        &lt;aside class=&quot;admonition info&quot;&gt;
        &lt;p&gt;Looking for a more grounded example of semantic code search?
        Check out &lt;a href=&quot;https://hoogle.haskell.org&quot;&gt;Hoogle&lt;/a&gt;:
        a Haskell API search engine
        that lets you search for functions by approximate type signature.
        For instance, you can search for
        &lt;a href=&quot;https://hoogle.haskell.org/?hoogle=Ord%20a%20%3D%3E%20%5Ba%5D%20-%3E%20%5Ba%5D&quot;&gt;&lt;code&gt;Ord a =&amp;gt; [a] -&amp;gt; [a]&lt;/code&gt;&lt;/a&gt;,
        (roughly, &lt;code&gt;([T]) -&amp;gt; [T] where T: Comparable&lt;/code&gt; in Swift)
        to find various &lt;code&gt;sort&lt;/code&gt; methods available in the ecosystem.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;linked-documentation&quot; href=&quot;#linked-documentation&quot;&gt;&lt;/a&gt;Linked Documentation&lt;/h3&gt;
        &lt;p&gt;When faced with
        &lt;a href=&quot;https://nooverviewavailable.com&quot;&gt;missing or incomplete documentation&lt;/a&gt;,
        developers are left to search Google for
        blog posts, tutorials, conference videos, and sample code
        to fill in the gaps.
        Often, this means sifting through pages of irrelevant results —
        to say nothing of outdated and incorrect information.&lt;/p&gt;
        &lt;p&gt;A knowledge graph can improve search for documentation
        much the same as it can for code,
        but we can go even further.
        Similar to how academic papers contain citations,
        example code can be annotated to include references to
        the canonical APIs it interacts with.
        Strong connections between references and its source material
        make for easy retrieval later on.&lt;/p&gt;
        &lt;p&gt;Imagine if,
        when you option-click on an API in Xcode
        to get its documentation,
        you also saw a list of sample code and WWDC session videos?
        Or what if we could generate sample code automatically from test cases?
        Wouldn’t that be nice?&lt;/p&gt;
        &lt;p&gt;All of that information is out there,
        just waiting for us to connect the dots.&lt;/p&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;automatic-dependencies&quot; href=&quot;#automatic-dependencies&quot;&gt;&lt;/a&gt;Automatic µDependencies&lt;/h3&gt;
        &lt;p&gt;John D. Cook once
        &lt;a href=&quot;https://www.johndcook.com/blog/2011/02/03/lego-blocks-and-organ-transplants/&quot;&gt;observed&lt;/a&gt;,
        code reuse is more like an organ transplant
        than snapping LEGO blocks together.
        Fred Brooks similarly analogized software developers to surgeons in
        &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Mythical_Man-Month&quot;&gt;&lt;em&gt;The Mythical Man-Month&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
        &lt;p&gt;But that’s not to say that things can’t get better —
        it’d be hard to argue that they haven’t.&lt;/p&gt;
        &lt;p&gt;Web applications were once described in similar, organic terms,
        but that came to an end with the advent of
        &lt;a href=&quot;https://en.wikipedia.org/wiki/OS-level_virtualization&quot;&gt;containerization&lt;/a&gt;.
        Now you can orchestrate entire multi-cloud deployments automatically
        via declarative configuration files.&lt;/p&gt;
        &lt;p&gt;Before &lt;abbr title=&quot;Comprehensive Perl Archive Network&quot;&gt;&lt;a href=&quot;https://www.cpan.org/&quot;&gt;CPAN&lt;/a&gt;&lt;/abbr&gt;,
        the state of the art for dependency management
        was copy-pasting chunks of code
        &lt;a href=&quot;https://en.wikipedia.org/wiki/Matt%27s_Script_Archive&quot;&gt;you found on a web page&lt;/a&gt;.
        But today, package managers are essential infrastructure for projects.&lt;/p&gt;
        &lt;hr&gt;
        &lt;p&gt;What if,
        instead of organizing code into self-contained, modular chunks ourselves,
        we let software do it for us?
        Call it
        &lt;abbr title=&quot;Functions as a Dependency&quot;&gt;FaaD&lt;/abbr&gt; (Functions as a Dependency).&lt;/p&gt;
        &lt;p&gt;Say you want an implementation of
        &lt;a href=&quot;https://en.wikipedia.org/wiki/K-means_clustering&quot;&gt;&lt;em&gt;k&lt;/em&gt;-means clustering&lt;/a&gt;.
        You might search around for “k-means” or “clustering” on GitHub
        and find a package named “SwiftyClusterAlgorithms” (😒),
        only to discover that it includes a bunch of functionality that you don’t need —
        and to add insult to injury,
        some of those extra bits happen to generate compiler warnings.
        Super annoying.&lt;/p&gt;
        &lt;aside class=&quot;parenthetical&quot;&gt;
        &lt;p&gt;For the record,
        &lt;a href=&quot;https://github.com/NSHipster/DBSCAN&quot;&gt;&lt;abbr title=&quot;Density-Based Spatial Clustering of Applications with Noise&quot;&gt;DBSCAN&lt;/abbr&gt;&lt;/a&gt;
        is way better than &lt;em&gt;k&lt;/em&gt;-means for most distributions.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;Today, there’s no automatic way to pick and choose what you need.
        (&lt;a href=&quot;/import/&quot;&gt;Swift &lt;code&gt;import&lt;/code&gt; syntax&lt;/a&gt; (&lt;code&gt;import func k&lt;wbr&gt;&lt;/wbr&gt;Means&lt;/code&gt;) is a lie)
        But there’s no inherent reason why the compiler couldn’t do this for you.&lt;/p&gt;
        &lt;p&gt;Or to go even further:
        If everything compiles down to &lt;a href=&quot;https://swiftwasm.org&quot;&gt;web assembly&lt;/a&gt;,
        there’s no inherent requirement for that implementation of &lt;em&gt;k&lt;/em&gt;-means —
        it could be written in Rust or JavaScript,
        and you’d be none the wiser.&lt;/p&gt;
        &lt;p&gt;At a certain point,
        you start to question the inherent necessity of software packaging
        as we know it today.
        Take it far enough,
        and you may wonder how much code we’ll write ourselves in the future.&lt;/p&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;code-generation&quot; href=&quot;#code-generation&quot;&gt;&lt;/a&gt;Code Generation&lt;/h3&gt;
        &lt;p&gt;A few months ago,
        Microsoft hosted its &lt;a href=&quot;https://mybuild.microsoft.com&quot;&gt;Build&lt;/a&gt; conference.
        And among the videos presented was an interview with
        &lt;a href=&quot;https://en.wikipedia.org/wiki/Sam_Altman&quot;&gt;Sam Altman&lt;/a&gt;,
        CEO of &lt;a href=&quot;https://openai.com/&quot;&gt;OpenAI&lt;/a&gt;.
        A few minutes in,
        the interview cut to a video of Sam using
        a fine-tuned version of
        &lt;a href=&quot;https://openai.com/blog/gpt-2-1-5b-release/&quot;&gt;GPT-2&lt;/a&gt;
        to
        &lt;a href=&quot;https://www.pscp.tv/Microsoft/1OyKAYWPRrWKb?t=27m1s&quot;&gt;write Python code from docstrings&lt;/a&gt;.&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Python&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;is_palindrome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Check whether a string is a palindrome&quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[::&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# ← Generated by AI model from docstring!
        &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;And that’s using a model that treats code as text.
        Imagine how far you could go with &lt;em&gt;a priori&lt;/em&gt; knowledge of programming languages!
        Unlike English, the rules of code are, well, codified.
        You can check to see if code compiles —
        and if it does compile,
        you can run it to see the results.&lt;/p&gt;
        &lt;aside class=&quot;admonition info&quot;&gt;
        &lt;p&gt;And that’s GPT-2.
        &lt;a href=&quot;https://www.gwern.net/GPT-3&quot;&gt;GPT-3&lt;/a&gt; is even more impressive.
        For your consideration,
        here’s what the model generated
        when prompted to write a parody of the
        &lt;a href=&quot;https://knowyourmeme.com/memes/navy-seal-copypasta&quot;&gt;Navy Seal copypasta meme&lt;/a&gt;
        relating to
        &lt;a href=&quot;https://en.wikipedia.org/wiki/Philosophy_of_mathematics#Platonism&quot;&gt;mathematical platonism&lt;/a&gt;:&lt;/p&gt;
        &lt;blockquote&gt;
        &lt;p&gt;What in set theory did you just write about me,
        you ignorant little inductivist?
        I’ll have you know I am a professor at the University of Chicago
        and I have been involved in numerous secret raids on the office of Quine,
        and I have over 300 confirmed set theoreticians. […]&lt;/p&gt;
        &lt;/blockquote&gt;
        &lt;/aside&gt;
        &lt;p&gt;At this point,
        you should feel either very worried or very excited. &lt;br&gt;
        If you don’t, then you’re not paying attention.&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;taking-ideas-seriously-the-shoemakers-children&quot; href=&quot;#taking-ideas-seriously-the-shoemakers-children&quot;&gt;&lt;/a&gt;&lt;small&gt;Taking Ideas Seriously&lt;/small&gt; The Shoemaker’s Children&lt;/h2&gt;
        &lt;blockquote&gt;
        &lt;p&gt;The use of &lt;abbr&gt;FORTRAN&lt;/abbr&gt;,
        like the earlier symbolic programming,
        was very slow to be taken up by the professionals.
        And this is typical of almost all professional groups.
        Doctors clearly do not follow the advice they give to others,
        and they also have a high proportion of drug addicts.
        Lawyers often do not leave decent wills when they die.
        Almost all professionals are slow to use their own expertise for their own work.
        The situation is nicely summarized by the old saying,
        “The shoe maker’s children go without shoes”.
        Consider how in the future, when you are a great expert,
        you will avoid this typical error!&lt;/p&gt;
        &lt;p&gt;&lt;cite&gt;Richard W. Hamming, &lt;a href=&quot;https://press.stripe.com/#the-art-of-doing-science-and-engineering&quot;&gt;&lt;em&gt;“The Art of Doing Science and Engineering”&lt;/em&gt;&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
        &lt;/blockquote&gt;
        &lt;p&gt;Today,
        lawyers delegate many paralegal tasks like document discovery to computers
        and
        doctors routinely use machine learning models to help diagnose patients.&lt;/p&gt;
        &lt;p&gt;So why aren’t we —
        &lt;em&gt;ostensibly the people writing software&lt;/em&gt; —
        doing more with AI in our day-to-day?
        Why are things like
        &lt;a href=&quot;https://www.tabnine.com&quot;&gt;TabNine&lt;/a&gt; and
        &lt;a href=&quot;https://kite.com&quot;&gt;Kite&lt;/a&gt;
        so often seen as curiosities instead of game-changers?&lt;/p&gt;
        &lt;p&gt;If you take seriously the idea that
        &lt;abbr title=&quot;artificial intelligence&quot;&gt;AI&lt;/abbr&gt;
        will fundamentally change the nature of many occupations in the coming decade,
        what reason do you have to believe that you’ll be immune from that
        because you work in software?
        Looking at the code you’ve been paid to write over the past few years,
        how much of that can you honestly say is truly novel?&lt;/p&gt;
        &lt;p&gt;We’re really not as clever as we think we are.&lt;/p&gt;
        &lt;hr&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;postscript-reflection-and-metaprogramming&quot; href=&quot;#postscript-reflection-and-metaprogramming&quot;&gt;&lt;/a&gt;&lt;small&gt;Postscript&lt;/small&gt; Reflection and Metaprogramming&lt;/h2&gt;
        &lt;p&gt;Today marks 8 years since I started NSHipster.&lt;/p&gt;
        &lt;p&gt;You might’ve noticed that I don’t write here as much as I once did.
        And on the occasions that I do publish an article,
        it’s more likely to include obscure
        &lt;a href=&quot;/swift-log/&quot;&gt;historical facts&lt;/a&gt; and
        &lt;a href=&quot;/timeinterval-date-dateinterval/&quot;&gt;cultural references&lt;/a&gt;
        than to the &lt;a href=&quot;/cfbag/&quot;&gt;obscure APIs&lt;/a&gt; promised by this blog’s tagline.&lt;/p&gt;
        &lt;p&gt;A few weeks out now from &lt;a href=&quot;/wwdc-2020&quot;&gt;WWDC&lt;/a&gt;,
        I &lt;em&gt;should&lt;/em&gt; be writing about
        &lt;a href=&quot;https://developer.apple.com/documentation/devicecheck/dcappattestservice&quot;&gt;&lt;code&gt;DCApp&lt;wbr&gt;&lt;/wbr&gt;Attest&lt;wbr&gt;&lt;/wbr&gt;Service&lt;/code&gt;&lt;/a&gt;,
        &lt;a href=&quot;https://developer.apple.com/documentation/storekittest/sktestsession&quot;&gt;&lt;code&gt;SKTest&lt;wbr&gt;&lt;/wbr&gt;Session&lt;/code&gt;&lt;/a&gt;,
        SwiftUI &lt;a href=&quot;https://developer.apple.com/documentation/swiftui/namespace&quot;&gt;&lt;code&gt;Namespace&lt;/code&gt;&lt;/a&gt;
        and
        &lt;a href=&quot;https://developer.apple.com/documentation/uniformtypeidentifiers/uttype&quot;&gt;&lt;code&gt;UTType&lt;/code&gt;&lt;/a&gt;.
        But here we are,
        at the end of an article about the semantic web, of all things…&lt;/p&gt;
        &lt;hr&gt;
        &lt;p&gt;The truth is,
        I’ve come around to thinking that
        programming isn’t the most important thing
        for programmers to pay attention to right now.&lt;/p&gt;
        &lt;hr&gt;
        &lt;p&gt;Anyway,
        I’d like to take this opportunity to extend my sincere gratitude
        to everyone who reads the words I write.
        Thank you.
        It may be a while before I get back into a regular cadence,
        so apologies in advance.&lt;/p&gt;
        &lt;p&gt;Until next time,
        &lt;em&gt;May your code continue to compile and inspire.&lt;/em&gt;&lt;/p&gt;
        &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;/assets/articles/as-we-may-code-a97159d31c2433baae69c5a7df23d0ee88baafddda1583f6b487850b17c4e6596b831fefad9428fb2b5dda11eb3a98fc8d68809c3ac3f7706f6bf584503ff294.css&quot; integrity=&quot;sha512-qXFZ0xwkM7quacWn3yPQ7oi6r93aFYP2tIeFCxfE5llrgx/vrZQo+ytd2hHrOpj8jWiAnDrD93Bva/WEUD/ylA==&quot; crossorigin=&quot;anonymous&quot;&gt;
      </content>
      <author>
        <name>Mattt</name>
        <email>mattt@nshipster.com</email>
        <uri>https://nshipster.com/authors/mattt/</uri>
      </author>
      <category term="Miscellaneous" />
      <summary type="html">&lt;p&gt;What if, instead of lowering source code down for the purpose of execution, we raised it for the purpose of understanding?&lt;/p&gt;</summary>
    </entry>
    <entry>
      <title type="html">WWDC 2020</title>
      <link href="https://nshipster.com/wwdc-2020/" rel="alternate" type="text/html" title="WWDC 2020" />
      <published>2020-06-26T00:00:00-07:00</published>
      <updated>2020-06-26T00:00:00-07:00</updated>
      <id>https://nshipster.com/wwdc-2020</id>
      <content type="html" xml:base="https://nshipster.com/wwdc-2020/">
        &lt;p&gt;Like everything else in 2020,
        this year’s WWDC had to be a little different
        if it was going to happen at all.&lt;/p&gt;
        &lt;p&gt;When Apple first announced that the conference would be fully remote,
        nobody knew what that would look like, exactly.
        What parts of the dubdub experience would be kept in this new format?
        What details would be lost in translation?
        Could they actually pull it off?&lt;/p&gt;
        &lt;aside class=&quot;admonition info&quot;&gt;
        &lt;p&gt;For context:
        Apple live-streamed its first keynote in 2013,
        and technical sessions in 2015.
        Attendees of &lt;a href=&quot;http://bslabs.net/2018/05/28/wwdc-1997-videos/&quot;&gt;WWDC 1997&lt;/a&gt; could obtain a collection of CDs
        with video recordings of sessions —
        a far cry from the VHS tape for &lt;a href=&quot;http://bslabs.net/2020/06/19/wwdc-1990/&quot;&gt;WWDC 1990&lt;/a&gt;.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;As it turns out,
        going fully remote wasn’t merely good enough —
        it was, in many ways, superior to the original thing.
        There’s a lot to like about the new format.&lt;/p&gt;
        &lt;p&gt;The videos are well-produced,
        and let each presenter’s personality really shine.
        Everybody looks and sounds great.&lt;/p&gt;
        &lt;p&gt;Sessions are tight and well-paced.
        Rather than stretching or cramming content into a fixed time slot,
        they’re as long as they need to be.
        And thanks to this more digestible format,
        we’re starting to see WWDC clips being shared around,
        which is new and refreshing.&lt;/p&gt;
        &lt;p&gt;To be honest,
        it’s hard to imagine ever going back to a physical conference.&lt;/p&gt;
        &lt;p&gt;However,
        as someone who had the privilege of attending WWDC in years past,
        there are things I’m going to miss
        (and some that I decidedly won’t).&lt;/p&gt;
        &lt;table&gt;
        &lt;thead&gt;
        &lt;tr&gt;
        &lt;th&gt;🥰&lt;/th&gt;
        &lt;th&gt;😫&lt;/th&gt;
        &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
        &lt;tr&gt;
        &lt;td&gt;Refrigerators stocked with Odwalla smoothies&lt;/td&gt;
        &lt;td&gt;Trying to download the latest Xcode beta over hotel internet&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
        &lt;td&gt;Lunchtime sessions&lt;/td&gt;
        &lt;td&gt;Eating lunch at or around Moscone&lt;/td&gt; 
        &lt;/tr&gt;
        &lt;tr&gt;
        &lt;td&gt;WWDC track jackets saving the lives of first-time attendees from the cold of San Francisco summer&lt;/td&gt;
        &lt;td&gt;Being in San Francisco, generally&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
        &lt;td&gt;Eating burritos on the terrace of McEnery Convention Center during WWDC check-in&lt;/td&gt;
        &lt;td&gt;Being in San Jose, generally&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
        &lt;td&gt;Guessing who would be playing at Bash this year&lt;/td&gt;
        &lt;td&gt;Hearing the same handful of songs on repeat before and after every session
        (&lt;a href=&quot;https://music.apple.com/us/album/animal/1471689800?i=1471689803&quot;&gt;this song&lt;/a&gt; in particular) &lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
        &lt;td colspan=&quot;2&quot;&gt;
        &lt;details&gt;
        &lt;summary&gt;Watching Apple executives dance at Bash&lt;/summary&gt;
        &lt;video preload=&quot;none&quot; width=&quot;636&quot; height=&quot;290&quot; controls&gt;
        &lt;source src=&quot;/assets/wwdc-2020-apple-executives-dancing-0c9034cf315cc9c4db419df4f1320c78b4711b10bd537eb8654aa3a1b4b93a9e364eb4967f4d20ad5ff5ccdea013421d86a0d515914c373ec3f5a99e5701f7a2.mp4&quot; type=&quot;video/mp4&quot;&gt;&lt;/source&gt;
        &lt;/video&gt;
        &lt;/details&gt;
        &lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
        &lt;td&gt;Talking to people as you wait in line for the keynote on Monday morning&lt;/td&gt;
        &lt;td&gt;Waking up late and having to settle for watching from the overflow room&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
        &lt;td&gt;Leaving at the end of the week with a mix of hope, fear, and inspiration &lt;sup&gt;*&lt;/sup&gt;
        &lt;/td&gt;
        &lt;td&gt;Being sick for the next week with dubdub flu&lt;/td&gt;
        &lt;/tr&gt;
        &lt;/tbody&gt;
        &lt;/table&gt;
        &lt;p&gt;&lt;sup&gt;*&lt;/sup&gt; I’d like to hold on this last point for a moment.&lt;/p&gt;
        &lt;p&gt;&lt;br&gt;&lt;/p&gt;
        &lt;p&gt;In the &lt;em&gt;Before Times&lt;/em&gt;,
        many of us traveled far from home to attend WWDC.
        There was a physical and temporal delineation
        between life before, during, and after the conference.
        Flying out of &lt;abbr&gt;SFO&lt;/abbr&gt;, &lt;abbr&gt;SJC&lt;/abbr&gt;, or &lt;abbr&gt;OAK&lt;/abbr&gt;,
        you escaped Apple’s &lt;a href=&quot;https://www.folklore.org/StoryView.py?story=Reality_Distortion_Field.txt&quot;&gt;“reality distortion field”&lt;/a&gt; 
        and its surrounding echo chamber.
        You returned to your normal life.&lt;/p&gt;
        &lt;p&gt;This year? Not so much.&lt;/p&gt;
        &lt;p&gt;WWDC 2020 was just another week in this bizarre existence amidst this pandemic.
        Not only is there no escape from the “reality distortion field”,
        there isn’t even a “normal life” for us to leave or return to.&lt;/p&gt;
        &lt;p&gt;So here we are,
        filled with anxious excitement and fear;
        our corporeal forms replaced by
        Memoji floating in a black, digital void
        lit only by the screens of our soon-to-be-obsolete MacBooks Pro.&lt;/p&gt;
        &lt;p&gt;&lt;img integrity=&quot;sha512-I2dXY3s8DjGgFFzXCHXgO3/jP5FAjcZ5dTkuqY5CRU7r8T6yfBY95C0ImwaUp/zL3m2guSMIWObMxGKC5Ry/kA==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/wwdc-2020-banner-236757637b3c0e31a0145cd70875e03b7fe33f91408dc67975392ea98e42454eebf13eb27c163de42d089b0694a7fccbde6da0b9230858e6ccc46282e51cbf90.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
        &lt;hr&gt;&lt;a id=&quot;get-on-with-it&quot;&gt;&lt;/a&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;excitement&quot; href=&quot;#excitement&quot;&gt;&lt;/a&gt;Excitement&lt;/h2&gt;
        &lt;p&gt;I don’t have a real sense of how everything went over this year.
        There wasn’t any applause (or heckling) at this year’s keynote
        to gauge the temperature in the room.
        There were no parties to overhear shop talk and hot takes.
        There was no line for lunch
        to make small talk with a fellow attendee.&lt;/p&gt;
        &lt;p&gt;But if &lt;a href=&quot;https://twitter.com/hashtag/WWDC20&quot;&gt;Twitter&lt;/a&gt; is anything to go on,
        my overall impression is that everyone is really &lt;em&gt;excited&lt;/em&gt;.&lt;/p&gt;
        &lt;p&gt;Which is fine. I get it.&lt;/p&gt;
        &lt;p&gt;But it should come as no surprise that things announced at WWDC are exciting —
        that’s the whole point of having a developer conference in the first place.
        Apple has the best marketing in the world,
        and WWDC is Apple’s way of marketing to us.&lt;/p&gt;
        &lt;p&gt;Here’s the thing about excitement:
        It’s kryptonite to developers.&lt;/p&gt;
        &lt;p&gt;Excitement messes with our ability to focus on one thing,
        which is already a big struggle for a lot of us (myself included).
        When you’re excited,
        it’s almost impossible to get anything done.&lt;/p&gt;
        &lt;p&gt;There are plenty of voices in the community who are echoing this excitement.
        I can’t add anything to that discussion.
        And besides,
        that’s not really where my head’s at right now.&lt;/p&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;trivial-pursuit&quot; href=&quot;#trivial-pursuit&quot;&gt;&lt;/a&gt;Trivial Pursuit&lt;/h3&gt;
        &lt;p&gt;I briefly considered reviving the &lt;a href=&quot;/nshipster-quiz-2/&quot;&gt;NSHipster Quiz&lt;/a&gt;
        for WWDC 2020,
        but it didn’t feel right.
        With everything going on in the world,
        Apple trivia just isn’t where my head or heart are right now.&lt;/p&gt;
        &lt;p&gt;To give you a sense of what I mean, here’s what I had for Round 3,
        whose theme was inspired by &lt;a href=&quot;https://www.cs.virginia.edu/~robins/YouAndYourResearch.html&quot;&gt;Richard Hamming&lt;/a&gt;:&lt;/p&gt;
        &lt;dl&gt;
        &lt;dt&gt;&lt;strong&gt;Question 1.&lt;/strong&gt;&lt;/dt&gt;
        &lt;dd&gt;What are the important problems of your field?&lt;/dd&gt;
        &lt;dt&gt;&lt;strong&gt;Question 2.&lt;/strong&gt;&lt;/dt&gt;
        &lt;dd&gt;What important problems are you working on?&lt;/dd&gt;
        &lt;dt&gt;&lt;strong&gt;Question 3.&lt;/strong&gt;&lt;/dt&gt;
        &lt;dd&gt;If what you are doing is not important,
        why are working on it?&lt;/dd&gt;
        &lt;/dl&gt;
        &lt;aside class=&quot;parenthetical&quot;&gt;
        &lt;p&gt;I think I made the right call by not doing a quiz this year.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;temperance&quot; href=&quot;#temperance&quot;&gt;&lt;/a&gt;Temperance&lt;/h2&gt;
        &lt;p&gt;If you’re serious about solving a problem,
        you owe it to yourself to temper any excitement
        that distracts you from making real progress.&lt;/p&gt;
        &lt;p&gt;In last year’s write-up for &lt;a href=&quot;/wwdc-2019/&quot;&gt;WWDC 2019&lt;/a&gt;,
        I concluded with the following,
        as a counterpoint to the conference’s theme of &lt;code&gt;#mindblown&lt;/code&gt; 🤯:&lt;/p&gt;
        &lt;blockquote&gt;
        &lt;p&gt;Taking care of yourself —
        sleeping enough, eating right, exercising regularly —
        will do more to improve your productivity
        than any language or framework out there.
        Your ability to communicate and collaborate with others
        will always be a better predictor of success
        than your choice of technology stack.
        Your relationships with others
        are the most significant factors of success and happiness in life.&lt;/p&gt;
        &lt;/blockquote&gt;
        &lt;p&gt;I stand by this advice, boring as it may be.&lt;/p&gt;
        &lt;p&gt;It’s been an exciting week,
        so take a moment to collect yourself.
        Go on a walk. Take a hike. (Be safe about it.)
        Do whatever you need to break free of the “reality distortion field”.
        Once you do, you’ll have the necessary distance to determine
        what new technologies you should pay attention to
        and what you can ignore for now.&lt;/p&gt;
        &lt;p&gt;We have a lot of work ahead of us.&lt;/p&gt;
        &lt;script integrity=&quot;sha512-lL08byJz4k6KCzOy1FWI4xfzMFgVCpw02QmuIF1ERt8ysz/BQRFlQeDFjRFBk7MFwx4/frh6kejFvTa4JXAr+g==&quot; crossorigin=&quot;anonymous&quot; type=&quot;text/javascript&quot; src=&quot;/assets/articles/wwdc-2020-94bd3c6f2273e24e8a0b33b2d45588e317f33058150a9c34d909ae205d4446df32b33fc141116541e0c58d114193b305c31e3f7eb87a91e8c5bd36b825702bfa.js&quot;&gt;&lt;/script&gt;
      </content>
      <author>
        <name>Mattt</name>
        <email>mattt@nshipster.com</email>
        <uri>https://nshipster.com/authors/mattt/</uri>
      </author>
      <category term="Miscellaneous" />
      <summary type="html">&lt;p&gt;A brief remark about the excitement of Apple’s annual developer conference.&lt;/p&gt;</summary>
    </entry>
    <entry>
      <title type="html">Language Server Protocol</title>
      <link href="https://nshipster.com/language-server-protocol/" rel="alternate" type="text/html" title="Language Server Protocol" />
      <published>2018-11-05T00:00:00-08:00</published>
      <updated>2020-05-07T00:00:00-07:00</updated>
      <id>https://nshipster.com/language-server-protocol</id>
      <content type="html" xml:base="https://nshipster.com/language-server-protocol/">
        &lt;p&gt;In October 2018,
        Apple &lt;a href=&quot;https://forums.swift.org/t/new-lsp-language-service-supporting-swift-and-c-family-languages-for-any-editor-and-platform/17024&quot;&gt;announced on the Swift.org forums&lt;/a&gt;
        that it was starting work to adopt
        the &lt;a href=&quot;https://microsoft.github.io/language-server-protocol/&quot;&gt;Language Server Protocol&lt;/a&gt;
        (&lt;abbr title=&quot;Language Server Protocol&quot;&gt;LSP&lt;/abbr&gt;)
        for Swift and C languages.&lt;/p&gt;
        &lt;blockquote&gt;
        &lt;p&gt;At Apple we are making it a priority
        to support high-quality tooling for all Swift developers,
        including those working on non-Apple platforms.
        We want to collaborate with the open-source community
        and focus our efforts on building common infrastructure
        that can be shared by Xcode and other editors and platforms.
        To that end, [ … ] we’ve chosen to adopt LSP.&lt;/p&gt;
        &lt;p&gt;&lt;cite&gt;Argyrios Kyrtzidis, October 15&lt;sup&gt;th&lt;/sup&gt;, 2018&lt;/cite&gt;&lt;/p&gt;
        &lt;/blockquote&gt;
        &lt;p&gt;&lt;strong&gt;This is arguably the most important decision Apple has made for Swift
        since releasing the language as open source in 2014.&lt;/strong&gt;
        It’s a big deal for app developers,
        and it’s an even bigger deal for Swift developers on other platforms.&lt;/p&gt;
        &lt;p&gt;To understand why,
        this week’s article will take a look at
        what problem the Language Server Protocol solves,
        how it works,
        and what its long-term impacts may be.&lt;/p&gt;
        &lt;aside class=&quot;admonition info&quot;&gt;
        &lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;:
        GitHub recently announced
        &lt;a href=&quot;https://github.com/features/codespaces/&quot;&gt;Codespaces&lt;/a&gt;,
        an upcoming feature that promises
        &lt;em&gt;“the full Visual Studio Code experience without leaving GitHub”&lt;/em&gt;.
        Thanks to Swift’s support for LSP,
        we’ll soon be able to edit Swift code —
        syntax highlighting, autocompletion, and all —
        directly from the browser.&lt;/p&gt;
        &lt;p&gt;Why wait for the
        &lt;a href=&quot;https://twitter.com/jon_prosser/status/1252187152831692800&quot;&gt;rumored&lt;/a&gt;
        announcement of Xcode for iPad at &lt;a href=&quot;https://developer.apple.com/wwdc20/&quot;&gt;WWDC&lt;/a&gt;?
        Codespaces turns any iPad into a
        &lt;a href=&quot;https://twitter.com/notdetails/status/1258120708212785154&quot;&gt;full-fledged development environment&lt;/a&gt;!&lt;/p&gt;
        &lt;/aside&gt;
        &lt;hr&gt;&lt;a id=&quot;get-on-with-it&quot;&gt;&lt;/a&gt;
        &lt;p&gt;Imagine a grid
        with each row representing a different programming language
        (Swift, JavaScript, Ruby, Python, etc.)
        and each column representing a different code editor
        (Xcode, Visual Studio, Vim, Atom, etc.),
        such that each cell represents
        the level of support that a particular editor has for a language.&lt;/p&gt;
        &lt;p&gt;&lt;img integrity=&quot;sha512-4wzxpi6l262BRXI+F+ihdxbzJeWPpUPFWcXm2MJUh91Wofig4KZymcaSf7Twl9wPj4A6qQiRRU+OmqGpI4b5kg==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/lsp-languages-times-editors-e30cf1a62ea5dbad8145723e17e8a17716f325e58fa543c559c5e6d8c25487dd56a1f8a0e0a67299c6927fb4f097dc0f8f803aa90891454f8e9aa1a92386f992.svg&quot; role=&quot;img&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
        &lt;p&gt;Up until recently,
        what you’d find was a patchwork of compatibility
        across the various combinations.
        Some editors offered deep integration with a few languages
        and little to no support for anything else,
        whereas other editors aimed to be general-purpose
        with at least a modicum of support for many languages.
        (The term &lt;abbr title=&quot;Integrated Development Environment&quot;&gt;IDE&lt;/abbr&gt;
        is often used to describe the former.)&lt;/p&gt;
        &lt;p&gt;Case in point:
        &lt;em&gt;You’d be stubborn not to use Xcode for app development
        and foolish to use it for anything else.&lt;/em&gt;&lt;/p&gt;
        &lt;p&gt;For an editor to have better support for a particular language,
        it needs to write integration code —
        either directly in the code base or via a plugin system.
        Due to implementation differences across languages and editors,
        improvements to, say,
        Ruby support in Vim
        wouldn’t translate into better support for Python,
        nor could they be applied to make Ruby work better in Atom.
        The end result: inconsistent support across technologies
        and a lot of wasted effort.&lt;/p&gt;
        &lt;p&gt;The situation we described
        is often referred to as an &lt;dfn&gt;M × N problem&lt;/dfn&gt;,
        where the number of integrations is the &lt;em&gt;product&lt;/em&gt; of
        &lt;code&gt;M&lt;/code&gt; editors and &lt;code&gt;N&lt;/code&gt; languages.
        What the Language Server Protocol does is change this M × N problem
        into a &lt;dfn&gt;M + N problem&lt;/dfn&gt;.&lt;/p&gt;
        &lt;p&gt;Rather than an editor having to implement support for each language,
        it only needs to support the LSP.
        And in doing so, it gets the same level of functionality
        for all languages that support the LSP.&lt;/p&gt;
        &lt;p&gt;&lt;img integrity=&quot;sha512-C/5Q7ZGL4DPRDUg3yQ0vaXpWOVlQGIrL3M3eaPQtZ/EmgoppX84xtQ9B+5LdvZkUIvk77kR+l8X5IUUxwueAiQ==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/lsp-languages-plus-editors-0bfe50ed918be033d10d4837c90d2f697a56395950188acbdccdde68f42d67f126828a695fce31b50f41fb92ddbd991422f93bee447e97c5f9214531c2e78089.svg&quot; role=&quot;img&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
        &lt;aside class=&quot;admonition info&quot;&gt;
        &lt;p&gt;An essay from 2010 by Tomohiro Matsuyama
        entitled &lt;a href=&quot;https://tkf.github.io/2013/06/04/Emacs-is-dead.html&quot;&gt;“Emacs は死んだ” (&lt;em&gt;“Emacs is Dead”&lt;/em&gt;)&lt;/a&gt;
        offers a nice encapsulation of this problem.
        Describing the limitations of Emacs’ scripting language
        (no multi-threading, few low-level APIs, and a small user base)
        Matsuyama argues that the preferred approach to writing a plugin
        should be to interface with an external program
        rather than implement something natively.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;Language Server Protocol provides a common set of functionality
        for supported languages, including:&lt;/p&gt;
        &lt;ul&gt;
        &lt;li&gt;Syntax Highlighting&lt;/li&gt;
        &lt;li&gt;Automatic Formatting&lt;/li&gt;
        &lt;li&gt;Autocomplete&lt;/li&gt;
        &lt;li&gt;Syntax&lt;/li&gt;
        &lt;li&gt;Tooltips&lt;/li&gt;
        &lt;li&gt;Inline Diagnostics&lt;/li&gt;
        &lt;li&gt;Jump to Definition&lt;/li&gt;
        &lt;li&gt;Find References in Project&lt;/li&gt;
        &lt;li&gt;Advanced Text and Symbol Search&lt;/li&gt;
        &lt;/ul&gt;
        &lt;p&gt;Rather than reinventing the wheel for each new technology,
        tools and editors can invest in better usability
        and more advanced functionality.&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;how-language-server-protocol-works&quot; href=&quot;#how-language-server-protocol-works&quot;&gt;&lt;/a&gt;How Language Server Protocol Works&lt;/h2&gt;
        &lt;p&gt;If you’re an iOS developer,
        you may be most familiar with
        the terms &lt;dfn&gt;server&lt;/dfn&gt; and &lt;dfn&gt;protocol&lt;/dfn&gt;
        in the sense of communicating with web applications
        in JSON format via HTTP.
        This actually isn’t too far off from how the Language Server Protocol works.&lt;/p&gt;
        &lt;p&gt;In the case of LSP,
        the &lt;em&gt;client&lt;/em&gt; refers to the editor —
        or more generally, the tool —
        and the &lt;em&gt;server&lt;/em&gt; refers to
        an external program run locally in a separate process.&lt;/p&gt;
        &lt;p&gt;As for the &lt;em&gt;protocol&lt;/em&gt; itself,
        LSP resembles a simplified version of HTTP:&lt;/p&gt;
        &lt;ul&gt;
        &lt;li&gt;Each message consists of
        a header part and a content part.&lt;/li&gt;
        &lt;li&gt;The header part has a required &lt;code&gt;Content-Length&lt;/code&gt; field
        containing the size of the content part in bytes,
        and an optional &lt;code&gt;Content-Type&lt;/code&gt; field
        (&lt;code&gt;application/vscode-jsonrpc; charset=utf-8&lt;/code&gt; by default)&lt;/li&gt;
        &lt;li&gt;The content part uses &lt;a href=&quot;https://www.jsonrpc.org/specification&quot;&gt;JSON-RPC&lt;/a&gt;
        to describe the structure of requests, responses, and notifications.&lt;/li&gt;
        &lt;/ul&gt;
        &lt;p&gt;Whenever something happens in the tool,
        such as the user jumping to the definition of a symbol,
        the tool sends a request to the server.
        The server receives that request
        and then returns an appropriate response.&lt;/p&gt;
        &lt;p&gt;For example,
        imagine that a user opens the following Swift code
        in an Xcode-like editor that supported the Language Server Protocol:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Parent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Child&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Parent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
        &lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;When the user &lt;kbd&gt;⌘&lt;/kbd&gt;-clicks the symbol &lt;code&gt;Parent&lt;/code&gt;
        in the inheritance clause on line 2,
        the editor jumps to the definition of the &lt;code&gt;Parent&lt;/code&gt; class on line 1.&lt;/p&gt;
        &lt;p&gt;&lt;img integrity=&quot;sha512-grTRHUOEJlbkFDJUA0vLNNDQZkXIJrXagzswke58mF1DCvMT6tVwYN3zoMJ6QlBV3Kkm0nBA1HPWyy+KeoDumw==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/lsp-jump-to-definition-82b4d11d43842656e4143254034bcb34d0d06645c826b5da833b3091ee7c985d430af313ead57060ddf3a0c27a425055dca926d27040d473d6cb2f8a7a80ee9b.gif&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
        &lt;p&gt;Here’s how LSP enables this interaction behind the scenes:&lt;/p&gt;
        &lt;p&gt;First,
        when the user opens the Swift code,
        the editor launches its Swift language server in a separate process,
        if it isn’t running already,
        and performs any additional setup.&lt;/p&gt;
        &lt;p&gt;When the user executes the “jump to definition” command,
        the editor sends the following request to its Swift language server:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;JSON&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;jsonrpc&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;2.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;method&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;text&lt;wbr&gt;&lt;/wbr&gt;Document/definition&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;params&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;text&lt;wbr&gt;&lt;/wbr&gt;Document&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;uri&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;file:///Users/NSHipster/Example.swift&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;position&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;line&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;character&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;Upon receiving this request,
        the Swift language server uses a compiler tool like
        &lt;a href=&quot;https://github.com/apple/swift/tree/master/tools/SourceKit&quot;&gt;SourceKit&lt;/a&gt;
        to identify the corresponding code entity
        and find the location of its declaration on the preceding line.
        The language server then responds with the following message:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;JSON&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;jsonrpc&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;2.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;result&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;uri&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;file:///Users/NSHipster/Example.swift&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;range&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;start&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;line&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;character&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;end&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;line&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;character&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;Finally,
        the editor navigates to the file
        (which, in this case, is already open),
        moves the cursor to that range,
        and highlights the token.&lt;/p&gt;
        &lt;p&gt;The beauty of this approach is that the editor did all of this
        without knowing anything about the Swift programming language
        other than that &lt;code&gt;.swift&lt;/code&gt; files are associated with Swift code.
        All the editor needs to do
        is talk to the language server and update the UI.
        And knowing how to do that,
        the editor can follow the same procedure
        to facilitate this interaction
        for code written in any language with a language server implementation.&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;language-server-protocol-support-in-clang-llvm&quot; href=&quot;#language-server-protocol-support-in-clang-llvm&quot;&gt;&lt;/a&gt;Language Server Protocol Support in Clang / LLVM&lt;/h2&gt;
        &lt;p&gt;If the &lt;em&gt;M + N&lt;/em&gt; diagram from before looks familiar,
        it might be because it’s the same approach taken by LLVM.&lt;/p&gt;
        &lt;p&gt;At the core of LLVM is an intermediate representation (IR).
        Supported languages generate IR using a &lt;dfn&gt;compiler frontend&lt;/dfn&gt;,
        and that IR can generate machine code
        for any platform supported by a &lt;dfn&gt;compiler backend&lt;/dfn&gt;.&lt;/p&gt;
        &lt;p&gt;&lt;img integrity=&quot;sha512-Uaejp73r7P0CrHwrJRcrkQBel3m0WPLQH0izCFnvILyDuQ7J+/sMBIcUtAvatqR9XvC8COn+RoH5LgA4mQ+BwA==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/lsp-llvm-ir-51a7a3a7bdebecfd02ac7c2b25172b91005e9779b458f2d01f48b30859ef20bc83b90ec9fbfb0c048714b40bdab6a47d5ef0bc08e9fe4681f92e0038990f81c0.svg&quot; role=&quot;img&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
        &lt;aside class=&quot;admonition info&quot;&gt;
        &lt;p&gt;If you’re curious to learn more about how Swift code is compiled,
        check out &lt;a href=&quot;https://nshipster.com/swiftsyntax/&quot;&gt;our article about SwiftSyntax&lt;/a&gt;.&lt;/p&gt;
        &lt;/aside&gt;
        &lt;p&gt;The LLVM compiler frontend for C languages
        is called &lt;a href=&quot;https://clang.llvm.org&quot;&gt;Clang&lt;/a&gt;.
        It’s also used by Swift for inter-operability with Objective-C.
        In its recent 5.0.0 release,
        Clang added a new tool called
        &lt;a href=&quot;https://clang.llvm.org/extra/clangd.html&quot;&gt;Clangd&lt;/a&gt;,
        LLVM’s implementation for the Language Server Protocol.&lt;/p&gt;
        &lt;p&gt;In April 2018,
        &lt;a href=&quot;http://lists.llvm.org/pipermail/cfe-dev/2018-April/057668.html&quot;&gt;Apple announced to the LLVM mailing list&lt;/a&gt;
        that it was switching the focus of its development efforts from
        &lt;a href=&quot;https://clang.llvm.org/doxygen/group__CINDEX.html&quot;&gt;libclang&lt;/a&gt;
        to Clangd as the primary way to create interactive tooling.&lt;/p&gt;
        &lt;p&gt;Now you might think, &lt;em&gt;“So what?”&lt;/em&gt;
        Apple is among the most prominent supporters of the LLVM project —
        having, among other things,
        employed the project’s founder, Chris Lattner, for over a decade.
        Apple’s decision to switch from one obscure Clang tool to another
        would seem to be an implementation detail (so to speak).&lt;/p&gt;
        &lt;p&gt;What makes this announcement quite interesting
        is that Clangd appears to have been created entirely outside of Apple,
        with significant contributions from Google and other companies.
        This announcement signals a significant shift
        in the direction of tooling development going forward —
        something that would be confirmed 6 months later on the Swift.org forums.&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;getting-started-with-language-server-protocol&quot; href=&quot;#getting-started-with-language-server-protocol&quot;&gt;&lt;/a&gt;Getting Started with Language Server Protocol&lt;/h2&gt;
        &lt;p&gt;Xcode 11.4 includes &lt;code&gt;sourcekit-lsp&lt;/code&gt; in its default toolchain.
        You can use the &lt;code&gt;xcrun&lt;/code&gt; command
        to get the path to the language server executable:&lt;/p&gt;
        &lt;pre class=&quot;highlight&quot; data-lang=&quot;Terminal&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;xcrun &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; sourcekit-lsp
        &lt;span class=&quot;go&quot;&gt;/Applications/Xcode.app/Contents/Developer/Toolchains/Xcode&lt;wbr&gt;&lt;/wbr&gt;Default.xctoolchain/usr/bin/sourcekit-lsp
        &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
        &lt;p&gt;Check out &lt;a href=&quot;/vscode/&quot;&gt;our article about Visual Studio Code&lt;/a&gt;
        to get started with our go-to editors.
        Beyond that,
        the sourcekit-lsp project on GitHub has
        &lt;a href=&quot;https://github.com/NSHipster/sourcekit-lsp/tree/master/Editors#editor-integration&quot;&gt;instructions for integrating with Sublime Text, Vim, Emacs, and others.&lt;/a&gt;.&lt;/p&gt;
        &lt;h2&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;potential-consequences-of-apples-support-of-language-server-protocol&quot; href=&quot;#potential-consequences-of-apples-support-of-language-server-protocol&quot;&gt;&lt;/a&gt;Potential Consequences of Apple’s Support of Language Server Protocol&lt;/h2&gt;
        &lt;p&gt;It’ll take some time to feel the full impact of these developments,
        but believe me: your patience will be rewarded.
        Here are just a few of what I believe will happen as a result of LSP
        in the coming months and years.&lt;/p&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;swift-becomes-more-appealing-as-a-general-purpose-programming-language&quot; href=&quot;#swift-becomes-more-appealing-as-a-general-purpose-programming-language&quot;&gt;&lt;/a&gt;Swift Becomes More Appealing as a General-Purpose Programming Language&lt;/h3&gt;
        &lt;p&gt;Although Swift is used primarily for app development,
        it was designed from the start to be
        a capable general-purpose programming language.
        Between
        &lt;a href=&quot;https://www.tensorflow.org/swift/&quot;&gt;Swift for TensorFlow&lt;/a&gt;,
        &lt;a href=&quot;https://github.com/apple/swift-nio&quot;&gt;SwiftNIO&lt;/a&gt;,
        and other projects,
        we’re just starting to see the promise of
        what Swift can do beyond the App Store.&lt;/p&gt;
        &lt;p&gt;Among the biggest factors holding Swift back from
        mainstream adoption up to this point
        has been its reliance on Xcode.&lt;/p&gt;
        &lt;p&gt;It’s a lot to ask, say, a web developer or machine learning engineer
        to download Xcode just to try Swift
        when there are so many great alternatives
        with a much lower barrier to entry.
        Support for the Language Server Protocol
        should make it significantly easier for folks outside the Apple ecosystem
        to evaluate Swift with the same, familiar tools they use for everything else.&lt;/p&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;xcode-gets-better&quot; href=&quot;#xcode-gets-better&quot;&gt;&lt;/a&gt;Xcode Gets Better&lt;/h3&gt;
        &lt;p&gt;Adopting LSP isn’t just about making Swift work better in other editors;
        Xcode stands to benefit immensely, as well.&lt;/p&gt;
        &lt;p&gt;Consider &lt;a href=&quot;https://forums.swift.org/t/new-lsp-language-service-supporting-swift-and-c-family-languages-for-any-editor-and-platform/17024/29&quot;&gt;this forum post&lt;/a&gt;
        from Project Lead for Swift at Apple, Ted Kremenek:&lt;/p&gt;
        &lt;blockquote&gt;
        &lt;p&gt;The LSP service [Argyrios] is describing
        will be functionally more powerful than SourceKit is today.&lt;/p&gt;
        &lt;/blockquote&gt;
        &lt;p&gt;LSP is an opportunity for the Xcode team to take a fresh approach to
        Swift integration,
        and to capitalize on all of the improvements to the language and tooling
        in the four years since its 1.0 release.&lt;/p&gt;
        &lt;p&gt;Our first glimpse into this overhauled infrastructure comes by way of
        &lt;a href=&quot;https://github.com/apple/indexstore-db&quot;&gt;IndexStoreDB&lt;/a&gt;:
        a powerful new API for querying code symbols in Swift projects
        from a &lt;a href=&quot;https://docs.google.com/document/d/1cH2sTpgSnJZCkZtJl1aY-rzy4uGPcrI-6RrUpdATO2Q/&quot;&gt;Clang index&lt;/a&gt;.&lt;/p&gt;
        &lt;h3&gt;
        &lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; id=&quot;xcode-eventually-becomes-more-capable&quot; href=&quot;#xcode-eventually-becomes-more-capable&quot;&gt;&lt;/a&gt;Xcode (Eventually) Becomes More Capable&lt;/h3&gt;
        &lt;p&gt;The benefit of LSP isn’t limited to Swift and Objective-C;
        &lt;a href=&quot;https://forums.swift.org/t/new-lsp-language-service-supporting-swift-and-c-family-languages-for-any-editor-and-platform/17024/33&quot;&gt;from another post by Argyrios in that thread&lt;/a&gt;:&lt;/p&gt;
        &lt;blockquote&gt;
        &lt;p&gt;Getting Xcode to use our new LSP service
        should make it viable to use other LSP services as well,
        and it’s something that we are interested in,
        but we don’t have specific plans to announce at this moment.&lt;/p&gt;
        &lt;/blockquote&gt;
        &lt;p&gt;The main focus for the current efforts are to improve the story for Swift.
        But once that’s done, it should be relatively straightforward
        to have those benefits cascade down to other languages with LSP support.&lt;/p&gt;
        &lt;hr&gt;
        &lt;p&gt;The architecture of software
        reflects the structure and values of the organizations that create it.
        The converse is true as well, to some extent.&lt;/p&gt;
        &lt;p&gt;By adopting the open Language Server Protocol standard for Xcode,
        Apple is making good on its commitment to the success of Swift
        on platforms outside the Apple ecosystem.
        And I think it’ll work:
        tooling (or lack thereof) is often the key decider
        in which technologies gain mindshare.
        But perhaps more importantly,
        I believe this decision demonstrates an increased willingness within
        (at least some small part of) the company
        for collaboration and transparency.&lt;/p&gt;
      </content>
      <author>
        <name>Mattt</name>
        <email>mattt@nshipster.com</email>
        <uri>https://nshipster.com/authors/mattt/</uri>
      </author>
      <category term="Open Source" />
      <summary type="html">&lt;p&gt;Apple’s adoption of LSP is arguably the most important decision they’ve made for Swift since releasing the language as open source in 2014. It’s a big deal for app developers, and it’s an even bigger deal for Swift developers on other platforms.&lt;/p&gt;</summary>
    </entry>
  </feed>