<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Osprey Programming Language</title>
  <subtitle>One core, two flavors: write Osprey in C-style braces or ML-style layout with curry-by-default. Both lower to one canonical AST with typed algebraic effects, fibers, persistent collections, Hindley-Milner inference, and LLVM code generation.</subtitle>
  <link href="https://www.ospreylang.dev/feed.xml" rel="self"/>
  <link href="https://www.ospreylang.dev/"/>
  <updated>2026-07-23T00:00:00.000Z</updated>
  <id>https://www.ospreylang.dev/</id>
  <author><name>Christian Findlay</name></author>
  <entry>
    <title>Building Type-Safe Web APIs with Osprey&#39;s Pattern Matching</title>
    <link href="https://www.ospreylang.dev/blog/2025-01-10-building-web-apis-with-pattern-matching/"/>
    <id>https://www.ospreylang.dev/blog/2025-01-10-building-web-apis-with-pattern-matching/</id>
    <updated>2025-01-10T00:00:00.000Z</updated>
    <content type="html">https://www.ospreylang.dev/%3Cp%3EWeb%20APIs%20are%20the%20backbone%20of%20modern%20applications,%20but%20they&#39;re%20also%20where%20things%20go%20wrong%20most%20often.%20Null%20reference%20exceptions,%20unhandled%20error%20cases,%20and%20missing%20validation%20logic%20plague%20even%20the%20most%20carefully%20written%20services.%20%3Cstrong%3EWhat%20if%20your%20programming%20language%20could%20eliminate%20these%20problems%20entirely#the-problem-with-traditional-error-handling%22%3EThe%20Problem%20with%20Traditional%20Error%20Handling%3C/a%3E%3C/h2%3E%3Cp%3EMost%20web%20frameworks%20handle%20errors%20through%20exceptions%20or%20error%20codes.%20Here&#39;s%20typical%20Node.js/Express%20code:%3C/p%3E%3Cpre%20class=%22language-javascript%22%3E%3Ccode%20class=%22language-javascript%22%3Eapp%3Cspan%20class=%22token%20punctuation%22%3E.%3C/span%3E%3Cspan%20class=%22token%20function%22%3Epost%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20string%22%3E&#39;/users&#39;%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Easync%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20parameter%22%3Ereq%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20res%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%3Cspan%20class=%22token%20keyword%22%3Etry%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Econst%3C/span%3E%20user%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Eawait%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EcreateUser%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Ereq%3Cspan%20class=%22token%20punctuation%22%3E.%3C/span%3Ebody%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E;%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Eif%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Euser%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20%20%20res%3Cspan%20class=%22token%20punctuation%22%3E.%3C/span%3E%3Cspan%20class=%22token%20function%22%3Ejson%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%3Cspan%20class=%22token%20literal-property%20property%22%3Esuccess%3C/span%3E%3Cspan%20class=%22token%20operator%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20boolean%22%3Etrue%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20literal-property%20property%22%3Edata%3C/span%3E%3Cspan%20class=%22token%20operator%22%3E:%3C/span%3E%20user%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E;%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Eelse%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20%20%20res%3Cspan%20class=%22token%20punctuation%22%3E.%3C/span%3E%3Cspan%20class=%22token%20function%22%3Estatus%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E400%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E.%3C/span%3E%3Cspan%20class=%22token%20function%22%3Ejson%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%3Cspan%20class=%22token%20literal-property%20property%22%3Eerror%3C/span%3E%3Cspan%20class=%22token%20operator%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22Failed%20to%20create%20user%22%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E;%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Ecatch%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Eerror%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Eif%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Eerror%3Cspan%20class=%22token%20punctuation%22%3E.%3C/span%3Ecode%20%3Cspan%20class=%22token%20operator%22%3E===%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E&#39;DUPLICATE_EMAIL&#39;%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20%20%20res%3Cspan%20class=%22token%20punctuation%22%3E.%3C/span%3E%3Cspan%20class=%22token%20function%22%3Estatus%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E409%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E.%3C/span%3E%3Cspan%20class=%22token%20function%22%3Ejson%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%3Cspan%20class=%22token%20literal-property%20property%22%3Eerror%3C/span%3E%3Cspan%20class=%22token%20operator%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22Email%20already%20exists%22%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E;%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Eelse%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20%20%20res%3Cspan%20class=%22token%20punctuation%22%3E.%3C/span%3E%3Cspan%20class=%22token%20function%22%3Estatus%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E500%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E.%3C/span%3E%3Cspan%20class=%22token%20function%22%3Ejson%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%3Cspan%20class=%22token%20literal-property%20property%22%3Eerror%3C/span%3E%3Cspan%20class=%22token%20operator%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22Internal%20server%20error%22%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E;%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E;%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3E%3Cstrong%3EWhat&#39;s%20wrong%20here?%3C/strong%3E%20The%20compiler%20can&#39;t%20verify%20you&#39;ve%20handled%20every%20error%20type.%20You%20might%20forget%20to%20handle%20a%20database%20timeout,%20miss%20a%20validation%20error,%20or%20incorrectly%20assume%20what%20%3Ccode%3EcreateUser%3C/code%3E%20returns.%3C/p%3E%3Ch2%20id=%22modeling-api-responses-with-algebraic-data-types%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#modeling-api-responses-with-algebraic-data-types%22%3EModeling%20API%20Responses%20with%20Algebraic%20Data%20Types%3C/a%3E%3C/h2%3E%3Cp%3EOsprey%20takes%20a%20different%20approach.%20We%20model%20all%20possible%20outcomes%20as%20a%20single%20%3Cstrong%3Ealgebraic%20data%20type%3C/strong%3E%20%E2%80%94%20a%20union%20whose%20variants%20each%20carry%20their%20own%20record%20of%20fields:%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20keyword%22%3Etype%3C/span%3E%20CreateUserResult%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%20%20%20Created%20%20%20%20%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20user%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20User%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20id%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20UserId%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20|%20ValidationFailed%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20fields%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3EList%3C/span%3E%3Cspan%20class=%22token%20operator%22%3E&amp;lt;%3C/span%3E%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%3Cspan%20class=%22token%20operator%22%3E%3E%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20messages%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3EList%3C/span%3E%3Cspan%20class=%22token%20operator%22%3E&amp;lt;%3C/span%3E%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%3Cspan%20class=%22token%20operator%22%3E%3E%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20|%20DuplicateEmail%20%20%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20email%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20|%20DatabaseTimeout%20%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20retryAfter%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20|%20DatabaseFailure%20%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20message%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20|%20InternalFailure%20%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20context%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3ENow%20our%20API%20handler%20%3Cstrong%3Emust%3C/strong%3E%20handle%20every%20case.%20A%20small%20helper%20keeps%20each%20arm%20to%20a%20single%20line%20%E2%80%94%20%3Ccode%3EHttpResponse%3C/code%3E%20is%20Osprey&#39;s%20built-in%20response%20record:%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Ejson%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Estatus%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20body%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3EHttpResponse%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3EHttpResponse%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20status%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20status%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%20%20%20headers%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22Content-Type:%20application/json%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%20%20%20contentType%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22application/json%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%20%20%20streamFd%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3C/span%3E%3Cspan%20class=%22token%20number%22%3E1%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%20%20%20isComplete%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Etrue%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%20%20%20partialBody%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20body%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EcreateUserHandler%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Erequest%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20HttpRequest%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3EHttpResponse%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Ematch%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EcreateUser%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20function%22%3EparseUserData%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Erequest%3Cspan%20class=%22token%20punctuation%22%3E.%3C/span%3Ebody%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20%20%20%20%20Created%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20user%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20id%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%20%20%20%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20function%22%3Ejson%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E201%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22{&#92;%22id&#92;%22:%20${toString(id)}}%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20%20%20%20%20ValidationFailed%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20fields%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20messages%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%20%20%20%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20function%22%3Ejson%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E400%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22{&#92;%22error&#92;%22:%20&#92;%22validation%20failed&#92;%22}%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20%20%20%20%20DuplicateEmail%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20email%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%20%20%20%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20function%22%3Ejson%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E409%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22{&#92;%22error&#92;%22:%20&#92;%22${email}%20is%20already%20registered&#92;%22}%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20%20%20%20%20DatabaseTimeout%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20retryAfter%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%20%20%20%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20function%22%3Ejson%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E503%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22{&#92;%22error&#92;%22:%20&#92;%22retry%20after%20${toString(retryAfter)}s&#92;%22}%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20%20%20%20%20DatabaseFailure%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20message%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%20%20%20%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20function%22%3Ejson%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E502%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22{&#92;%22error&#92;%22:%20&#92;%22database%20error&#92;%22}%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20%20%20%20%20InternalFailure%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20context%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%20%20%20%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20function%22%3Ejson%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E500%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22{&#92;%22error&#92;%22:%20&#92;%22internal%20error%20in%20${context}&#92;%22}%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3E%3Cstrong%3EThe%20compiler%20guarantees%3C/strong%3E%20you%20handle%20every%20case.%20If%20you%20add%20a%20new%20variant%20to%20%3Ccode%3ECreateUserResult%3C/code%3E,%20every%20%3Ccode%3Ematch%3C/code%3E%20that%20handles%20it%20will%20fail%20to%20compile%20until%20you%20add%20the%20new%20arm.%3C/p%3E%3Ch2%20id=%22building-a-complete-user-api%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#building-a-complete-user-api%22%3EBuilding%20a%20Complete%20User%20API%3C/a%3E%3C/h2%3E%3Cp%3ELet&#39;s%20build%20out%20a%20user%20management%20API%20to%20see%20how%20this%20scales.%20Osprey%20has%20no%20%3Ccode%3Emodule%3C/code%3E%20keyword%20yet%20%E2%80%94%20types%20and%20functions%20live%20at%20the%20top%20level.%20Each%20operation%20returns%20a%20domain%20union,%20so%20the%20caller%20is%20forced%20to%20handle%20every%20outcome:%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20keyword%22%3Etype%3C/span%3E%20User%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20id%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20email%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20name%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20isActive%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Ebool%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Etype%3C/span%3E%20UserFilter%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20All%20|%20Active%20|%20Inactive%20|%20EmailDomain%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20domain%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Etype%3C/span%3E%20UserQuery%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%20%20%20Found%20%20%20%20%20%20%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20user%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20User%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20|%20Missing%20%20%20%20%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20id%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20|%20Forbidden%20%20%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20action%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20|%20QueryFailed%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20details%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3Cspan%20class=%22token%20comment%22%3E//%20GET%20/users/:id%20%E2%80%94%20permission%20gating%20is%20just%20another%20match%20arm.%3C/span%3E%3Cspan%20class=%22token%20comment%22%3E//%20Osprey%20is%20expression-based,%20so%20there%20is%20no%20early%20%60return%60.%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EgetUser%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Eid%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20auth%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20AuthToken%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20UserQuery%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Ematch%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EhasPermission%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Eauth%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22users:read%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Efalse%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20Forbidden%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20action%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22read%20user%22%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Etrue%3C/span%3E%20%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3ElookupUser%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Eid%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3EValidation%20and%20lookup%20compose%20as%20nested%20matches.%20The%20built-in%20%3Ccode%3EResult&amp;lt;T,%20E&amp;gt;%3C/code%3E%20type%20(whose%20variants%20are%20%3Ccode%3ESuccess%3C/code%3E%20and%20%3Ccode%3EError%3C/code%3E)%20threads%20naturally%20into%20our%20domain%20union:%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20comment%22%3E//%20PUT%20/users/:id%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EupdateUser%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Eid%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20updates%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20UserUpdates%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20auth%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20AuthToken%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20UserQuery%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Ematch%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EhasPermission%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Eauth%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22users:write%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Efalse%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20Forbidden%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20action%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22update%20user%22%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Etrue%3C/span%3E%20%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Ematch%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Evalidate%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Eupdates%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20%20%20%20%20%20%20%20%20Error%20%20%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20message%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20QueryFailed%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20details%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20message%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20%20%20%20%20%20%20%20%20Success%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20value%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EapplyUpdate%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Eid%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20value%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3C/code%3E%3C/pre%3E%3Ch2%20id=%22http-response-conversion%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#http-response-conversion%22%3EHTTP%20Response%20Conversion%3C/a%3E%3C/h2%3E%3Cp%3EConverting%20our%20domain%20types%20to%20HTTP%20responses%20becomes%20a%20pure%20mapping%20function%20that%20reuses%20the%20%3Ccode%3Ejson%3C/code%3E%20helper%20from%20earlier:%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EtoHttpResponse%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Eq%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20UserQuery%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3EHttpResponse%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Ematch%3C/span%3E%20q%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20Found%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20user%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Ejson%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E200%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22{&#92;%22email&#92;%22:%20&#92;%22${user.email}&#92;%22}%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20Missing%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20id%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Ejson%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E404%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22{&#92;%22error&#92;%22:%20&#92;%22user%20${toString(id)}%20not%20found&#92;%22}%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20Forbidden%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20action%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Ejson%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E403%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22{&#92;%22error&#92;%22:%20&#92;%22permission%20denied:%20${action}&#92;%22}%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20QueryFailed%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20details%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Ejson%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E500%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22{&#92;%22error&#92;%22:%20&#92;%22internal%20error&#92;%22}%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3C/code%3E%3C/pre%3E%3Ch2%20id=%22request-routing-with-pattern-matching%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#request-routing-with-pattern-matching%22%3ERequest%20Routing%20with%20Pattern%20Matching%3C/a%3E%3C/h2%3E%3Cp%3EOsprey%20matches%20a%20single%20value%20per%20%3Ccode%3Ematch%3C/code%3E,%20so%20multi-key%20routing%20is%20expressed%20as%20%3Cstrong%3Enested%20matches%3C/strong%3E%20rather%20than%20tuple%20patterns:%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3ErouteRequest%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Emethod%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20path%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20auth%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20AuthToken%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3EHttpResponse%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Ematch%3C/span%3E%20method%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20string%22%3E%22GET%22%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Ematch%3C/span%3E%20path%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20string%22%3E%22/health%22%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Ejson%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E200%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22{&#92;%22status&#92;%22:%20&#92;%22ok&#92;%22}%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20string%22%3E%22/users%22%3C/span%3E%20%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EtoHttpResponse%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20function%22%3EgetUser%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E1%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20auth%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20%20%20%20%20%20%20%20%20_%20%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Ejson%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E404%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22{&#92;%22error&#92;%22:%20&#92;%22not%20found&#92;%22}%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20string%22%3E%22POST%22%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Ejson%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E201%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22{&#92;%22message&#92;%22:%20&#92;%22created&#92;%22}%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20%20%20%20%20_%20%20%20%20%20%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Ejson%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E405%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22{&#92;%22error&#92;%22:%20&#92;%22method%20not%20allowed&#92;%22}%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3C/code%3E%3C/pre%3E%3Ch2%20id=%22middleware-as-function-composition%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#middleware-as-function-composition%22%3EMiddleware%20as%20Function%20Composition%3C/a%3E%3C/h2%3E%3Cp%3EFunctions%20are%20first-class,%20so%20middleware%20is%20just%20a%20function%20that%20wraps%20a%20handler.%20The%20%3Ccode%3Enext%3C/code%3E%20parameter%20is%20the%20handler%20to%20run%20if%20the%20gate%20passes%20%E2%80%94%20again,%20no%20early%20return,%20the%20gate%20is%20simply%20a%20%3Ccode%3Ematch%3C/code%3E:%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EwithAuth%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%20%20%20%20auth%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20AuthToken%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%20%20%20action%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%20%20%20next%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3EAuthToken%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20UserQuery%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20UserQuery%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Ematch%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EhasPermission%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Eauth%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20action%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Efalse%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20Forbidden%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20action%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20action%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Etrue%3C/span%3E%20%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Enext%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Eauth%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3EBecause%20handlers%20are%20ordinary%20values,%20you%20compose%20cross-cutting%20concerns%20the%20same%20way%20you%20compose%20any%20other%20function%20%E2%80%94%20with%20the%20pipe%20operator%20%3Ccode%3E|&amp;gt;%3C/code%3E.%3C/p%3E%3Ch2%20id=%22testing-becomes-trivial%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#testing-becomes-trivial%22%3ETesting%20Becomes%20Trivial%3C/a%3E%3C/h2%3E%3Cp%3ESince%20every%20handler%20is%20a%20pure%20function%20over%20data,%20testing%20is%20incredibly%20straightforward.%20Osprey%20programs%20are%20exercised%20with%20the%20%3Cstrong%3Edifferential%20harness%3C/strong%3E:%20a%20program&#39;s%20%3Ccode%3Estdout%3C/code%3E%20is%20byte-compared%20against%20a%20checked-in%20%3Ccode%3E.expectedoutput%3C/code%3E%20file.%20A%20test%20is%20just%20a%20program%20that%20prints%20each%20outcome:%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Emain%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20function%22%3Eprint%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20function%22%3Edescribe%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20function%22%3EgetUser%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E1%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20adminAuth%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%3Cspan%20class=%22token%20comment%22%3E//%20Found%20...%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20function%22%3Eprint%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20function%22%3Edescribe%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20function%22%3EgetUser%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E2%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20adminAuth%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%3Cspan%20class=%22token%20comment%22%3E//%20Forbidden%20...%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20function%22%3Eprint%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20function%22%3Edescribe%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20function%22%3EgetUser%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E9%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20adminAuth%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%3Cspan%20class=%22token%20comment%22%3E//%20Missing%20...%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20number%22%3E0%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3EBecause%20the%20result%20of%20each%20call%20is%20plain%20data,%20the%20expected%20output%20is%20completely%20deterministic%20%E2%80%94%20there%20is%20no%20hidden%20state%20to%20mock.%3C/p%3E%3Ch2%20id=%22the-reliability-advantage%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#the-reliability-advantage%22%3EThe%20Reliability%20Advantage%3C/a%3E%3C/h2%3E%3Cp%3EThis%20approach%20eliminates%20entire%20categories%20of%20production%20bugs:%3C/p%3E%3Cul%3E%3Cli%3E%3Cstrong%3ENo%20null%20reference%20exceptions%3C/strong%3E%20-%20Absence%20is%20modelled%20explicitly%20with%20union%20variants%3C/li%3E%3Cli%3E%3Cstrong%3ENo%20unhandled%20error%20cases%3C/strong%3E%20-%20Pattern%20matching%20forces%20you%20to%20handle%20every%20scenario%3C/li%3E%3Cli%3E%3Cstrong%3ENo%20silent%20failures%3C/strong%3E%20-%20Every%20operation&#39;s%20outcome%20is%20explicitly%20modeled%3C/li%3E%3Cli%3E%3Cstrong%3ENo%20incorrect%20status%20codes%3C/strong%3E%20-%20HTTP%20responses%20are%20generated%20deterministically%3C/li%3E%3Cli%3E%3Cstrong%3ENo%20missing%20validation%3C/strong%3E%20-%20Validation%20is%20built%20into%20the%20type%20system%3C/li%3E%3C/ul%3E%3Ch2%20id=%22performance-benefits%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#performance-benefits%22%3EPerformance%20Benefits%3C/a%3E%3C/h2%3E%3Cp%3EDespite%20the%20high-level%20abstractions,%20Osprey%20compiles%20to%20efficient%20code.%20Functional%20pipelines%20over%20ranges%20are%20fused%20into%20a%20single%20loop:%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Eadd%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Ea%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20b%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20a%20%3Cspan%20class=%22token%20operator%22%3E+%3C/span%3E%20b%3Cspan%20class=%22token%20comment%22%3E//%20This%20high-level%20code...%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Elet%3C/span%3E%20result%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Erange%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E1%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20number%22%3E1000%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20operator%22%3E|%3E%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Efilter%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3En%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3En%20%3Cspan%20class=%22token%20operator%22%3E%%3C/span%3E%20%3Cspan%20class=%22token%20number%22%3E2%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E==%3C/span%3E%20%3Cspan%20class=%22token%20number%22%3E0%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20operator%22%3E|%3E%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Emap%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3En%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20n%20%3Cspan%20class=%22token%20operator%22%3E*%3C/span%3E%20n%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20operator%22%3E|%3E%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Efold%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E0%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20add%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20comment%22%3E//%20...compiles%20to%20a%20single%20loop%20with%20no%20intermediate%20lists%20(stream%20fusion).%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3EThe%20pattern%20matching%20compiles%20to%20efficient%20jump%20tables,%20and%20the%20functional%20pipelines%20are%20optimized%20away%20entirely.%3C/p%3E%3Ch2%20id=%22conclusion%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#conclusion%22%3EConclusion%3C/a%3E%3C/h2%3E%3Cp%3EBuilding%20web%20APIs%20with%20Osprey&#39;s%20pattern%20matching%20transforms%20error-prone,%20defensive%20programming%20into%20%3Cstrong%3Ecompiler-verified%20correctness%3C/strong%3E.%20You%20can&#39;t%20ship%20a%20handler%20that%20forgets%20to%20handle%20an%20error%20case%20because%20%3Cstrong%3Eit%20won&#39;t%20compile%3C/strong%3E.%3C/p%3E%3Cp%3EThis%20isn&#39;t%20just%20academic%20elegance%E2%80%94it&#39;s%20practical%20reliability.%20When%20your%20API%20serves%20millions%20of%20requests%20per%20day,%20the%20difference%20between%20&amp;quot;it%20should%20work&amp;quot;%20and%20&amp;quot;it%20can&#39;t%20fail&amp;quot;%20is%20the%20difference%20between%203%20AM%20pages%20and%20peaceful%20sleep.%3C/p%3E%3Cp%3EThe%20functional%20programming%20revolution%20isn&#39;t%20coming%E2%80%94%3Cstrong%3Eit&#39;s%20here%3C/strong%3E.%20And%20for%20web%20development,%20the%20benefits%20are%20too%20compelling%20to%20ignore.%3C/p%3E%3Chr%3E%3Cp%3E%3Cem%3EReady%20to%20try%20building%20your%20own%20type-safe%20APIs?%20Browse%20the%20%3Ca%20href=%22/docs/%22%3Edocumentation%3C/a%3E%20or%20experiment%20in%20the%20%3Ca%20href=%22/playground/%22%3Eplayground%3C/a%3E.%3C/em%3E%3C/p%3E%3Cblockquote%3E%3Cp%3E%3Cstrong%3EEditor&#39;s%20note%20(updated%202026-06-20):%3C/strong%3E%20This%20post%20was%20first%20published%20in%20January%202025,%20early%20in%20Osprey&#39;s%20development.%20Osprey&#39;s%20syntax%20has%20evolved%20considerably%20since%20then%20%E2%80%94%20among%20other%20changes,%20the%20language%20settled%20on%20%3Ccode%3E=&amp;gt;%3C/code%3E%20for%20match%20arms,%20record-style%20union%20variants,%20expression-bodied%20functions,%20lowercase%20primitive%20types%20(%3Ccode%3Eint%3C/code%3E/%3Ccode%3Estring%3C/code%3E/%3Ccode%3Ebool%3C/code%3E),%20and%20%3Ccode%3EResult%3C/code%3E%20with%20%3Ccode%3ESuccess%3C/code%3E/%3Ccode%3EError%3C/code%3E.%20The%20code%20samples%20above%20have%20been%20revised%20to%20match%20the%20current%20language.%20The%20original%20article%20is%20preserved%20unchanged%20in%20this%20site&#39;s%20Git%20history%20%E2%80%94%20browse%20the%20%3Ca%20href=%22https://github.com/Nimblesite/osprey%22%3Erepository%3C/a%3E%20and%20view%20this%20file&#39;s%20history%20to%20read%20it%20exactly%20as%20first%20published.%3C/p%3E%3C/blockquote%3E</content>
    <summary>Learn how Osprey’s exhaustive pattern matching and algebraic data types make web API states explicit, checked, and easier to maintain as services evolve.</summary>
  </entry>
  <entry>
    <title>The Memory-Safe Revolution: Why Osprey is Built for Tomorrow&#39;s Challenges</title>
    <link href="https://www.ospreylang.dev/blog/2025-01-15-the-memory-safe-revolution/"/>
    <id>https://www.ospreylang.dev/blog/2025-01-15-the-memory-safe-revolution/</id>
    <updated>2025-01-15T00:00:00.000Z</updated>
    <content type="html">https://www.ospreylang.dev/%3Cp%3EThe%20software%20industry%20is%20at%20an%20inflection%20point.%20Microsoft&#39;s%20Security%20Response%20Center%20has%20reported%20that%20%3Ca%20href=%22https:/msrc.microsoft.com/blog/2019/07/a-proactive-approach-to-more-secure-code/%22%3Earound%2070%%20of%20the%20vulnerabilities%20it%20assigns%20a%20CVE%20each%20year%3C/a%3E%20are%20memory%20safety%20issues.%20In%202024,%20a%20faulty%20CrowdStrike%20update%20%E2%80%94%20an%20out-of-bounds%20memory%20read%20%E2%80%94%20crashed%20millions%20of%20Windows%20machines;%20a%20%3Ca%20href=%22https:/fortune.com/2024/08/03/crowdstrike-outage-fortune-500-companies-5-4-billion-damages-uninsured-losses/%22%3EParametrix%20analysis%20estimated%20%3Cstrong%3E$5.4%20billion%3C/strong%3E%20in%20direct%20losses%3C/a%3E%20for%20Fortune%20500%20companies%20alone.%20Meanwhile,%20the%20U.S.%20White%20House%20is%20%3Ca%20href=%22https:/bidenwhitehouse.archives.gov/oncd/briefing-room/2024/02/26/press-release-technical-report/%22%3Eurging%20the%20industry%20to%20adopt%20memory-safe%20languages%3C/a%3E%20for%20critical%20systems.%3C/p%3E%3Cp%3EThis%20isn&#39;t%20just%20another%20trend%E2%80%94it&#39;s%20a%20fundamental%20shift%20that%20will%20reshape%20how%20we%20build%20software.%20And%20at%20the%20heart%20of%20this%20revolution%20lies%20a%20perfect%20storm%20of%20converging%20technologies:%20%3Cstrong%3Ememory%20safety%3C/strong%3E,%20%3Cstrong%3Efunctional%20programming%3C/strong%3E,%20and%20%3Cstrong%3Emodern%20concurrency%20models%3C/strong%3E.%3C/p%3E%3Ch2%20id=%22the-problem-we-cant-ignore%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#the-problem-we-cant-ignore%22%3EThe%20Problem%20We%20Can&#39;t%20Ignore%3C/a%3E%3C/h2%3E%3Cp%3ETraditional%20systems%20languages%20like%20C%20and%20C++%20have%20powered%20our%20digital%20infrastructure%20for%20decades.%20But%20their%20flexibility%20comes%20with%20a%20devastating%20cost:%20%3Cstrong%3Ememory%20vulnerabilities%20are%20endemic%3C/strong%3E.%20Buffer%20overflows,%20use-after-free%20bugs,%20and%20null%20pointer%20dereferences%20aren&#39;t%20edge%20cases%E2%80%94they&#39;re%20the%20primary%20attack%20vectors%20compromising%20our%20most%20critical%20systems.%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20comment%22%3E//%20Osprey%20has%20no%20null.%20Absence%20is%20a%20value%20you%20must%20handle%20explicitly,%3C/span%3E%3Cspan%20class=%22token%20comment%22%3E//%20so%20%22forgot%20to%20check%20for%20null%22%20simply%20cannot%20happen.%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Etype%3C/span%3E%20Email%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20Provided%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20address%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20|%20Absent%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EdescribeEmail%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Ee%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20Email%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Ematch%3C/span%3E%20e%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20Provided%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20address%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22User%20has%20email:%20${address}%22%3C/span%3E%20%20%20%20Absent%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22User%20email%20not%20provided%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3EBut%20here&#39;s%20where%20it%20gets%20interesting:%20%3Cstrong%3EAI%20is%20about%20to%20make%20everything%20worse%3C/strong%3E.%20As%20AI%20tools%20become%20better%20at%20pattern%20recognition,%20they&#39;re%20being%20trained%20to%20discover%20vulnerabilities%20orders%20of%20magnitude%20faster%20than%20humans%20ever%20could.%20What%20used%20to%20require%20painstaking%20manual%20code%20review%20can%20now%20be%20automated%20at%20scale.%3C/p%3E%3Cblockquote%3E%3Cp%3E%3Cem%3E&amp;quot;A%20flood%20of%20dangerous%20vulnerability%20discoveries%20might%20be%20on%20the%20horizon.%20This%20acceleration%20in%20bug%20discovery%20makes%20migrating%20to%20safer%20languages%20more%20urgent%20than%20ever.&amp;quot;%3C/em%3E%3C/p%3E%3Cp%3E%3Cstrong%3E%E2%80%94%20Adam%20Ierymenko,%20ZeroTier%3C/strong%3E%3C/p%3E%3C/blockquote%3E%3Ch2%20id=%22the-functional-programming-renaissance%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#the-functional-programming-renaissance%22%3EThe%20Functional%20Programming%20Renaissance%3C/a%3E%3C/h2%3E%3Cp%3EWhile%20the%20memory%20safety%20crisis%20unfolds,%20functional%20programming%20is%20experiencing%20unprecedented%20growth.%20Languages%20like%20Haskell,%20F#,%20and%20Scala%20are%20finding%20homes%20in%20finance,%20AI,%20and%20distributed%20systems.%20Even%20traditionally%20imperative%20languages%20are%20adopting%20functional%20features%E2%80%94lambdas%20in%20Java,%20destructuring%20in%20JavaScript,%20pattern%20matching%20in%20Python.%3C/p%3E%3Cp%3E%3Cstrong%3EWhy%20the%20sudden%20shift?%3C/strong%3E%20Because%20functional%20programming%20solves%20fundamental%20problems:%3C/p%3E%3Ch3%20id=%22immutability-by-default%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#immutability-by-default%22%3E%3Cstrong%3EImmutability%20by%20Default%3C/strong%3E%3C/a%3E%3C/h3%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20keyword%22%3Etype%3C/span%3E%20User%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20name%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20age%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20status%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Elet%3C/span%3E%20alice%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20User%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20name%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22Alice%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20age%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20number%22%3E30%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20status%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22new%22%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3Cspan%20class=%22token%20comment%22%3E//%20Record%20%22update%22%20returns%20a%20NEW%20value%20%E2%80%94%20alice%20is%20untouched.%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Elet%3C/span%3E%20verified%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20alice%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20status%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22verified%22%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3Cspan%20class=%22token%20comment%22%3E//%20Persistent%20collections%20behave%20the%20same%20way.%20listAppend%20returns%20a%20new%3C/span%3E%3Cspan%20class=%22token%20comment%22%3E//%20list%20that%20shares%20structure%20with%20the%20old%20one;%20nothing%20is%20mutated.%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Elet%3C/span%3E%20base%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3ElistAppend%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20function%22%3ElistAppend%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20type%22%3EList%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20alice%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20verified%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Elet%3C/span%3E%20more%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3ElistAppend%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Ebase%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20alice%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20name%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22Bob%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20age%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20number%22%3E25%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20comment%22%3E//%20base%20still%20has%20length%202;%20%60more%60%20has%20length%203.%3C/span%3E%3C/code%3E%3C/pre%3E%3Ch3%20id=%22fearless-concurrency%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#fearless-concurrency%22%3E%3Cstrong%3EFearless%20Concurrency%3C/strong%3E%3C/a%3E%3C/h3%3E%3Cp%3EIn%20Osprey,%20our%20%3Cstrong%3Efiber-based%20concurrency%20model%3C/strong%3E%20makes%20parallel%20programming%20intuitive.%20Fibers%20are%20spawned%20with%20%3Ccode%3Espawn%20{%20...%20}%3C/code%3E%20and%20joined%20with%20%3Ccode%3Eawait(...)%3C/code%3E:%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20comment%22%3E//%20Launch%20isolated%20async%20operations%20that%20can&#39;t%20cause%20data%20races.%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EfetchUserData%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3EuserId%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E!%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E[%3C/span%3ELogger%3Cspan%20class=%22token%20punctuation%22%3E]%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Elet%3C/span%3E%20profile%20%20%20%20%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Espawn%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EfetchProfile%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3EuserId%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Elet%3C/span%3E%20preferences%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Espawn%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EfetchPreferences%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3EuserId%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Elet%3C/span%3E%20activity%20%20%20%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Espawn%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EfetchActivity%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3EuserId%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Eawait%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Eprofile%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E+%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Eawait%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Epreferences%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E+%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Eawait%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Eactivity%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3C/code%3E%3C/pre%3E%3Ch2%20id=%22why-traditional-asyncawait-falls-short%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#why-traditional-asyncawait-falls-short%22%3EWhy%20Traditional%20Async/Await%20Falls%20Short%3C/a%3E%3C/h2%3E%3Cp%3EMost%20modern%20languages%20adopted%20async/await%20as%20their%20concurrency%20solution.%20But%20as%20developer%20experience%20reports%20show,%20%3Cstrong%3Easync/await%20introduces%20new%20classes%20of%20problems%3C/strong%3E:%3C/p%3E%3Cul%3E%3Cli%3E%3Cstrong%3EColored%20functions%3C/strong%3E:%20Async%20functions%20can%20only%20call%20async%20functions%3C/li%3E%3Cli%3E%3Cstrong%3ELost%20call%20stacks%3C/strong%3E:%20Debugging%20becomes%20nightmare%20when%20promises%20sit%20unresolved%3C/li%3E%3Cli%3E%3Cstrong%3EHidden%20complexity%3C/strong%3E:%20Simple%20operations%20become%20callback%20chains%3C/li%3E%3C/ul%3E%3Cp%3EResearch%20from%20functional%20programming%20communities%20shows%20a%20clear%20alternative:%20%3Cstrong%3Estructured%20concurrency%20with%20lightweight%20threads%3C/strong%3E.%20This%20is%20exactly%20what%20Osprey&#39;s%20fiber%20system%20provides.%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20comment%22%3E//%20Structured%20concurrency:%20spawn%20child%20fibers,%20then%20await%20each%20result.%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EprocessBatch%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E!%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E[%3C/span%3ELogger%3Cspan%20class=%22token%20punctuation%22%3E]%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Elet%3C/span%3E%20a%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Espawn%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EprocessOne%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E1%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Elet%3C/span%3E%20b%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Espawn%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EprocessOne%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E2%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Elet%3C/span%3E%20c%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Espawn%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EprocessOne%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E3%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Eawait%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Ea%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E+%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Eawait%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Eb%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E+%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Eawait%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Ec%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3EFibers%20are%20isolated%20execution%20contexts%20that%20communicate%20by%20message%20passing%20rather%20than%20shared%20memory%20%E2%80%94%20so%20there%20are%20no%20orphaned%20operations%20sharing%20mutable%20state%20behind%20your%20back.%3C/p%3E%3Ch2%20id=%22the-enterprise-shift-is-already-happening%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#the-enterprise-shift-is-already-happening%22%3EThe%20Enterprise%20Shift%20is%20Already%20Happening%3C/a%3E%3C/h2%3E%3Cp%3EMajor%20tech%20companies%20are%20making%20the%20transition:%3C/p%3E%3Cul%3E%3Cli%3E%3Cstrong%3EMicrosoft%3C/strong%3E%20is%20prototyping%20Rust%20for%20Windows%20kernel%20components%3C/li%3E%3Cli%3E%3Cstrong%3EGoogle%3C/strong%3E%20officially%20adopted%20Rust%20for%20Android&#39;s%20low-level%20system%20components%3C/li%3E%3Cli%3E%3Cstrong%3EAWS%3C/strong%3E%20built%20Firecracker%20(powering%20Lambda%20and%20Fargate)%20entirely%20in%20Rust%3C/li%3E%3Cli%3E%3Cstrong%3EMeta%3C/strong%3E%20added%20Rust%20as%20an%20officially%20supported%20server-side%20language%3C/li%3E%3C/ul%3E%3Cp%3EBut%20here&#39;s%20what&#39;s%20missing:%20most%20memory-safe%20languages%20sacrifice%20either%20%3Cstrong%3Eperformance%3C/strong%3E%20or%20%3Cstrong%3Eexpressiveness%3C/strong%3E.%20Rust%20achieves%20memory%20safety%20but%20has%20a%20notoriously%20steep%20learning%20curve.%20Go%20prioritizes%20simplicity%20but%20lacks%20advanced%20type%20system%20features.%3C/p%3E%3Cp%3E%3Cstrong%3EOsprey%20bridges%20this%20gap%3C/strong%3E%20by%20combining:%3C/p%3E%3Cul%3E%3Cli%3E%3Cstrong%3EMemory%20safety%3C/strong%3E%20without%20manual%20memory%20management%3C/li%3E%3Cli%3E%3Cstrong%3EFunctional%20expressiveness%3C/strong%3E%20with%20pattern%20matching%20and%20type%20inference%3C/li%3E%3Cli%3E%3Cstrong%3EZero-cost%20abstractions%3C/strong%3E%20that%20compile%20to%20efficient%20native%20code%3C/li%3E%3Cli%3E%3Cstrong%3EModern%20concurrency%3C/strong%3E%20with%20structured%20fiber%20programming%3C/li%3E%3C/ul%3E%3Ch2%20id=%22pattern-matching-the-secret-weapon%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#pattern-matching-the-secret-weapon%22%3EPattern%20Matching:%20The%20Secret%20Weapon%3C/a%3E%3C/h2%3E%3Cp%3EOne%20of%20Osprey&#39;s%20most%20powerful%20features%20is%20its%20%3Cstrong%3Eexhaustive%20pattern%20matching%3C/strong%3E%20system:%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20keyword%22%3Etype%3C/span%3E%20ApiResult%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%20%20%20Body%20%20%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20data%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20status%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20|%20ClientError%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20message%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20status%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20|%20ServerError%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20message%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20|%20NetworkDown%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20timedOut%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Ebool%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EhandleResponse%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Er%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20ApiResult%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Ematch%3C/span%3E%20r%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20Body%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20data%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20status%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22${toString(status)}%20OK:%20${data}%22%3C/span%3E%20%20%20%20ClientError%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20message%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20status%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22client%20${toString(status)}:%20${message}%22%3C/span%3E%20%20%20%20ServerError%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20message%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22server%20error:%20${message}%22%3C/span%3E%20%20%20%20NetworkDown%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20timedOut%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Ematch%3C/span%3E%20timedOut%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Etrue%3C/span%3E%20%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22request%20timed%20out%22%3C/span%3E%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Efalse%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22network%20connection%20failed%22%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3EThe%20compiler%20%3Cstrong%3Eguarantees%3C/strong%3E%20you%20handle%20every%20case.%20No%20null%20pointer%20exceptions,%20no%20unexpected%20crashes,%20no%20forgotten%20error%20conditions.%3C/p%3E%3Ch2%20id=%22the-performance-story%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#the-performance-story%22%3EThe%20Performance%20Story%3C/a%3E%3C/h2%3E%3Cp%3EMemory%20safety%20typically%20comes%20with%20runtime%20overhead%E2%80%94garbage%20collection%20pauses,%20reference%20counting%20costs,%20or%20dynamic%20checks.%20%3Cstrong%3EOsprey%20takes%20a%20different%20approach%3C/strong%3E:%3C/p%3E%3Cp%3ECompile-time%20analysis%20eliminates%20most%20runtime%20safety%20checks%20while%20providing%20%3Cstrong%3Ezero-cost%20abstractions%3C/strong%3E.%20When%20you%20write%20high-level%20functional%20code,%20the%20compiler%20generates%20efficient%20imperative%20machine%20code.%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Eadd%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Ea%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20b%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20a%20%3Cspan%20class=%22token%20operator%22%3E+%3C/span%3E%20b%3Cspan%20class=%22token%20comment%22%3E//%20High-level%20functional%20code...%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Elet%3C/span%3E%20result%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Erange%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E1%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20number%22%3E100%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20operator%22%3E|%3E%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Efilter%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3En%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20n%20%3Cspan%20class=%22token%20operator%22%3E%3E%3C/span%3E%20%3Cspan%20class=%22token%20number%22%3E0%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20operator%22%3E|%3E%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Emap%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3En%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20n%20%3Cspan%20class=%22token%20operator%22%3E*%3C/span%3E%20%3Cspan%20class=%22token%20number%22%3E2%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20operator%22%3E|%3E%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Efold%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20number%22%3E0%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20add%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20comment%22%3E//%20...compiles%20to%20a%20single%20fused%20loop%20with%20no%20intermediate%20lists.%3C/span%3E%3C/code%3E%3C/pre%3E%3Ch2%20id=%22what-makes-osprey-different%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#what-makes-osprey-different%22%3EWhat%20Makes%20Osprey%20Different%3C/a%3E%3C/h2%3E%3Ch3%20id=%22immutable-state-no-hidden-globals%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#immutable-state-no-hidden-globals%22%3E%3Cstrong%3EImmutable%20State,%20No%20Hidden%20Globals%3C/strong%3E%3C/a%3E%3C/h3%3E%3Cp%3EOsprey%20threads%20state%20explicitly%20as%20immutable%20values%20instead%20of%20hiding%20it%20in%20mutable%20globals%20%E2%80%94%20exactly%20the%20kind%20of%20shared%20state%20that%20plagues%20large%20codebases.%20A%20cache%20is%20just%20an%20immutable%20%3Ccode%3EMap%3C/code%3E%20passed%20in%20and%20returned:%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EcachedName%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Eid%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20cache%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3EMap%3C/span%3E%3Cspan%20class=%22token%20operator%22%3E&amp;lt;%3C/span%3E%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%3Cspan%20class=%22token%20operator%22%3E%3E%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Ematch%3C/span%3E%20cache%3Cspan%20class=%22token%20punctuation%22%3E[%3C/span%3Eid%3Cspan%20class=%22token%20punctuation%22%3E]%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20%20%20%20%20Success%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20value%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%20%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20value%20%20%20%20%20%20%20%20Error%20%20%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20message%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22miss%22%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3Cspan%20class=%22token%20comment%22%3E//%20Growing%20the%20cache%20returns%20a%20NEW%20map%20%E2%80%94%20old%20versions%20stay%20valid.%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Elet%3C/span%3E%20c1%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EmapSet%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20type%22%3EMap%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22u1%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22Alice%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Elet%3C/span%3E%20c2%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EmapSet%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Ec1%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22u2%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22Bob%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3C/code%3E%3C/pre%3E%3Ch3%20id=%22effect-system-for-controlled-side-effects%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#effect-system-for-controlled-side-effects%22%3E%3Cstrong%3EEffect%20System%20for%20Controlled%20Side%20Effects%3C/strong%3E%3C/a%3E%3C/h3%3E%3Cp%3ENot%20all%20operations%20are%20pure,%20but%20Osprey&#39;s%20effect%20system%20makes%20side%20effects%20%3Cstrong%3Eexplicit%20and%20controllable%3C/strong%3E.%20Effects%20are%20declared%20in%20the%20signature%20with%20%3Ccode%3E![...]%3C/code%3E%20and%20performed%20with%20%3Ccode%3Eperform%3C/code%3E;%20a%20handler%20decides%20what%20they%20actually%20do:%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20keyword%22%3Eeffect%3C/span%3E%20Db%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20insert%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3EUser%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EsaveUser%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Euser%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20User%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E!%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E[%3C/span%3EDb%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20Logger%3Cspan%20class=%22token%20punctuation%22%3E]%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Eperform%3C/span%3E%20Logger%3Cspan%20class=%22token%20punctuation%22%3E.%3C/span%3E%3Cspan%20class=%22token%20function%22%3Elog%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20string%22%3E%22validating%20user%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Elet%3C/span%3E%20id%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Eperform%3C/span%3E%20Db%3Cspan%20class=%22token%20punctuation%22%3E.%3C/span%3E%3Cspan%20class=%22token%20function%22%3Einsert%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Euser%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Eperform%3C/span%3E%20Logger%3Cspan%20class=%22token%20punctuation%22%3E.%3C/span%3E%3Cspan%20class=%22token%20function%22%3Elog%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20string%22%3E%22saved%20${toString(id)}%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20id%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3C/code%3E%3C/pre%3E%3Ch2%20id=%22the-road-ahead%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#the-road-ahead%22%3EThe%20Road%20Ahead%3C/a%3E%3C/h2%3E%3Cp%3EThe%20momentum%20is%20undeniable:%3C/p%3E%3Cul%3E%3Cli%3E%3Cstrong%3EFinancial%20institutions%3C/strong%3E%20are%20adopting%20functional%20languages%20for%20trading%20systems%3C/li%3E%3Cli%3E%3Cstrong%3ECloud%20providers%3C/strong%3E%20are%20investing%20in%20memory-safe%20infrastructure%3C/li%3E%3Cli%3E%3Cstrong%3EGovernments%3C/strong%3E%20are%20mandating%20memory%20safety%20for%20critical%20systems%3C/li%3E%3Cli%3E%3Cstrong%3EAI%20companies%3C/strong%3E%20need%20reliable,%20concurrent%20systems%20for%20model%20serving%3C/li%3E%3C/ul%3E%3Cp%3E%3Cstrong%3EOsprey%20is%20designed%20for%20this%20future.%3C/strong%3E%20We&#39;re%20not%20just%20another%20programming%20language%E2%80%94we&#39;re%20a%20response%20to%20the%20fundamental%20challenges%20facing%20software%20development%20in%20the%202020s%20and%20beyond.%3C/p%3E%3Cp%3EAs%20the%20industry%20grapples%20with%20AI-accelerated%20vulnerability%20discovery,%20climate-conscious%20computing,%20and%20the%20need%20for%20massively%20concurrent%20systems,%20%3Cstrong%3Efunctional%20programming%20with%20memory%20safety%20isn&#39;t%20just%20an%20advantage%E2%80%94it&#39;s%20becoming%20a%20requirement%3C/strong%3E.%3C/p%3E%3Cp%3EThe%20question%20isn&#39;t%20whether%20the%20industry%20will%20adopt%20memory-safe%20functional%20languages.%20%3Cstrong%3EThe%20question%20is%20whether%20you&#39;ll%20be%20ready%20when%20it%20does.%3C/strong%3E%3C/p%3E%3Chr%3E%3Cp%3E%3Cem%3EWant%20to%20try%20Osprey%20yourself?%20Check%20out%20our%20%3Ca%20href=%22/playground/%22%3Einteractive%20playground%3C/a%3E%20or%20dive%20into%20the%20%3Ca%20href=%22/docs/%22%3Edocumentation%3C/a%3E%20to%20get%20started.%3C/em%3E%3C/p%3E%3Cblockquote%3E%3Cp%3E%3Cstrong%3EEditor&#39;s%20note%20(updated%202026-06-20):%3C/strong%3E%20This%20post%20was%20first%20published%20in%20January%202025,%20early%20in%20Osprey&#39;s%20development.%20Osprey&#39;s%20syntax%20has%20evolved%20considerably%20since%20then%20%E2%80%94%20among%20other%20changes,%20the%20language%20dropped%20%3Ccode%3EOption%3C/code%3E/%3Ccode%3ESome%3C/code%3E/%3Ccode%3ENone%3C/code%3E%20in%20favour%20of%20explicit%20union%20variants,%20settled%20on%20%3Ccode%3Espawn%3C/code%3E/%3Ccode%3Eawait(...)%3C/code%3E%20for%20fibers,%20%3Ccode%3E=&amp;gt;%3C/code%3E%20for%20match%20arms,%20expression-bodied%20functions,%20and%20lowercase%20primitive%20types%20(%3Ccode%3Eint%3C/code%3E/%3Ccode%3Estring%3C/code%3E/%3Ccode%3Ebool%3C/code%3E).%20The%20code%20samples%20above%20have%20been%20revised%20to%20match%20the%20current%20language.%20The%20original%20article%20is%20preserved%20unchanged%20in%20this%20site&#39;s%20Git%20history%20%E2%80%94%20browse%20the%20%3Ca%20href=%22https://github.com/Nimblesite/osprey%22%3Erepository%3C/a%3E%20and%20view%20this%20file&#39;s%20history%20to%20read%20it%20exactly%20as%20first%20published.%3C/p%3E%3C/blockquote%3E</content>
    <summary>See how memory-safe languages, immutable data, and functional concurrency address common systems vulnerabilities and support resilient software design.</summary>
  </entry>
  <entry>
    <title>Persistent Collections in Osprey: Immutable List and Map with Structural Sharing</title>
    <link href="https://www.ospreylang.dev/blog/2026-05-17-persistent-collections/"/>
    <id>https://www.ospreylang.dev/blog/2026-05-17-persistent-collections/</id>
    <updated>2026-05-17T00:00:00.000Z</updated>
    <content type="html">https://www.ospreylang.dev/%3Cp%3EOsprey%20now%20has%20first-class%20persistent%20collections.%20%3Cstrong%3E%3Ccode%3EList&amp;lt;T&amp;gt;%3C/code%3E%20and%20%3Ccode%3EMap&amp;lt;K,%20V&amp;gt;%3C/code%3E%20are%20immutable%3C/strong%3E,%20but%20&amp;quot;modifying&amp;quot;%20them%20is%20cheap%20because%20the%20runtime%20shares%20structure%20between%20versions.%20This%20post%20walks%20through%20what%20landed,%20how%20it%20works%20under%20the%20hood,%20and%20which%20papers%20we%20leaned%20on.%3C/p%3E%3Ch2%20id=%22the-user-facing-surface%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#the-user-facing-surface%22%3EThe%20user-facing%20surface%3C/a%3E%3C/h2%3E%3Cp%3E%3Ccode%3EList&amp;lt;T&amp;gt;%3C/code%3E%20is%20backed%20by%20a%2032-way%20bitmapped%20vector%20trie%20with%20a%20tail%20buffer%20%E2%80%94%20the%20same%20design%20as%20Clojure&#39;s%20%3Ccode%3EPersistentVector%3C/code%3E%20and%20Scala&#39;s%20%3Ccode%3Eimmutable.Vector%3C/code%3E.%20Every%20operation%20returns%20a%20%3Cem%3Enew%3C/em%3E%20list%20that%20shares%20almost%20all%20of%20its%20nodes%20with%20the%20old%20one:%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20keyword%22%3Elet%3C/span%3E%20xs%20%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3ElistAppend%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20function%22%3ElistAppend%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20type%22%3EList%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20number%22%3E10%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20number%22%3E20%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Elet%3C/span%3E%20xs1%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3ElistAppend%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Exs%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20number%22%3E30%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Elet%3C/span%3E%20xs2%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3ElistAppend%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Exs%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20number%22%3E99%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20function%22%3ElistLength%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Exs%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%3Cspan%20class=%22token%20comment%22%3E//%202%20%20%E2%80%94%20xs%20is%20untouched%3C/span%3E%3Cspan%20class=%22token%20function%22%3ElistLength%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Exs1%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%3Cspan%20class=%22token%20comment%22%3E//%203%20%20%E2%80%94%20extended%20with%2030%3C/span%3E%3Cspan%20class=%22token%20function%22%3ElistLength%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Exs2%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%3Cspan%20class=%22token%20comment%22%3E//%203%20%20%E2%80%94%20independent%20branch%20with%2099%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3E%3Ccode%3EMap&amp;lt;K,%20V&amp;gt;%3C/code%3E%20uses%20a%20%3Cstrong%3EHash%20Array%20Mapped%20Trie%3C/strong%3E%20(HAMT)%20per%20Phil%20Bagwell&#39;s%202000%20paper,%20%3Ca%20href=%22https://lampwww.epfl.ch/papers/idealhashtrees.pdf%22%3E%3Cem%3EIdeal%20Hash%20Trees%3C/em%3E%3C/a%3E.%20Each%20internal%20node%20holds%20a%2032-bit%20bitmap%20of%20present%20slots%20plus%20a%20packed%20array%20of%20children%20%E2%80%94%20no%20wasted%20pointer%20slots%20%E2%80%94%20so%20lookup,%20insert%20and%20remove%20are%20O(log%E2%82%83%E2%82%82%20n)%20expected:%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20keyword%22%3Elet%3C/span%3E%20m%20%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EmapSet%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20function%22%3EmapSet%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20type%22%3EMap%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22alice%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20number%22%3E25%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22bob%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20number%22%3E30%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Elet%3C/span%3E%20m1%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EmapSet%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Em%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22charlie%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20number%22%3E35%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Elet%3C/span%3E%20m2%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EmapRemove%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Em%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22alice%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20function%22%3EmapLength%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Em%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%3Cspan%20class=%22token%20comment%22%3E//%202%20%20%E2%80%94%20m%20is%20untouched%3C/span%3E%3Cspan%20class=%22token%20function%22%3EmapLength%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Em1%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%3Cspan%20class=%22token%20comment%22%3E//%203%3C/span%3E%3Cspan%20class=%22token%20function%22%3EmapLength%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Em2%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%3Cspan%20class=%22token%20comment%22%3E//%201%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3EBoth%20collections%20are%20full%20participants%20in%20the%20operator%20algebra:%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3Exs%20%3Cspan%20class=%22token%20operator%22%3E+%3C/span%3E%20xs1%20%20%20%20%20%3Cspan%20class=%22token%20comment%22%3E//%20O(n+m)%20list%20concat%20via%20listConcat%3C/span%3Em%20%3Cspan%20class=%22token%20operator%22%3E+%3C/span%3E%20m1%20%20%20%20%20%20%20%3Cspan%20class=%22token%20comment%22%3E//%20right-biased%20union%20via%20mapMerge%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3EThe%20%3Ccode%3E+%3C/code%3E%20operator%20dispatches%20on%20the%20inferred%20type%20%E2%80%94%20list%20operands%20route%20to%20%3Ccode%3Eosprey_list_concat%3C/code%3E,%20map%20operands%20to%20%3Ccode%3Eosprey_map_merge%3C/code%3E,%20and%20integer/string%20operands%20stay%20on%20the%20existing%20fast%20paths.%3C/p%3E%3Ch2%20id=%22why-structural-sharing-matters%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#why-structural-sharing-matters%22%3EWhy%20structural%20sharing%20matters%3C/a%3E%3C/h2%3E%3Cp%3EA%20naive%20immutable%20list%20copies%20the%20whole%20array%20on%20every%20append:%20O(n)%20per%20write,%20O(n%C2%B2)%20to%20build%20a%20million-element%20list.%20That&#39;s%20the%20kind%20of%20complexity%20that%20pushes%20people%20back%20to%20mutable%20state.%3C/p%3E%3Cp%3EThe%20bitmapped%20trie%20does%20something%20cleverer.%20The%20list%20is%20a%20%3Cem%3Etree%3C/em%3E%20with%2032-way%20branching.%20To%20append,%20we%20copy%20at%20most%20one%20%3Cem%3Epath%3C/em%3E%20from%20the%20root%20down%20to%20the%20affected%20leaf%20%E2%80%94%20roughly%20%3Cstrong%3Elog%E2%82%83%E2%82%82%20n%20nodes%3C/strong%3E,%20each%20holding%2032%20slots.%20For%20a%20million-element%20list,%20that&#39;s%204%20levels%20of%2032%20pointer%20copies%20%E2%80%94%20~128%20pointer%20writes%20per%20append.%20The%20rest%20of%20the%20tree%20is%20shared%20with%20every%20previous%20version%20of%20the%20list.%3C/p%3E%3Cp%3EThe%20same%20idea%20drives%20the%20HAMT:%20an%20insert%20path-copies%20one%20branch%20down%20to%20where%20the%20new%20key%20lands.%20Old%20versions%20keep%20pointing%20to%20the%20unmodified%20subtrees,%20so%20they%20survive%20every%20&amp;quot;mutation&amp;quot;%20without%20paying%20for%20one.%3C/p%3E%3Cp%3EFor%20more%20background:%3C/p%3E%3Cul%3E%3Cli%3EChris%20Okasaki,%20%3Cem%3EPurely%20Functional%20Data%20Structures%3C/em%3E%20(Cambridge%20UP,%201998)%20%E2%80%94%20the%20canonical%20reference.%3C/li%3E%3Cli%3E%3Ca%20href=%22https://en.wikipedia.org/wiki/Persistent_data_structure%22%3EWikipedia:%20Persistent%20data%20structure%3C/a%3E%20%E2%80%94%20covers%20path-copying.%3C/li%3E%3Cli%3E%3Ca%20href=%22https://clojure.org/reference/data_structures%22%3EClojure&#39;s%20data%20structures%20reference%3C/a%3E%20%E2%80%94%20Rich%20Hickey&#39;s%20adaptation%20of%20Bagwell&#39;s%20HAMT.%3C/li%3E%3C/ul%3E%3Ch2%20id=%22builders-and-the-transient-escape-hatch%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#builders-and-the-transient-escape-hatch%22%3EBuilders%20and%20the%20transient%20escape%20hatch%3C/a%3E%3C/h2%3E%3Cp%3EThere&#39;s%20a%20tension%20in%20any%20persistent%20collection:%20when%20you&#39;re%20%3Cstrong%3Ebuilding%3C/strong%3E%20a%20large%20collection%20from%20scratch,%20each%20step%20doesn&#39;t%20need%20to%20be%20observable%20as%20a%20persistent%20snapshot.%20Path-copying%20every%20push%20is%20wasted%20work.%3C/p%3E%3Cp%3EClojure%20solves%20this%20with%20%3Ca%20href=%22https://clojure.org/reference/transients%22%3Etransients%3C/a%3E%20%E2%80%94%20a%20temporary%20mutable%20window%20you%20can%20write%20into,%20then%20&amp;quot;seal&amp;quot;%20back%20into%20a%20persistent%20collection.%20Hickey&#39;s%20own%20benchmark%20shows%20~34%%20speedup%20on%20a%20million-element%20build.%3C/p%3E%3Cp%3EOsprey%20uses%20the%20same%20trick%20internally.%20The%20runtime%20exposes%20a%20%3Ccode%3EBuilder%3C/code%3E%20type%20that%20mutates%20in%20place,%20and%20the%20literal%20lowering%20(%3Ccode%3E[1,%202,%203]%3C/code%3E)%20drives%20a%20builder%20behind%20the%20scenes.%20%3Cstrong%3EThe%20transient%20itself%20is%20never%20exposed%20to%20user%20code%3C/strong%3E,%20so%20the%20functional%20surface%20stays%20clean.%3C/p%3E%3Ch2%20id=%22stream-fusion-still-applies%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#stream-fusion-still-applies%22%3EStream%20fusion%20still%20applies%3C/a%3E%3C/h2%3E%3Cp%3EOsprey&#39;s%20iterator%20family%20(%3Ccode%3Emap%3C/code%3E,%20%3Ccode%3Efilter%3C/code%3E,%20%3Ccode%3Efold%3C/code%3E,%20%3Ccode%3EforEach%3C/code%3E)%20already%20does%20compile-time%20stream%20fusion%20in%20the%20style%20of%20Coutts,%20Leshchinskiy%20&amp;amp;%20Stewart&#39;s%20%3Ca%20href=%22https://www.cs.tufts.edu/~nr/cs257/archive/duncan-coutts/stream-fusion.pdf%22%3E%3Cem%3EStream%20Fusion:%20From%20Lists%20to%20Streams%20to%20Nothing%20at%20All%3C/em%3E%3C/a%3E%20(ICFP%202007).%20With%20collections%20in%20the%20iterator%20family,%20a%20chain%20like:%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3Exs%20%3Cspan%20class=%22token%20operator%22%3E|%3E%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Efilter%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3EisEven%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E|%3E%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Emap%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Edouble%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E|%3E%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EforEach%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Eprint%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3Ecompiles%20to%20a%20single%20loop%20with%20no%20intermediate%20list%20materialised%20%E2%80%94%20the%20same%20zero-cost%20abstraction%20we%20already%20had%20for%20ranges,%20now%20applied%20to%20user-built%20collections.%3C/p%3E%3Ch2%20id=%22whats-tested%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#whats-tested%22%3EWhat&#39;s%20tested%3C/a%3E%3C/h2%3E%3Cp%3EEvery%20behaviour%20above%20is%20locked%20in%20by%20tests%20at%20two%20levels:%3C/p%3E%3Cul%3E%3Cli%3E%3Cp%3E%3Cstrong%3EC%20runtime%3C/strong%3E:%2033%20vanilla-C%20unit%20tests%20with%20%3Ccode%3Eassert()%3C/code%3E%20in%20%3Ca%20href=%22https://github.com/Nimblesite/osprey/tree/main/compiler/runtime/list_tests.c%22%3E%3Ccode%3Ecompiler/runtime/list_tests.c%3C/code%3E%3C/a%3E%20and%20%3Ca%20href=%22https://github.com/Nimblesite/osprey/tree/main/compiler/runtime/map_tests.c%22%3E%3Ccode%3Ecompiler/runtime/map_tests.c%3C/code%3E%3C/a%3E.%20These%20cover%20empty%20edges,%20trie-level%20transitions%20at%2032%20/%2033%20/%201024%20/%201025%20elements,%20a%2010%20000-element%20stress,%20hash%20collisions,%20structural-sharing%20invariants%20(&amp;quot;mutate%20one%20version,%20the%20others%20stay%20intact&amp;quot;),%20and%20equivalence%20between%20builder%20construction%20and%20incremental%20%3Ccode%3Eappend%3C/code%3E.%3C/p%3E%3C/li%3E%3Cli%3E%3Cp%3E%3Cstrong%3EEnd-to-end%20Osprey%20programs%3C/strong%3E:%2012%20%3Ccode%3E.osp%3C/code%3E%20files%20in%20%3Ca%20href=%22https://github.com/Nimblesite/osprey/tree/main/examples/tested/basics/lists%22%3E%3Ccode%3Eexamples/tested/basics/lists/%3C/code%3E%3C/a%3E.%20Each%20one%20actually%20runs%20through%20the%20JIT%20and%20its%20%3Ccode%3Estdout%3C/code%3E%20is%20byte-compared%20against%20a%20checked-in%20%3Ccode%3E.expectedoutput%3C/code%3E.%20Any%20regression%20in%20length,%20value,%20iteration%20order%20or%20persistence%20breaks%20the%20build.%3C/p%3E%3C/li%3E%3C/ul%3E%3Ch2%20id=%22whats-deferred%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#whats-deferred%22%3EWhat&#39;s%20deferred%3C/a%3E%3C/h2%3E%3Cp%3EA%20few%20items%20from%20the%20%3Ca%20href=%22https://github.com/Nimblesite/osprey/tree/main/docs/plans/collections.md%22%3Ecollections%20plan%3C/a%3E%20are%20explicitly%20deferred:%3C/p%3E%3Cul%3E%3Cli%3E%3Cstrong%3E%3Ccode%3E[head,%20...tail]%3C/code%3E%20and%20subset%20map%20patterns%3C/strong%3E%20in%20%3Ccode%3Ematch%3C/code%3E%20%E2%80%94%20requires%20grammar%20additions%20and%20a%20parser%20regeneration%20cycle.%3C/li%3E%3Cli%3E%3Cstrong%3EList%20comprehensions%3C/strong%3E%20(%3Ccode%3E[x%20*%20x%20for%20x%20in%20xs]%3C/code%3E)%20%E2%80%94%20same%20grammar%20pipeline.%3C/li%3E%3Cli%3E%3Cstrong%3ENames%20collapsing%20to%20%3Ccode%3Elength%3C/code%3E%20/%20%3Ccode%3Econtains%3C/code%3E%3C/strong%3E%20without%20a%20%3Ccode%3Elist%3C/code%3E/%3Ccode%3Emap%3C/code%3E%20prefix%20%E2%80%94%20waiting%20on%20universal%20function%20call%20syntax%20(UFCS),%20which%20is%20in%20flight.%3C/li%3E%3C/ul%3E%3Cp%3EThe%20plan%20document%20tracks%20each%20of%20these%20with%20its%20specific%20blocker.%3C/p%3E%3Ch2%20id=%22try-it%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#try-it%22%3ETry%20it%3C/a%3E%3C/h2%3E%3Cp%3EThe%20collections%20runtime%20ships%20in%20%3Ccode%3E0.2.0%3C/code%3E.%20Install%20it%20on%20macOS%20or%20Linux:%3C/p%3E%3Cpre%20class=%22language-bash%22%3E%3Ccode%20class=%22language-bash%22%3Ebrew%20%3Cspan%20class=%22token%20function%22%3Einstall%3C/span%3E%20nimblesite/tap/osprey%3C/code%3E%3C/pre%3E%3Cp%3E%E2%80%A6and%20the%20%3Ca%20href=%22/playground/%22%3Eplayground%3C/a%3E%20supports%20the%20new%20builtins%20too.%20Build%20something%20stateful%20%E2%80%94%20a%20route%20table,%20an%20event%20log,%20an%20undo%20stack%20%E2%80%94%20and%20see%20how%20the%20persistent%20semantics%20change%20the%20shape%20of%20the%20code.%3C/p%3E</content>
    <summary>Explore Osprey’s persistent List and Map, their vector-trie and HAMT internals, structural sharing, complexity, API, and current implementation tradeoffs.</summary>
  </entry>
  <entry>
    <title>Osprey Flavors: One Core, Two Flavors, Zero Compromise</title>
    <link href="https://www.ospreylang.dev/blog/2026-06-30-osprey-flavors/"/>
    <id>https://www.ospreylang.dev/blog/2026-06-30-osprey-flavors/</id>
    <updated>2026-06-30T00:00:00.000Z</updated>
    <content type="html">https://www.ospreylang.dev/%3Cp%3EWhen%20I%20started%20working%20on%20Osprey,%20the%20dream%20was%20%3Cem%3Ezero%20compromise%3C/em%3E.%20I%20think%20the%20biggest%20shame%20about%20the%20most%20popular%20languages%20is%20that%20they%20compromise.%20The%20language%20designers%20make%20decisions%20for%20adoption%20but%20end%20up%20watering%20down%20the%20original%20spirit%20of%20the%20language%20because%20of%20this.%20I%20didn&#39;t%20want%20this%20for%20Osprey.%20I%20wanted%20something%20else.%20I%20wanted%20the%20language%20to%20be%20exactly%20what%20I%20wanted%20it%20to%20be%20and%20to%20have%20all%20the%20performance,%20safety%20and%20elegance%20of%20the%20other%20great,%20modern%20languages.%3C/p%3E%3Cp%3EI%20found%20out%20immediately%20that%20there%20was%20a%20big%20catch%20to%20this.%20You%20cannot%20please%20everyone.%20It&#39;s%20not%20just%20about%20aesthetics.%20You%20have%20to%20make%20tradeoffs%20when%20you%20design%20syntax.%20Certain%20decisions%20push%20you%20in%20directions%20that%20have%20rippling%20effects.%20The%20most%20obvious%20decision%20is%20the%20decision%20on%20whether%20to%20use%20indentation%20or%20braces%20to%20specify%20blocks.%3C/p%3E%3Cp%3EMany%20programmers%20that%20are%20accustomed%20to%20C%20style%20languages%20like%20C#,%20Java,%20Dart%20and%20so%20on%20find%20indentation%20based%20syntax%20to%20be%20too%20uncomfortable%20to%20use.%20But,%20indentation%20based%20languages%20mean%20you%20can%20remove%20a%20lot%20of%20symbols%20and%20reduce%20visual%20noise.%20At%20the%20end%20of%20the%20day,%20it&#39;s%20cleaner%20but%20it%20also%20alienates%20a%20whole%20group%20of%20people.%20Many%20people%20wouldn&#39;t%20touch%20Osprey%20because%20it%20looks%20like%20code%20from%20another%20tribe.%3C/p%3E%3Cp%3EEvery%20language%20picks%20a%20side,%20and%20every%20side%20loses%20someone.%20Curly%20braces%20or%20significant%20whitespace.%20%3Ccode%3Efn%20add(x,%20y)%3C/code%3E%20or%20%3Ccode%3Eadd%20x%20y%3C/code%3E.%20The%20systems%20programmer%20who%20wants%20explicit%20blocks%20and%20named%20arguments,%20versus%20the%20FP%20devotee%20who%20wants%20layout%20and%20curry-by-default.%20Pick%20braces%20and%20the%20Haskell%20crowd%20wrinkles%20their%20nose;%20pick%20layout%20and%20the%20C%20crowd%20walks%20away.%20The%20syntax%20wars%20are%20real,%20and%20they%20force%20you%20into%20a%20tribe%20before%20you&#39;ve%20written%20a%20line.%3C/p%3E%3Cp%3EI%20had%20encountered%20dilemmas%20several%20times%20while%20build%20Osprey%20and%20the%20answer%20was%20always%20&amp;quot;put%20an%20abstraction%20here&amp;quot;.%20My%20thinking%20was%20&amp;quot;Can%20we%20defer%20this%20decision?%20Can%20we%20make%20this%20aspect%20of%20the%20language%20pluggable?&amp;quot;.%20We%20shouldn&#39;t%20bake%20decisions%20into%20the%20language%20early.%20We%20should%20allow%20people%20building%20with%20Osprey%20to%20make%20their%20own%20decisions.%20And,%20in%20many%20cases,%20I%20found%20that%20leaving%20an%20abstraction%20where%20the%20develop%20could%20make%20their%20own%20call%20was%20the%20exact%20right%20decision.%3C/p%3E%3Cp%3EThen,%20I%20asked%20the%20question%20&amp;quot;Can%20we%20make%20the%20syntax%20pluggable?&amp;quot;.%20Well,%20it%20turns%20out%20that%20we%20absolutely%20can%20and%20it&#39;s%20barely%20even%20a%20for%20the%20compiler.%20When%20we%20parse%20code,%20we%20convert%20the%20code%20into%20a%20Concrete%20Syntax%20Tree%20(CST).%20This%20is%20the%20first%20pass%20that%20just%20converts%20the%20code%20unprocessed%20into%20in-memory%20data.%20Then,%20that%20data%20is%20converted%20to%20an%20Abstract%20Syntax%20Tree%20(AST).%20This%20is%20the%20processed%20syntax%20that%20can%20be%20readily%20converted%20to%20code.%3C/p%3E%3Cp%3EIt%20turns%20out%20that%20we%20can%20basically%20swap%20any%20CST%20in%20front%20of%20the%20AST.%20That&#39;s%20how%20we%20get%20flavors.%20It&#39;s%20a%20powerful%20concept.%20There%20is%20nothing%20about%20any%20language%20that%20weds%20it%20to%20the%20syntax.%20The%20syntax%20is%20basically%20just%20a%20taste%20aspect%20of%20the%20language.%20So,%20I%20made%20the%20obvious%20choice%20to%20allow%20multiple%20flavor%20syntaxes%20instead%20of%20tying%20Osprey%20to%20one%20view%20of%20the%20world.%3C/p%3E%3Cp%3EOsprey&#39;s%20answer%20is%20to%20stop%20pretending%20there&#39;s%20one%20right%20answer.%20%3Cstrong%3EOne%20core.%20Two%20flavors.%20Zero%20compromise.%3C/strong%3E%3C/p%3E%3Ch2%20id=%22the-problem-syntax-forces-a-tribe%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#the-problem-syntax-forces-a-tribe%22%3EThe%20problem:%20syntax%20forces%20a%20tribe%3C/a%3E%3C/h2%3E%3Cp%3EThe%20FP-snob-versus-systems-programmer%20divide%20is%20mostly%20about%20spelling.%20The%20ideas%20%E2%80%94%20algebraic%20data%20types,%20exhaustive%20matching,%20immutability,%20effects%20%E2%80%94%20are%20not%20in%20dispute.%20What&#39;s%20in%20dispute%20is%20whether%20%3Ccode%3Edo%3C/code%3E-blocks%20should%20have%20braces,%20whether%20application%20should%20need%20parentheses,%20whether%20a%20function%20with%20two%20arguments%20is%20one%20value%20or%20two.%20These%20are%20aesthetic%20and%20ergonomic%20preferences,%20and%20they%20are%20%3Cem%3Estrong%3C/em%3E%20preferences.%20Telling%20someone%20their%20preferred%20surface%20is%20wrong%20is%20how%20you%20lose%20them.%3C/p%3E%3Cp%3EMost%20languages%20resolve%20this%20by%20declaring%20a%20winner%20and%20grudgingly%20bolting%20on%20the%20loser%20as%20an%20afterthought%20%E2%80%94%20a%20&amp;quot;lite&amp;quot;%20mode,%20an%20optional%20layout%20extension,%20a%20deprecated%20legacy%20syntax%20kept%20alive%20for%20migration.%20The%20afterthought%20is%20always%20second-class,%20and%20everybody%20can%20tell.%3C/p%3E%3Ch2%20id=%22ospreys-answer-flavors%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#ospreys-answer-flavors%22%3EOsprey&#39;s%20answer:%20flavors%3C/a%3E%3C/h2%3E%3Cp%3EOsprey%20ships%20%3Cstrong%3Etwo%20first-class,%20permanent%20syntaxes%3C/strong%3E%20called%20flavors.%20Neither%20is%20the%20watered-down%20one.%3C/p%3E%3Cul%3E%3Cli%3E%3Cstrong%3EDefault%20flavor%20(%3Ccode%3E.osp%3C/code%3E)%3C/strong%3E%20%E2%80%94%20C-style%20braces,%20%3Ccode%3Efn%3C/code%3E,%20%3Ccode%3Ef(x:%20a,%20y:%20b)%3C/code%3E%20calls%20with%20named%20arguments.%20Explicit,%20familiar,%20block-structured.%20This%20is%20the%20surface%20a%20systems%20programmer%20reaches%20for.%20Fully%20implemented%20today.%3C/li%3E%3Cli%3E%3Cstrong%3EML%20flavor%20(%3Ccode%3E.ospml%3C/code%3E)%3C/strong%3E%20%E2%80%94%20offside-rule%20layout%20(indentation,%20no%20braces),%20curry-by-default,%20whitespace%20application%20%3Ccode%3Ef%20a%20b%3C/code%3E,%20%3Ccode%3E&#92;x%20=&amp;gt;%20e%3C/code%3E%20lambdas,%20%3Ccode%3E:=%3C/code%3E%20mutation,%20%3Ccode%3E-&amp;gt;%3C/code%3E%20for%20types%20and%20%3Ccode%3E=&amp;gt;%3C/code%3E%20for%20clauses.%20Terse,%20expression-first,%20ML/Haskell-shaped.%20This%20is%20the%20surface%20an%20FP%20devotee%20reaches%20for.%20Fully%20implemented%20today.%3C/li%3E%3C/ul%3E%3Cp%3EThe%20point%20is%20%3Cstrong%3Eno%20compromise%3C/strong%3E.%20The%20ML%20flavor%20is%20not%20&amp;quot;braces%20optional.&amp;quot;%20The%20Default%20flavor%20is%20not%20deprecated%20or%20transitional.%20Each%20surface%20goes%20all%20the%20way%20in%20its%20own%20direction.%20Systems%20programmers%20get%20real%20braces%20and%20real%20named%20arguments;%20FP%20folks%20get%20real%20layout%20and%20real%20currying.%20Nobody%20is%20asked%20to%20swallow%20the%20other%20camp&#39;s%20spelling.%20The%20language%20belongs%20to%20%3Cem%3Eyour%3C/em%3E%20tribe%20%E2%80%94%20pick%20your%20flavor%20and%20go%20all%20in.%3C/p%3E%3Cp%3EHere&#39;s%20the%20ML%20flavor%20saying%20hello%20%E2%80%94%20this%20runs%20today:%3C/p%3E%3Cpre%20class=%22language-osprey-ml%22%3E%3Ccode%20class=%22language-osprey-ml%22%3Egreeting%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22Hello%20from%20the%20ML%20flavor%22%3C/span%3Eprint%20greetingprint%20%3Cspan%20class=%22token%20string%22%3E%222%20+%203%20=%20${2%20+%203}%22%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3ENo%20%3Ccode%3Efn%3C/code%3E,%20no%20braces,%20no%20parentheses%20around%20the%20print%20argument.%20Layout%20and%20whitespace%20application%20all%20the%20way%20down.%3C/p%3E%3Ch2%20id=%22how-it-actually-works%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#how-it-actually-works%22%3EHow%20it%20actually%20works%3C/a%3E%3C/h2%3E%3Cp%3EA%20flavor%20is%20not%20a%20preprocessor%20or%20a%20transpiler%20bolted%20onto%20a%20host%20language.%20Each%20flavor%20is%20a%20%3Cstrong%3Eparser%20plus%20a%20lowerer%3C/strong%3E%20that%20converge%20on%20%3Cstrong%3Eone%20canonical%20AST%3C/strong%3E%20%E2%80%94%20%3Ccode%3Eosprey_ast::Program%3C/code%3E.%20After%20lowering,%20there%20is%20exactly%20one%20type%20checker,%20one%20effect%20system,%20one%20optimiser,%20one%20LLVM/wasm%20backend.%20None%20of%20them%20know%20which%20flavor%20you%20wrote.%20The%20flavor%20is%20gone%20by%20the%20time%20any%20analysis%20runs.%3C/p%3E%3Cp%3EThat&#39;s%20what%20makes%20the%20&amp;quot;no%20compromise&amp;quot;%20claim%20more%20than%20a%20slogan:%20both%20surfaces%20meet%20at%20the%20same%20tree,%20so%20both%20get%20the%20same%20Hindley-Milner%20inference,%20typed%20effect%20operations,%20and%20the%20same%20performance.%20There%20is%20no%20second-class%20path.%3C/p%3E%3Cp%3EThe%20one%20honest%20difference%20between%20the%20surfaces%20is%20currying,%20and%20it&#39;s%20machine-checked.%20In%20ML,%20every%20function%20is%20curried%20by%20default:%3C/p%3E%3Cpre%20class=%22language-osprey-ml%22%3E%3Ccode%20class=%22language-osprey-ml%22%3Einc%20%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3Einc%20x%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20x%20%3Cspan%20class=%22token%20operator%22%3E+%3C/span%3E%20%3Cspan%20class=%22token%20number%22%3E1%3C/span%3Eadd%20%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3Eadd%20x%20y%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20x%20%3Cspan%20class=%22token%20operator%22%3E+%3C/span%3E%20y%3Cspan%20class=%22token%20comment%22%3E//%20partial%20application%20falls%20straight%20out%20of%20currying:%3C/span%3EaddTen%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20add%20%3Cspan%20class=%22token%20number%22%3E10%3C/span%3Eanswer%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20addTen%20%3Cspan%20class=%22token%20number%22%3E32%3C/span%3E%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20comment%22%3E//%2042%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3EThat%20ML%20%3Ccode%3Eadd%20x%20y%3C/code%3E%20lowers%20to%20%3Cem%3Eexactly%3C/em%3E%20the%20same%20canonical%20AST%20as%20this%20Default-flavor%20explicit-curry%20definition:%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20comment%22%3E//%20Default%20flavor%20(.osp):%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Eadd%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Ex%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Ey%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20x%20%3Cspan%20class=%22token%20operator%22%3E+%3C/span%3E%20y%3Cspan%20class=%22token%20comment%22%3E//%20ML%20flavor%20(.ospml)%20%E2%80%94%20identical%20canonical%20AST:%3C/span%3Eadd%20x%20y%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20x%20%3Cspan%20class=%22token%20operator%22%3E+%3C/span%3E%20y%3C/code%3E%3C/pre%3E%3Cp%3EWe%20have%20a%20test%20that%20asserts%20the%20two%20produce%20the%20same%20tree.%20Note%20the%20precision%20here:%20ML%20%3Ccode%3Eadd%20x%20y%3C/code%3E%20equals%20the%20%3Cem%3Eexplicit-curry%3C/em%3E%20Default%20form,%20not%20the%20multi-parameter%20%3Ccode%3Efn%20add(x,%20y)%3C/code%3E.%20The%20latter%20is%20deliberately%20a%20different%20value%20%E2%80%94%20a%20single%20two-argument%20function,%20not%20a%20chain.%20The%20flavors%20converge%20where%20they%20should%20and%20stay%20distinct%20where%20the%20semantics%20genuinely%20differ.%3C/p%3E%3Cp%3EThe%20ML%20surface%20carries%20its%20FP%20shape%20all%20the%20way%20through.%20Layout-driven%20%3Ccode%3Ematch%3C/code%3E:%3C/p%3E%3Cpre%20class=%22language-osprey-ml%22%3E%3Ccode%20class=%22language-osprey-ml%22%3Eclassify%20n%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Ematch%3C/span%3E%20n%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20number%22%3E0%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22zero%22%3C/span%3E%20%20%20%20%20%20%20%20%3Cspan%20class=%22token%20number%22%3E1%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22one%22%3C/span%3E%20%20%20%20%20%20%20%20_%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20string%22%3E%22many%22%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3EHigher-order%20functions%20and%20%3Ccode%3EResult%3C/code%3E%20payload%20matching%20(integer%20division%20and%20mod%20return%20%3Ccode%3EResult&amp;lt;int,%20MathError&amp;gt;%3C/code%3E,%20so%20you%20match%20the%20payload):%3C/p%3E%3Cpre%20class=%22language-osprey-ml%22%3E%3Ccode%20class=%22language-osprey-ml%22%3Etwice%20%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Eint%3C/span%3Etwice%20f%20x%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Ef%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Ef%20x%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3Ebump%20x%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20x%20%3Cspan%20class=%22token%20operator%22%3E+%3C/span%3E%20%3Cspan%20class=%22token%20number%22%3E10%3C/span%3EsafeMod%20a%20b%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Ematch%3C/span%3E%20a%20%3Cspan%20class=%22token%20operator%22%3E%%3C/span%3E%20b%20%20%20%20%20%20%20%20Success%20value%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20value%20%20%20%20%20%20%20%20Error%20e%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3C/span%3E%3Cspan%20class=%22token%20number%22%3E1%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3EBindings%20and%20mutation,%20with%20%3Ccode%3E=%3C/code%3E%20to%20bind%20and%20%3Ccode%3E:=%3C/code%3E%20to%20mutate:%3C/p%3E%3Cpre%20class=%22language-osprey-ml%22%3E%3Ccode%20class=%22language-osprey-ml%22%3E%3Cspan%20class=%22token%20keyword%22%3Emut%3C/span%3E%20counter%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20number%22%3E0%3C/span%3Ecounter%20%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20counter%20%3Cspan%20class=%22token%20operator%22%3E+%3C/span%3E%20%3Cspan%20class=%22token%20number%22%3E1%3C/span%3E%20%20%20%20%20%20%3Cspan%20class=%22token%20comment%22%3E//%20:=%20mutates;%20=%20binds%3C/span%3Eprint%20%3Cspan%20class=%22token%20string%22%3E%22counter%20=%20${counter}%22%3C/span%3E%3C/code%3E%3C/pre%3E%3Ch2%20id=%22same-folder-compiled-together%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#same-folder-compiled-together%22%3ESame%20folder,%20compiled%20together%3C/a%3E%3C/h2%3E%3Cp%3EBecause%20every%20flavor%20lowers%20to%20the%20same%20canonical%20AST%20%3Cem%3Ebefore%3C/em%3E%20any%20type%20checking,%20the%20flavor%20is%20a%20%3Cstrong%3Eper-file%3C/strong%3E%20choice%20%E2%80%94%20not%20a%20per-project%20one.%20A%20%3Ccode%3E.osp%3C/code%3E%20file%20and%20a%20%3Ccode%3E.ospml%3C/code%3E%20file%20can%20sit%20in%20the%20same%20folder%20and%20compile%20into%20one%20program:%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20comment%22%3E//%20One%20project%20folder,%20two%20flavors,%20one%20compiled%20program:%3C/span%3E%3Cspan%20class=%22token%20comment%22%3E//%20%20%20project/%3C/span%3E%3Cspan%20class=%22token%20comment%22%3E//%20%20%20%20%20math.ospml%20%20%20%20%20#%20ML%20flavor%20%E2%80%94%20curry-by-default%20module%3C/span%3E%3Cspan%20class=%22token%20comment%22%3E//%20%20%20%20%20app.osp%20%20%20%20%20%20%20%20#%20Default%20flavor%20%E2%80%94%20braces;%20imports%20math%3C/span%3E%3Cspan%20class=%22token%20comment%22%3E//%20Each%20file%20is%20wholly%20one%20flavor%20(chosen%20by%20extension/marker/--flavor).%20Both%20lower%20to%3C/span%3E%3Cspan%20class=%22token%20comment%22%3E//%20the%20SAME%20canonical%20AST,%20so%20they%20share%20one%20type%20checker%20and%20one%20binary.%20Exports%20are%3C/span%3E%3Cspan%20class=%22token%20comment%22%3E//%20canonical%20signatures,%20so%20a%20Default%20module%20and%20an%20ML%20module%20import%20each%20other%20normally.%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3EExports%20are%20canonical%20signatures%20with%20stable%20names%20and%20ordering,%20so%20a%20Default%20module%20and%20an%20ML%20module%20reference%20each%20other%20with%20no%20glue%20layer.%20The%20team%20is%20never%20forced%20to%20pick%20one%20tribe;%20each%20developer%20picks%20the%20flavor%20for%20the%20file%20they&#39;re%20writing.%3C/p%3E%3Cp%3ETo%20be%20precise%20about%20what%20ships%20today:%20%3Cstrong%3Eper-file%20flavor%20selection%20is%20implemented%20and%20green.%3C/strong%3E%20You%20select%20the%20ML%20surface%20with%20the%20%3Ccode%3E.ospml%3C/code%3E%20extension,%20the%20%3Ccode%3E--flavor%20ml%3C/code%3E%20CLI%20flag,%20or%20a%20leading%20%3Ccode%3E//%20osprey:%20flavor=ml%3C/code%3E%20marker%20(precedence:%20flag%20&amp;gt;%20marker%20&amp;gt;%20extension%20&amp;gt;%20Default).%20That%20mechanism%20is%20exercised%20by%20tested%20examples%20right%20now.%20The%20multi-file%20%3Cem%3Ecross-flavor%20import%3C/em%3E%20%E2%80%94%20a%20Default%20module%20pulling%20in%20an%20ML%20module%20in%20the%20same%20build%20%E2%80%94%20is%20the%20design%20direction%20the%20canonical-AST%20architecture%20is%20built%20for,%20but%20it%20is%20not%20yet%20covered%20by%20a%20tested%20example,%20so%20we&#39;re%20showing%20you%20the%20folder%20model%20and%20the%20per-file%20selection%20that%20is%20green,%20not%20a%20runnable%20cross-flavor%20import%20program.%3C/p%3E%3Ch2%20id=%22effects-in-both-flavors%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#effects-in-both-flavors%22%3EEffects:%20in%20both%20flavors%3C/a%3E%3C/h2%3E%3Cp%3EOsprey&#39;s%20headline%20feature%20is%20typed%20algebraic%20effects%20%E2%80%94%20and%20the%20lexical%20effect%20syntax%20works%20in%20%3Cstrong%3Eboth%3C/strong%3E%20flavors.%20Here&#39;s%20the%20same%20%3Ccode%3ELogger%3C/code%3E%20demo,%20first%20in%20the%20Default%20flavor:%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20keyword%22%3Eeffect%3C/span%3E%20Logger%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20log%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3EUnit%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Egreet%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Ename%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3EUnit%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E!%3C/span%3ELogger%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%20%3Cspan%20class=%22token%20keyword%22%3Eperform%3C/span%3E%20Logger%3Cspan%20class=%22token%20punctuation%22%3E.%3C/span%3E%3Cspan%20class=%22token%20function%22%3Elog%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20string%22%3E%22Hello,%20${name}!%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20comment%22%3E//%20Production:%20write%20to%20stdout%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Ehandle%3C/span%3E%20Logger%20%20log%20msg%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Eprint%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Emsg%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Ein%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Egreet%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20string%22%3E%22Alice%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3Cspan%20class=%22token%20comment%22%3E//%20Test:%20stay%20silent%20%E2%80%94%20same%20code,%20new%20handler%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Ehandle%3C/span%3E%20Logger%20%20log%20msg%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20number%22%3E0%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Ein%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Egreet%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3E%3Cspan%20class=%22token%20string%22%3E%22Bob%22%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3E%E2%80%A6and%20the%20identical%20program%20in%20the%20ML%20flavor%20%E2%80%94%20layout,%20whitespace%20application,%20%3Ccode%3Ehandle%20%E2%80%A6%20in%3C/code%3E,%20the%20lot:%3C/p%3E%3Cpre%20class=%22language-osprey-ml%22%3E%3Ccode%20class=%22language-osprey-ml%22%3E%3Cspan%20class=%22token%20keyword%22%3Eeffect%3C/span%3E%20Logger%20%20%20%20log%20%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20keyword%22%3EUnit%3C/span%3Egreet%20name%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Eperform%3C/span%3E%20Logger%3Cspan%20class=%22token%20punctuation%22%3E.%3C/span%3Elog%20%3Cspan%20class=%22token%20string%22%3E%22Hello,%20${name}!%22%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Ehandle%3C/span%3E%20Logger%20%20%20%20log%20msg%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20print%20msg%3Cspan%20class=%22token%20keyword%22%3Ein%3C/span%3E%20greet%20%3Cspan%20class=%22token%20string%22%3E%22Alice%22%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Ehandle%3C/span%3E%20Logger%20%20%20%20log%20msg%20%3Cspan%20class=%22token%20operator%22%3E=%3E%3C/span%3E%20%3Cspan%20class=%22token%20number%22%3E0%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Ein%3C/span%3E%20greet%20%3Cspan%20class=%22token%20string%22%3E%22Bob%22%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3EThe%20%3Ccode%3E!Logger%3C/code%3E%20row%20documents%20and%20helps%20instantiate%20the%20%3Ccode%3ELogger%3C/code%3E%20operations%20used%20by%20%3Ccode%3Egreet%3C/code%3E.%20Swap%20the%20handler%20and%20the%20same%20code%20logs%20to%20stdout%20or%20stays%20silent%20%E2%80%94%20no%20global%20mutable%20wiring,%20just%20a%20different%20%3Ccode%3Ehandle%3C/code%3E%20block.%20Both%20flavors%20lower%20to%20the%20same%20%3Ccode%3EHandler%3C/code%3E%20node,%20so%20the%20effect%20checker%20and%20runtime%20never%20learn%20which%20one%20you%20wrote.%20Complete%20static%20effect-row%20propagation%20and%20missing-handler%20rejection%20are%20still%20in%20progress;%20today%20a%20missing%20runtime%20handler%20aborts%20with%20an%20explicit%20diagnostic.%3C/p%3E%3Ch2%20id=%22status-honestly%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#status-honestly%22%3EStatus,%20honestly%3C/a%3E%3C/h2%3E%3Cp%3EThe%20%3Cstrong%3EDefault%20flavor%20is%20the%20most%20mature%20surface%3C/strong%3E.%20It%20includes%20effects,%20persistent%20collections,%20native%20continuations,%20and%20the%20wider%20runtime,%20with%20the%20limitations%20recorded%20on%20the%20%3Ca%20href=%22/status/%22%3Efeature%20status%20page%3C/a%3E.%3C/p%3E%3Cp%3EThe%20%3Cstrong%3EML%20flavor%20is%20fully%20implemented%20too%3C/strong%3E,%20with%20runnable%20proof%20you%20can%20read%20and%20run:%20the%20%3Ca%20href=%22https://github.com/Nimblesite/osprey/tree/main/examples/tested%22%3Etested%20ML%20examples%3C/a%3E%20cover%20hello-world,%20curry-by-default%20with%20partial%20application,%20higher-order%20functions,%20%3Ccode%3EResult%3C/code%3E%20matching,%20layout%20%3Ccode%3Ematch%3C/code%3E,%20mutation,%20fibers,%20and%20algebraic%20effects%20with%20%3Ccode%3Ehandle%20%E2%80%A6%20in%3C/code%3E%20%E2%80%94%20each%20one%20runs%20through%20the%20compiler%20and%20its%20%3Ccode%3Estdout%3C/code%3E%20is%20byte-compared%20against%20a%20checked-in%20%3Ccode%3E.expectedoutput%3C/code%3E.%3C/p%3E%3Cp%3EML%20effects%20run%20today:%20%3Ccode%3Eeffect%3C/code%3E,%20%3Ccode%3Eperform%3C/code%3E,%20%3Ccode%3Ehandle%20%E2%80%A6%20in%3C/code%3E,%20and%20native%20%3Ccode%3Eresume%3C/code%3E%20examples%20are%20byte-checked%20in%20the%20%3Ca%20href=%22https://github.com/Nimblesite/osprey/tree/main/examples/tested/effects%22%3Etested%20examples%3C/a%3E.%20Important%20shared-core%20limits%20remain:%20compile-time%20effect%20coverage%20is%20incomplete,%20and%20%3Cstrong%3Efirst-class%20handler%20values%3C/strong%3E%20%E2%80%94%20a%20%3Ccode%3EHandler%20E%3C/code%3E%20type%20you%20can%20pass%20around%20and%20install%20dynamically%20%E2%80%94%20are%20deferred.%20Lexically%20scoped%20%3Ccode%3Ehandle%20%E2%80%A6%20in%3C/code%3E%20regions%20work%20in%20both%20flavors.%3C/p%3E%3Ch2%20id=%22pick-your-flavor%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#pick-your-flavor%22%3EPick%20your%20flavor%3C/a%3E%3C/h2%3E%3Cp%3EIf%20you%20live%20in%20braces%20and%20named%20arguments,%20write%20%3Ccode%3E.osp%3C/code%3E%20and%20never%20think%20about%20layout%20again.%20If%20you%20live%20in%20layout%20and%20currying,%20write%20%3Ccode%3E.ospml%3C/code%3E%20and%20never%20type%20a%20brace.%20Either%20way%20you%20get%20the%20same%20Hindley-Milner%20type%20checker,%20typed%20effect%20operations,%20backend,%20and%20standard%20library%20%E2%80%94%20because%20after%20lowering,%20nothing%20downstream%20can%20even%20tell%20which%20flavor%20you%20wrote.%3C/p%3E%3Cp%3EPick%20your%20flavor.%20Go%20all%20in.%20It&#39;s%20the%20same%20Osprey.%3C/p%3E</content>
    <summary>Compare Osprey’s brace-style and ML-style flavors, how both lower to one canonical AST, and which shared compiler features and limitations apply today.</summary>
  </entry>
  <entry>
    <title>Perceus ARC in Osprey: Functional Memory Management</title>
    <link href="https://www.ospreylang.dev/blog/2026-07-23-perceus-arc-in-osprey/"/>
    <id>https://www.ospreylang.dev/blog/2026-07-23-perceus-arc-in-osprey/</id>
    <updated>2026-07-23T00:00:00.000Z</updated>
    <content type="html">https://www.ospreylang.dev/%3Ch1%20id=%22perceus-arc-in-osprey-functional-memory-management%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#perceus-arc-in-osprey-functional-memory-management%22%3EPerceus%20ARC%20in%20Osprey:%20Functional%20Memory%20Management%3C/a%3E%3C/h1%3E%3Cp%3E%3Cem%3EBy%20Christian%20Findlay%20%C2%B7%2023%20July%202026%3C/em%3E%3C/p%3E%3Cp%3EI%20want%20Osprey%20to%20make%20immutable%20functional%20programming%20feel%20cheap.%20That%20promise%20gets%20harder%20when%20lists,%20maps,%20records,%20unions%20and%20closures%20all%20live%20on%20the%20heap.%20If%20the%20compiler%20allocates%20every%20new%20value%20but%20never%20knows%20when%20the%20last%20owner%20disappears,%20a%20long-running%20program%20eventually%20pays%20for%20every%20value%20it%20has%20ever%20created.%3C/p%3E%3Cp%3EOsprey%20now%20ships%20an%20opt-in%20%3Ccode%3E--memory=arc%3C/code%3E%20backend%20based%20on%20%3Cstrong%3EPerceus%20automatic%20reference%20counting%3C/strong%3E.%20The%20compiler%20tracks%20ownership,%20inserts%20the%20required%20duplicate%20and%20drop%20operations,%20and%20transfers%20existing%20owners%20instead%20of%20creating%20unnecessary%20reference-count%20traffic.%20When%20the%20final%20owner%20disappears,%20the%20runtime%20reclaims%20the%20value%20and%20walks%20supported%20child%20layouts%20using%20layout%20metadata.%3C/p%3E%3Cp%3EThis%20first%20release%20implements%20the%20Perceus%20ownership%20core%20and%20several%20useful%20move%20optimisations.%20It%20does%20not%20yet%20implement%20the%20paper&#39;s%20compiler-guided%20reuse%20analysis%20or%20its%20full%20functional-but-in-place%20story.%20I%20also%20added%20a%20conservative%20tracing%20collector%20recently%20behind%20the%20same%20%3Ccode%3E--memory%3C/code%3E%20boundary.%20That%20deserves%20its%20own%20post.%20This%20one%20is%20about%20why%20Perceus%20fits%20Osprey%20and%20how%20the%20ARC%20implementation%20actually%20works.%3C/p%3E%3Ch2%20id=%22why-memory-management-belongs-below-the-language%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#why-memory-management-belongs-below-the-language%22%3EWhy%20memory%20management%20belongs%20below%20the%20language%3C/a%3E%3C/h2%3E%3Cp%3EI%20made%20one%20decision%20early:%20an%20Osprey%20program%20should%20never%20observe%20memory%20reclamation.%3C/p%3E%3Cp%3EYou%20cannot%20attach%20a%20finalizer%20to%20a%20value.%20You%20cannot%20inspect%20its%20address.%20You%20cannot%20write%20code%20that%20depends%20on%20destruction%20order%20or%20timing.%20A%20conforming%20implementation%20can%20reclaim%20a%20value%20at%20its%20last%20use,%20later%20in%20the%20run,%20or%20at%20process%20exit%20without%20changing%20what%20your%20program%20does.%20The%20%3Ca%20href=%22/spec/0018-memorymanagement/%22%3Ememory%20management%20specification%3C/a%3E%20makes%20that%20contract%20explicit.%3C/p%3E%3Cp%3EThat%20gives%20the%20compiler%20room%20to%20choose%20the%20right%20mechanism.%20Osprey%20emits%20one%20backend-neutral%20LLVM%20IR%20with%20calls%20to%20a%20small%20allocation,%20retain%20and%20release%20interface.%20The%20linker%20selects%20the%20runtime%20archive.%20Under%20ARC,%20those%20retain%20and%20release%20hooks%20update%20exact%20counts.%20The%20default%20and%20tracing%20collector%20archives%20leave%20those%20two%20hooks%20as%20no-ops.%3C/p%3E%3Cp%3EYou%20write%20the%20same%20source%20either%20way.%20Memory%20management%20stays%20an%20implementation%20concern.%3C/p%3E%3Ch2%20id=%22the-academic-foundation-perceus%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#the-academic-foundation-perceus%22%3EThe%20academic%20foundation:%20Perceus%3C/a%3E%3C/h2%3E%3Cp%3EThe%20design%20comes%20from%20Alex%20Reinking,%20Ningning%20Xie,%20Leonardo%20de%20Moura%20and%20Daan%20Leijen&#39;s%20PLDI%202021%20paper,%20%3Ca%20href=%22https://www.microsoft.com/en-us/research/wp-content/uploads/2021/06/perceus-pldi21.pdf%22%3E%3Cem%3EPerceus:%20Garbage%20Free%20Reference%20Counting%20with%20Reuse%3C/em%3E%3C/a%3E.%20The%20authors%20developed%20Perceus%20for%20Koka%20and%20grounded%20it%20in%20a%20linear%20resource%20calculus%20called%20%3Ccode%3E%CE%BB%E2%82%81%3C/code%3E.%20Osprey%20adapts%20the%20ownership%20and%20%3Ccode%3Edup%3C/code%3E/%3Ccode%3Edrop%3C/code%3E%20insertion%20discipline%20from%20their%20%3Ca%20href=%22https://www.microsoft.com/en-us/research/wp-content/uploads/2020/11/perceus-tr-v1.pdf%22%3Eextended%20technical%20report%3C/a%3E.%3C/p%3E%3Cp%3EThe%20central%20idea%20is%20simple%20enough%20to%20state%20without%20the%20calculus:%3C/p%3E%3Cul%3E%3Cli%3EA%20produced%20heap%20value%20starts%20with%20one%20owner.%3C/li%3E%3Cli%3EIf%20code%20needs%20another%20owner,%20the%20compiler%20inserts%20%3Ccode%3Edup%3C/code%3E.%3C/li%3E%3Cli%3EA%20final%20use%20consumes%20or%20transfers%20its%20owner.%20If%20a%20path%20does%20not%20use%20that%20owner,%20the%20compiler%20inserts%20%3Ccode%3Edrop%3C/code%3E%20as%20soon%20as%20it%20becomes%20dead.%3C/li%3E%3Cli%3EA%20function%20can%20transfer%20an%20owner%20to%20its%20caller%20instead%20of%20duplicating%20and%20then%20dropping%20it.%3C/li%3E%3C/ul%3E%3Cp%3EThe%20formal%20system%20treats%20an%20owned%20resource%20as%20something%20the%20program%20must%20consume%20exactly%20once.%20Perceus%20then%20gives%20the%20compiler%20syntax-directed%20rules%20that%20insert%20duplicates%20late%20and%20drops%20early.%20That%20placement%20matters.%20Basic%20reference%20counting%20can%20spend%20a%20lot%20of%20time%20incrementing%20and%20decrementing%20counts%20that%20cancel%20each%20other.%20Precise%20ownership%20information%20lets%20the%20compiler%20avoid%20much%20of%20that%20work.%3C/p%3E%3Cp%3EPerceus%20builds%20on%20earlier%20work%20from%20Sebastian%20Ullrich%20and%20Leonardo%20de%20Moura,%20%3Ca%20href=%22https://www.microsoft.com/en-us/research/publication/counting-immutable-beans-reference-counting-optimized-for-purely-functional-programming/%22%3E%3Cem%3ECounting%20Immutable%20Beans:%20Reference%20Counting%20Optimized%20for%20Purely%20Functional%20Programming%3C/em%3E%3C/a%3E.%20That%20Lean%20research%20explored%20exact%20counts,%20borrowed%20references%20and%20destructive%20updates%20when%20a%20value%20has%20one%20owner.%20Perceus%20turned%20those%20ideas%20into%20a%20systematic%20translation%20with%20a%20proof%20for%20its%20cycle-free%20core.%3C/p%3E%3Cp%3EThe%20paper%20uses%20%3Cstrong%3Egarbage-free%3C/strong%3E%20in%20a%20precise%20academic%20sense.%20In%20its%20cycle-free%20calculus,%20at%20each%20intermediate%20state%20after%20any%20immediately%20pending%20duplicate%20or%20drop%20operation,%20every%20heap%20object%20is%20reachable%20from%20the%20current%20computation.%20It%20does%20not%20mean%20zero%20allocation%20or%20zero%20bookkeeping.%3C/p%3E%3Cp%3EThe%20second%20half%20of%20the%20Perceus%20story%20uses%20dynamic%20uniqueness.%20If%20a%20pattern%20match%20consumes%20a%20uniquely%20owned%20constructor,%20the%20program%20can%20reuse%20that%20storage%20for%20a%20new%20constructor%20of%20the%20same%20size.%20Shared%20inputs%20keep%20persistent%20copy%20semantics.%20Unique%20inputs%20can%20update%20in%20place.%20The%20authors%20call%20this%20%3Cstrong%3Efunctional%20but%20in-place%3C/strong%3E,%20or%20FBIP.%3C/p%3E%3Cp%3EThat%20reuse%20work%20matters,%20but%20I%20want%20to%20draw%20a%20hard%20line%20around%20the%20current%20implementation:%20Osprey%20ships%20the%20ownership%20and%20%3Ccode%3Edup%3C/code%3E/%3Ccode%3Edrop%3C/code%3E%20foundation%20today.%20Compiler-guided%20constructor%20reuse%20remains%20future%20work.%3C/p%3E%3Ch2%20id=%22how-automatic-reference-counting-works-in-osprey%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#how-automatic-reference-counting-works-in-osprey%22%3EHow%20automatic%20reference%20counting%20works%20in%20Osprey%3C/a%3E%3C/h2%3E%3Cp%3EConsider%20a%20small%20value%20that%20stores%20the%20same%20string%20twice:%3C/p%3E%3Cpre%20class=%22language-osprey%22%3E%3Ccode%20class=%22language-osprey%22%3E%3Cspan%20class=%22token%20keyword%22%3Etype%3C/span%3E%20Names%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20Names%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20left%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20right%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3Cspan%20class=%22token%20keyword%22%3Efn%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3EduplicateName%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Einput%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20%3Cspan%20class=%22token%20type%22%3Estring%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%3Cspan%20class=%22token%20operator%22%3E-%3E%3C/span%3E%20Names%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%20%20%20%3Cspan%20class=%22token%20keyword%22%3Elet%3C/span%3E%20name%20%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3E%20%3Cspan%20class=%22token%20function%22%3Etrim%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E(%3C/span%3Einput%3Cspan%20class=%22token%20punctuation%22%3E)%3C/span%3E%20%20%20%20Names%20%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20left%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20name%3Cspan%20class=%22token%20punctuation%22%3E,%3C/span%3E%20right%3Cspan%20class=%22token%20punctuation%22%3E:%3C/span%3E%20name%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3EYou%20never%20annotate%20%3Ccode%3Ename%3C/code%3E%20as%20owned%20or%20borrowed.%20The%20compiler%20sees%20a%20produced%20string,%20two%20owning%20fields%20and%20a%20returned%20aggregate.%20It%20maintains%20the%20ownership%20ledger%20for%20you.%3C/p%3E%3Cp%3EThe%20ARC%20rules%20work%20like%20this:%3C/p%3E%3Col%3E%3Cli%3E%3Ccode%3Etrim(input)%3C/code%3E%20produces%20a%20string%20with%20one%20owner.%3C/li%3E%3Cli%3EEach%20heap%20field%20that%20keeps%20a%20shared%20value%20acquires%20its%20own%20owner.%3C/li%3E%3Cli%3EThe%20local%20%3Ccode%3Ename%3C/code%3E%20owner%20drops%20as%20the%20function%20exits,%20after%20its%20final%20use.%3C/li%3E%3Cli%3EThe%20%3Ccode%3ENames%3C/code%3E%20value%20transfers%20its%20existing%20owner%20to%20the%20caller%20on%20return.%3C/li%3E%3Cli%3EWhen%20the%20final%20owner%20of%20%3Ccode%3ENames%3C/code%3E%20disappears,%20the%20runtime%20releases%20both%20child%20fields.%20The%20string%20disappears%20when%20its%20own%20final%20count%20reaches%20zero.%3C/li%3E%3C/ol%3E%3Cp%3EThe%20important%20part%20is%20what%20does%20not%20happen.%20The%20return%20path%20does%20not%20retain%20the%20%3Ccode%3ENames%3C/code%3E%20value%20and%20immediately%20release%20the%20function&#39;s%20copy.%20The%20compiler%20moves%20that%20existing%20%3Ccode%3E+1%3C/code%3E%20out%20of%20the%20function.%3C/p%3E%3Ch2%20id=%22what-the-compiler-actually-emits%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#what-the-compiler-actually-emits%22%3EWhat%20the%20compiler%20actually%20emits%3C/a%3E%3C/h2%3E%3Cp%3EThe%20implementation%20lives%20in%20Osprey&#39;s%20%3Ca%20href=%22https://github.com/Nimblesite/osprey/blob/main/crates/osprey-codegen/src/arc.rs%22%3EPerceus%20ownership%20ledger%3C/a%3E.%20It%20threads%20ownership%20information%20through%20the%20normal%20AST-to-LLVM%20walk%20rather%20than%20adding%20a%20second%20ARC-only%20compiler%20pipeline.%3C/p%3E%3Cp%3EThe%20compiler%20assigns%20every%20tracked%20managed-pointer%20owner%20a%20null-initialised%20slot%20in%20the%20function%20entry%20block.%20If%20a%20branch%20never%20produces%20the%20value,%20the%20compiler%20leaves%20that%20slot%20null.%20Region%20cleanup%20can%20therefore%20load%20and%20release%20the%20slot%20safely%20without%20solving%20a%20separate%20dominance%20problem%20for%20every%20match%20arm%20and%20loop%20edge.%3C/p%3E%3Cp%3EOn%20top%20of%20the%20basic%20producer,%20duplicate%20and%20drop%20rules,%20the%20compiler%20already%20removes%20several%20common%20pairs:%3C/p%3E%3Cul%3E%3Cli%3E%3Cstrong%3EFresh%20constructor%20moves:%3C/strong%3E%20a%20fresh%20unnamed%20owner%20can%20move%20straight%20into%20a%20constructor%20field.%3C/li%3E%3Cli%3E%3Cstrong%3EMatch%20join%20moves:%3C/strong%3E%20when%20every%20possible%20incoming%20arm%20produces%20a%20fresh%20owner,%20that%20owner%20can%20move%20through%20the%20LLVM%20%3Ccode%3Ephi%3C/code%3E%20at%20the%20join.%3C/li%3E%3Cli%3E%3Cstrong%3EReturn%20transfers:%3C/strong%3E%20a%20function%20moves%20an%20owner%20it%20already%20holds%20to%20its%20caller.%3C/li%3E%3Cli%3E%3Cstrong%3ELast-use%20drops:%3C/strong%3E%20region%20cleanup%20and%20function-level%20liveness%20release%20a%20named%20top-level%20value%20after%20its%20final%20syntactic%20use%20instead%20of%20always%20waiting%20for%20the%20whole%20function%20to%20end.%3C/li%3E%3Cli%3E%3Cstrong%3ELLVM%20allocation%20elimination:%3C/strong%3E%20LLVM%20can%20remove%20some%20fresh,%20non-escaping%20allocation%20and%20unique-release%20pairs,%20especially%20scalar%20%3Ccode%3EResult%3C/code%3E%20blocks.%3C/li%3E%3C/ul%3E%3Cp%3EThe%20generated%20IR%20always%20names%20the%20same%20hooks.%20%3Ccode%3E--memory=arc%3C/code%3E%20simply%20links%20the%20ARC%20runtime%20behind%20them.%20That%20boundary%20keeps%20the%20language,%20type%20checker%20and%20optimiser%20independent%20from%20the%20selected%20memory%20backend.%3C/p%3E%3Ch2%20id=%22inside-the-arc-runtime%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#inside-the-arc-runtime%22%3EInside%20the%20ARC%20runtime%3C/a%3E%3C/h2%3E%3Cp%3EThe%20%3Ca%20href=%22https://github.com/Nimblesite/osprey/blob/main/compiler/runtime/memory_arc.c%22%3EARC%20runtime%3C/a%3E%20puts%20a%2016-byte%20header%20before%20every%20managed%20allocation:%3C/p%3E%3Cpre%20class=%22language-c%22%3E%3Ccode%20class=%22language-c%22%3E%3Cspan%20class=%22token%20punctuation%22%3E{%3C/span%3E%20%3Cspan%20class=%22token%20class-name%22%3Eint64_t%3C/span%3E%20meta%3Cspan%20class=%22token%20punctuation%22%3E;%3C/span%3E%20%3Cspan%20class=%22token%20class-name%22%3Eint32_t%3C/span%3E%20rc%3Cspan%20class=%22token%20punctuation%22%3E;%3C/span%3E%20%3Cspan%20class=%22token%20class-name%22%3Euint32_t%3C/span%3E%20size%3Cspan%20class=%22token%20punctuation%22%3E;%3C/span%3E%20%3Cspan%20class=%22token%20punctuation%22%3E}%3C/span%3E%3C/code%3E%3C/pre%3E%3Cp%3E%3Ccode%3Erc%3C/code%3E%20stores%20a%20positive%20owner%20count,%20while%20negative%20values%20mark%20immortal%20allocations.%20%3Ccode%3Esize%3C/code%3E%20records%20the%20body%20size.%20%3Ccode%3Emeta%3C/code%3E%20encodes%20a%20layout%20kind%20and,%20for%20masked%20layouts,%20which%20body%20words%20may%20hold%20managed%20pointers.%20Code%20generation%20and%20the%20collection%20runtimes%20supply%20those%20layouts,%20while%20the%20allocation%20registry%20distinguishes%20ARC%20objects%20from%20static%20and%20foreign%20pointers.%3C/p%3E%3Cp%3ERetain%20and%20release%20first%20probe%20a%20registry%20of%20Osprey%20allocations.%20A%20null%20pointer,%20static%20string%20or%20foreign%20pointer%20misses%20that%20registry%20and%20becomes%20a%20safe%20no-op.%20When%20a%20count%20reaches%20zero,%20an%20iterative%20worklist%20releases%20the%20object&#39;s%20managed%20children.%20Deep%20trees%20therefore%20do%20not%20consume%20the%20C%20call%20stack%20while%20they%20collapse.%3C/p%3E%3Cp%3EFreed%20blocks%20enter%20an%20exact%20size-class%20pool%20when%20they%20fit.%20A%20later%20allocation%20can%20recycle%20one%20of%20those%20blocks.%20This%20is%20useful%20allocator%20engineering,%20but%20it%20is%20not%20Perceus%20reuse%20analysis.%20The%20pool%20recycles%20storage%20after%20an%20object%20has%20died.%20The%20paper&#39;s%20reuse%20pass%20pairs%20a%20specific%20dying%20match%20scrutinee%20with%20a%20same-sized%20constructor%20and%20uses%20dynamic%20uniqueness%20to%20reuse%20it%20directly.%3C/p%3E%3Ch2%20id=%22why-reference-counting-fits-functional-programming%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#why-reference-counting-fits-functional-programming%22%3EWhy%20reference%20counting%20fits%20functional%20programming%3C/a%3E%3C/h2%3E%3Cp%3EReference%20counting%20has%20one%20famous%20weakness:%20cycles.%20Osprey%20avoids%20that%20problem%20by%20construction.%3C/p%3E%3Cp%3EHeap%20values%20are%20immutable,%20so%20an%20older%20value%20cannot%20later%20gain%20a%20pointer%20to%20a%20younger%20value.%20%3Ccode%3Emut%3C/code%3E%20rebinds%20a%20name%20to%20a%20new%20value;%20it%20does%20not%20rewrite%20an%20existing%20heap%20object.%20The%20value%20graph%20stays%20acyclic,%20which%20means%20a%20count%20reaching%20zero%20can%20reclaim%20dead%20subgraphs%20for%20supported%20precise%20layouts%20without%20a%20cycle%20collector.%3C/p%3E%3Cp%3EPersistent%20collections%20make%20the%20ownership%20model%20especially%20concrete.%20Two%20versions%20of%20a%20list%20or%20map%20can%20share%20most%20of%20their%20internal%20nodes.%20Exact%20counts%20record%20that%20sharing.%20When%20one%20version%20dies,%20the%20runtime%20releases%20only%20the%20spine%20that%20version%20stopped%20owning.%20Nodes%20shared%20with%20another%20live%20version%20keep%20a%20positive%20count.%3C/p%3E%3Cp%3EThis%20is%20the%20part%20I%20like%20most.%20Immutability%20gives%20you%20simple%20source%20semantics,%20and%20the%20compiler%20turns%20the%20resulting%20ownership%20structure%20into%20ownership-aware%20runtime%20behaviour.%20You%20get%20persistent%20values%20without%20asking%20every%20object%20to%20survive%20until%20the%20end%20of%20the%20process.%3C/p%3E%3Ch2%20id=%22what-the-current-measurements-say%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#what-the-current-measurements-say%22%3EWhat%20the%20current%20measurements%20say%3C/a%3E%3C/h2%3E%3Cp%3EI%20do%20not%20want%20to%20turn%20one%20benchmark%20into%20a%20universal%20performance%20claim.%20Still,%20the%20committed%20%3Ca%20href=%22/benchmarks/%22%3EOsprey%20benchmark%20run%3C/a%3E%20shows%20why%20this%20work%20matters.%3C/p%3E%3Cp%3EOn%20%3Ccode%3Ebinarytrees%3C/code%3E,%20the%20default%20allocator%20reached%20%3Cstrong%3E603.8%20MiB%3C/strong%3E%20of%20peak%20memory%20and%20completed%20in%20%3Cstrong%3E248.7%20ms%3C/strong%3E.%20The%20ARC%20build%20reached%20%3Cstrong%3E2.8%20MiB%3C/strong%3E%20and%20completed%20in%20%3Cstrong%3E216.4%20ms%3C/strong%3E.%20ARC%20reclaimed%20the%20short-lived%20tree%20nodes%20throughout%20the%20run,%20and%20its%20bookkeeping%20did%20not%20slow%20this%20particular%20result.%3C/p%3E%3Cp%3EDifferent%20programs%20create%20different%20ownership%20patterns,%20so%20you%20should%20read%20those%20numbers%20as%20one%20reproducible%20data%20point.%20The%20useful%20result%20is%20that%20the%20implementation%20now%20gives%20us%20a%20real%20way%20to%20measure%20reference-counted%20reclamation%20across%20the%20benchmark%20suite%20instead%20of%20reasoning%20from%20a%20design%20document.%3C/p%3E%3Ch2%20id=%22status-honestly%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#status-honestly%22%3EStatus,%20honestly%3C/a%3E%3C/h2%3E%3Cp%3EOsprey%20currently%20ships:%3C/p%3E%3Cul%3E%3Cli%3EThe%20Perceus%20producer,%20duplicate%20and%20drop%20discipline.%3C/li%3E%3Cli%3ERegion-end%20and%20function-level%20last-use%20drops.%3C/li%3E%3Cli%3EFresh%20constructor,%20match%20join%20and%20return-owner%20moves.%3C/li%3E%3Cli%3ECompiler-supplied%20layouts%20for%20generated%20records,%20unions,%20%3Ccode%3EResult%3C/code%3E%20blocks,%20closures%20and%20flat%20list%20headers,%20plus%20runtime-supplied%20layouts%20for%20persistent%20collection%20nodes.%20Runtime-created%20strings%20use%20raw%20managed%20allocations.%3C/li%3E%3Cli%3EA%20non-recursive%20drop%20walk,%20allocation%20registry,%20leak%20diagnostics%20and%20size-classed%20block%20pool.%3C/li%3E%3C/ul%3E%3Cp%3EThe%20inline%20pointer%20mask%20currently%20covers%20the%20first%2056%20body%20words.%20If%20an%20aggregate%20has%20managed%20fields%20beyond%20that%20range,%20the%20compiler%20falls%20back%20to%20a%20raw%20layout%20and%20retains%20those%20children%20rather%20than%20risking%20an%20invalid%20release.%3C/p%3E%3Cp%3EOsprey%20does%20not%20yet%20ship:%3C/p%3E%3Cul%3E%3Cli%3ESelective%20borrow%20inference.%3C/li%3E%3Cli%3EPerceus%20drop%20specialization.%3C/li%3E%3Cli%3ECompiler-guided%20reuse,%20including%20drop-guided%20reuse%20and%20reuse%20specialization.%3C/li%3E%3Cli%3EAn%20FBIP%20guarantee.%3C/li%3E%3C/ul%3E%3Cp%3EThe%20distinction%20matters.%20The%20%3Ca%20href=%22https://www.microsoft.com/en-us/research/publication/perceus-garbage-free-reference-counting-with-reuse-2/%22%3EPerceus%20paper%3C/a%3E%20proves%20soundness%20and%20garbage-freedom%20for%20the%20syntax-directed%20duplicate-and-drop%20translation%20of%20its%20cycle-free%20core.%20It%20does%20not%20formally%20verify%20the%20Koka%20implementation%20or%20every%20optimisation%20and%20reuse%20transformation.%20Osprey%20adapts%20the%20discipline%20to%20a%20real%20LLVM%20compiler,%20persistent%20containers,%20effects%20and%20foreign%20pointers.%20Our%20tests%20give%20strong%20implementation%20evidence,%20but%20they%20do%20not%20inherit%20the%20paper&#39;s%20proof%20automatically.%3C/p%3E%3Cp%3EAt%20the%20time%20of%20writing,%20the%20code-generation%20suite%20passes%2074%20tests,%20and%20the%20C%20ARC%20test%20binary%20executes%20600,975%20assertions%20across%20allocation,%20layout,%20ownership,%20pooling%20and%20failure%20paths.%20The%20differential%20suite%20also%20runs%20the%20same%20Osprey%20programs%20through%20each%20backend%20and%20compares%20their%20output.%20ARC%20remains%20opt-in%20while%20I%20build%20the%20independent%20precise%20oracle%20I%20want%20before%20making%20ownership-based%20reclamation%20the%20default.%3C/p%3E%3Cp%3EThe%20next%20academic%20step%20is%20also%20clear.%20Anton%20Lorenzen%20and%20Daan%20Leijen&#39;s%20%3Ca%20href=%22https://www.microsoft.com/en-us/research/publication/reference-counting-with-frame-limited-reuse/%22%3E%3Cem%3EReference%20Counting%20with%20Frame%20Limited%20Reuse%3C/em%3E%3C/a%3E%20introduces%20drop-guided%20reuse%20and%20a%20frame-limited%20bound.%20Earlier%20reuse%20could%20react%20poorly%20to%20small%20program%20transformations%20and%20increase%20peak%20heap%20use%20without%20a%20bound.%20That%20is%20the%20direction%20I%20want%20to%20investigate%20when%20Osprey%20moves%20beyond%20the%20current%20%3Ccode%3Edup%3C/code%3E/%3Ccode%3Edrop%3C/code%3E%20tier.%3C/p%3E%3Ch2%20id=%22try-it%22%20tabindex=%22-1%22%3E%3Ca%20class=%22header-anchor%22%20href=%22#try-it%22%3ETry%20it%3C/a%3E%3C/h2%3E%3Cp%3EBuild%20and%20run%20the%20same%20Osprey%20program%20with%20Perceus%20ARC:%3C/p%3E%3Cpre%20class=%22language-bash%22%3E%3Ccode%20class=%22language-bash%22%3Eosprey%20app.osp%20%3Cspan%20class=%22token%20parameter%20variable%22%3E--run%3C/span%3E%20%3Cspan%20class=%22token%20parameter%20variable%22%3E--memory%3C/span%3E%3Cspan%20class=%22token%20operator%22%3E=%3C/span%3Earc%3C/code%3E%3C/pre%3E%3Cp%3EYou%20do%20not%20add%20lifetime%20syntax.%20You%20do%20not%20call%20%3Ccode%3Efree%3C/code%3E.%20You%20do%20not%20change%20the%20program&#39;s%20types.%20The%20compiler%20accounts%20for%20ownership,%20and%20the%20runtime%20reclaims%20a%20value%20when%20its%20last%20owner%20goes%20away.%3C/p%3E%3Cp%3EThat%20is%20the%20memory%20model%20I%20wanted%20for%20Osprey:%20functional%20at%20the%20surface,%20explicit%20inside%20the%20compiler%20and%20governed%20by%20ownership%20counts%20at%20runtime.%20Try%20it%20on%20a%20program%20that%20builds%20persistent%20data,%20then%20watch%20what%20happens%20to%20its%20peak%20memory.%3C/p%3E</content>
    <summary>Osprey ships opt-in Perceus automatic reference counting. The compiler inserts ownership operations, and the runtime reclaims values as owner counts reach zero.</summary>
  </entry>
</feed>
