Ridgun
The language itself: a compiler that compiles itself, the stable project tool, the specification and the book
| 1 | <!DOCTYPE html> |
| 2 | <html lang="sv" data-theme="dark"> |
| 3 | <head> |
| 4 | <meta charset="UTF-8" /> |
| 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
| 6 | <title>Boken om Ridgun — Komplett Språkguide</title> |
| 7 | <style> |
| 8 | :root, [data-theme="dark"] { |
| 9 | --bg: #0f141c; |
| 10 | --bg-sidebar: #141b26; |
| 11 | --bg-card: #18212f; |
| 12 | --bg-code: #0b0f16; |
| 13 | --border: #263246; |
| 14 | --text: #e6edf3; |
| 15 | --text-muted: #94a3b8; |
| 16 | --accent: #38bdf8; |
| 17 | --accent-soft: rgba(56, 189, 248, 0.14); |
| 18 | --kw: #ff7b72; |
| 19 | --ty: #79c0ff; |
| 20 | --fn: #d2a8ff; |
| 21 | --str: #a5d6ff; |
| 22 | --num: #f2cc60; |
| 23 | --com: #6e7681; |
| 24 | --op: #ffa657; |
| 25 | --shadow: 0 8px 24px rgba(0, 0, 0, 0.35); |
| 26 | } |
| 27 | [data-theme="light"] { |
| 28 | --bg: #f8fafc; |
| 29 | --bg-sidebar: #f1f5f9; |
| 30 | --bg-card: #ffffff; |
| 31 | --bg-code: #0f172a; |
| 32 | --border: #cbd5e1; |
| 33 | --text: #0f172a; |
| 34 | --text-muted: #475569; |
| 35 | --accent: #0284c7; |
| 36 | --accent-soft: rgba(2, 132, 199, 0.12); |
| 37 | --kw: #ff7b72; |
| 38 | --ty: #79c0ff; |
| 39 | --fn: #d2a8ff; |
| 40 | --str: #a5d6ff; |
| 41 | --num: #f2cc60; |
| 42 | --com: #94a3b8; |
| 43 | --op: #ffa657; |
| 44 | --shadow: 0 4px 16px rgba(15, 23, 42, 0.08); |
| 45 | } |
| 46 | * { box-sizing: border-box; } |
| 47 | body { |
| 48 | margin: 0; |
| 49 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, sans-serif; |
| 50 | background: var(--bg); |
| 51 | color: var(--text); |
| 52 | line-height: 1.72; |
| 53 | display: flex; |
| 54 | min-height: 100vh; |
| 55 | } |
| 56 | /* Sidebar */ |
| 57 | aside.sidebar { |
| 58 | width: 310px; |
| 59 | background: var(--bg-sidebar); |
| 60 | border-right: 1px solid var(--border); |
| 61 | display: flex; |
| 62 | flex-direction: column; |
| 63 | position: fixed; |
| 64 | top: 0; |
| 65 | bottom: 0; |
| 66 | left: 0; |
| 67 | z-index: 20; |
| 68 | overflow-y: auto; |
| 69 | } |
| 70 | .brand { |
| 71 | padding: 1.35rem 1.25rem 1rem; |
| 72 | border-bottom: 1px solid var(--border); |
| 73 | } |
| 74 | .brand-top { |
| 75 | display: flex; |
| 76 | justify-content: space-between; |
| 77 | align-items: center; |
| 78 | margin-bottom: 0.45rem; |
| 79 | } |
| 80 | .brand-badge { |
| 81 | display: inline-block; |
| 82 | font-size: 0.72rem; |
| 83 | font-weight: 700; |
| 84 | text-transform: uppercase; |
| 85 | letter-spacing: 0.08em; |
| 86 | color: var(--accent); |
| 87 | background: var(--accent-soft); |
| 88 | padding: 0.2rem 0.55rem; |
| 89 | border-radius: 999px; |
| 90 | } |
| 91 | .lang-bar { |
| 92 | display: flex; |
| 93 | gap: 0.25rem; |
| 94 | } |
| 95 | .lang-link { |
| 96 | font-size: 0.72rem; |
| 97 | font-weight: 600; |
| 98 | text-decoration: none; |
| 99 | color: var(--text-muted); |
| 100 | padding: 0.16rem 0.42rem; |
| 101 | border-radius: 5px; |
| 102 | border: 1px solid var(--border); |
| 103 | } |
| 104 | .lang-link:hover, .lang-link.active { |
| 105 | color: var(--accent); |
| 106 | border-color: var(--accent); |
| 107 | background: var(--accent-soft); |
| 108 | } |
| 109 | .brand h1 { |
| 110 | margin: 0; |
| 111 | font-size: 1.25rem; |
| 112 | font-weight: 800; |
| 113 | letter-spacing: -0.02em; |
| 114 | } |
| 115 | .brand p { |
| 116 | margin: 0.25rem 0 0; |
| 117 | font-size: 0.83rem; |
| 118 | color: var(--text-muted); |
| 119 | } |
| 120 | .search-box { |
| 121 | padding: 0.85rem 1.1rem; |
| 122 | border-bottom: 1px solid var(--border); |
| 123 | } |
| 124 | .search-box input { |
| 125 | width: 100%; |
| 126 | padding: 0.55rem 0.75rem; |
| 127 | border-radius: 8px; |
| 128 | border: 1px solid var(--border); |
| 129 | background: var(--bg); |
| 130 | color: var(--text); |
| 131 | font-size: 0.88rem; |
| 132 | outline: none; |
| 133 | } |
| 134 | .search-box input:focus { |
| 135 | border-color: var(--accent); |
| 136 | } |
| 137 | .nav-list { |
| 138 | list-style: none; |
| 139 | padding: 0.75rem 0.65rem 1.5rem; |
| 140 | margin: 0; |
| 141 | flex: 1; |
| 142 | } |
| 143 | .nav-item { |
| 144 | margin-bottom: 0.25rem; |
| 145 | } |
| 146 | .nav-btn { |
| 147 | width: 100%; |
| 148 | text-align: left; |
| 149 | background: transparent; |
| 150 | border: none; |
| 151 | color: var(--text-muted); |
| 152 | padding: 0.62rem 0.75rem; |
| 153 | border-radius: 8px; |
| 154 | font-size: 0.9rem; |
| 155 | cursor: pointer; |
| 156 | display: flex; |
| 157 | align-items: flex-start; |
| 158 | gap: 0.55rem; |
| 159 | transition: all 0.15s ease; |
| 160 | line-height: 1.38; |
| 161 | } |
| 162 | .nav-btn:hover { |
| 163 | background: var(--accent-soft); |
| 164 | color: var(--text); |
| 165 | } |
| 166 | .nav-btn.active { |
| 167 | background: var(--accent-soft); |
| 168 | color: var(--accent); |
| 169 | font-weight: 600; |
| 170 | } |
| 171 | .nav-num { |
| 172 | font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; |
| 173 | font-size: 0.78rem; |
| 174 | opacity: 0.8; |
| 175 | min-width: 1.5rem; |
| 176 | padding-top: 0.08rem; |
| 177 | } |
| 178 | .sidebar-footer { |
| 179 | padding: 0.85rem 1.1rem; |
| 180 | border-top: 1px solid var(--border); |
| 181 | display: flex; |
| 182 | justify-content: space-between; |
| 183 | align-items: center; |
| 184 | font-size: 0.8rem; |
| 185 | color: var(--text-muted); |
| 186 | } |
| 187 | .theme-btn { |
| 188 | background: var(--bg-card); |
| 189 | color: var(--text); |
| 190 | border: 1px solid var(--border); |
| 191 | border-radius: 6px; |
| 192 | padding: 0.35rem 0.65rem; |
| 193 | font-size: 0.8rem; |
| 194 | cursor: pointer; |
| 195 | } |
| 196 | /* Main content */ |
| 197 | main.reader { |
| 198 | margin-left: 310px; |
| 199 | flex: 1; |
| 200 | display: flex; |
| 201 | justify-content: center; |
| 202 | padding: 2.5rem 2rem 5rem; |
| 203 | } |
| 204 | article.chapter { |
| 205 | max-width: 820px; |
| 206 | width: 100%; |
| 207 | } |
| 208 | article.chapter h1 { |
| 209 | font-size: 2.15rem; |
| 210 | line-height: 1.22; |
| 211 | margin-top: 0; |
| 212 | margin-bottom: 1.25rem; |
| 213 | letter-spacing: -0.025em; |
| 214 | border-bottom: 1px solid var(--border); |
| 215 | padding-bottom: 0.85rem; |
| 216 | } |
| 217 | article.chapter h2 { |
| 218 | font-size: 1.48rem; |
| 219 | margin-top: 2.6rem; |
| 220 | margin-bottom: 0.85rem; |
| 221 | color: var(--accent); |
| 222 | letter-spacing: -0.015em; |
| 223 | } |
| 224 | article.chapter h3 { |
| 225 | font-size: 1.16rem; |
| 226 | margin-top: 1.8rem; |
| 227 | margin-bottom: 0.6rem; |
| 228 | } |
| 229 | article.chapter p { |
| 230 | margin: 0 0 1.1rem; |
| 231 | } |
| 232 | article.chapter ul, article.chapter ol { |
| 233 | margin: 0 0 1.25rem; |
| 234 | padding-left: 1.45rem; |
| 235 | } |
| 236 | article.chapter li { |
| 237 | margin-bottom: 0.4rem; |
| 238 | } |
| 239 | article.chapter hr { |
| 240 | border: none; |
| 241 | border-top: 1px solid var(--border); |
| 242 | margin: 2.2rem 0; |
| 243 | } |
| 244 | article.chapter blockquote { |
| 245 | margin: 1.35rem 0; |
| 246 | padding: 0.9rem 1.15rem; |
| 247 | border-left: 4px solid var(--accent); |
| 248 | background: var(--accent-soft); |
| 249 | border-radius: 0 8px 8px 0; |
| 250 | } |
| 251 | article.chapter blockquote p:last-child { |
| 252 | margin-bottom: 0; |
| 253 | } |
| 254 | /* Code blocks */ |
| 255 | .code-wrapper { |
| 256 | position: relative; |
| 257 | margin: 1.25rem 0 1.5rem; |
| 258 | border-radius: 10px; |
| 259 | overflow: hidden; |
| 260 | border: 1px solid var(--border); |
| 261 | background: var(--bg-code); |
| 262 | box-shadow: var(--shadow); |
| 263 | } |
| 264 | .code-header { |
| 265 | display: flex; |
| 266 | justify-content: space-between; |
| 267 | align-items: center; |
| 268 | padding: 0.42rem 0.9rem; |
| 269 | background: rgba(255, 255, 255, 0.04); |
| 270 | border-bottom: 1px solid rgba(255, 255, 255, 0.07); |
| 271 | font-size: 0.75rem; |
| 272 | color: #94a3b8; |
| 273 | font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; |
| 274 | } |
| 275 | .copy-btn { |
| 276 | background: rgba(255, 255, 255, 0.08); |
| 277 | color: #e2e8f0; |
| 278 | border: 1px solid rgba(255, 255, 255, 0.14); |
| 279 | border-radius: 5px; |
| 280 | padding: 0.18rem 0.55rem; |
| 281 | font-size: 0.73rem; |
| 282 | cursor: pointer; |
| 283 | } |
| 284 | .copy-btn:hover { |
| 285 | background: rgba(56, 189, 248, 0.25); |
| 286 | } |
| 287 | pre { |
| 288 | margin: 0; |
| 289 | padding: 1rem 1.15rem; |
| 290 | overflow-x: auto; |
| 291 | font-family: "JetBrains Mono", "Fira Code", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; |
| 292 | font-size: 0.89rem; |
| 293 | line-height: 1.58; |
| 294 | color: #e6edf3; |
| 295 | } |
| 296 | p code, li code, td code { |
| 297 | font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; |
| 298 | font-size: 0.86em; |
| 299 | background: var(--accent-soft); |
| 300 | color: var(--accent); |
| 301 | padding: 0.15rem 0.38rem; |
| 302 | border-radius: 5px; |
| 303 | } |
| 304 | /* Tables */ |
| 305 | .table-wrap { |
| 306 | overflow-x: auto; |
| 307 | margin: 1.35rem 0; |
| 308 | border: 1px solid var(--border); |
| 309 | border-radius: 10px; |
| 310 | } |
| 311 | table { |
| 312 | width: 100%; |
| 313 | border-collapse: collapse; |
| 314 | font-size: 0.92rem; |
| 315 | } |
| 316 | th, td { |
| 317 | padding: 0.7rem 0.95rem; |
| 318 | border-bottom: 1px solid var(--border); |
| 319 | text-align: left; |
| 320 | } |
| 321 | th { |
| 322 | background: var(--bg-sidebar); |
| 323 | font-weight: 700; |
| 324 | } |
| 325 | tr:last-child td { |
| 326 | border-bottom: none; |
| 327 | } |
| 328 | /* Syntax tokens */ |
| 329 | .rg-com { color: var(--com); font-style: italic; } |
| 330 | .rg-kw { color: var(--kw); font-weight: 600; } |
| 331 | .rg-ty { color: var(--ty); font-weight: 600; } |
| 332 | .rg-str { color: var(--str); } |
| 333 | .rg-num { color: var(--num); } |
| 334 | .rg-op { color: var(--op); font-weight: 600; } |
| 335 | /* Chapter pager */ |
| 336 | .pager { |
| 337 | margin-top: 3.5rem; |
| 338 | padding-top: 1.5rem; |
| 339 | border-top: 1px solid var(--border); |
| 340 | display: flex; |
| 341 | justify-content: space-between; |
| 342 | gap: 1rem; |
| 343 | } |
| 344 | .pager-btn { |
| 345 | flex: 1; |
| 346 | padding: 0.9rem 1.1rem; |
| 347 | border-radius: 10px; |
| 348 | border: 1px solid var(--border); |
| 349 | background: var(--bg-card); |
| 350 | color: var(--text); |
| 351 | cursor: pointer; |
| 352 | text-align: left; |
| 353 | transition: border-color 0.15s ease; |
| 354 | } |
| 355 | .pager-btn.next { text-align: right; } |
| 356 | .pager-btn:hover { border-color: var(--accent); } |
| 357 | .pager-label { |
| 358 | display: block; |
| 359 | font-size: 0.76rem; |
| 360 | color: var(--text-muted); |
| 361 | margin-bottom: 0.2rem; |
| 362 | } |
| 363 | .pager-title { |
| 364 | font-weight: 600; |
| 365 | color: var(--accent); |
| 366 | font-size: 0.95rem; |
| 367 | } |
| 368 | .search-results { |
| 369 | margin-bottom: 2rem; |
| 370 | padding: 1rem 1.2rem; |
| 371 | border-radius: 10px; |
| 372 | border: 1px solid var(--accent); |
| 373 | background: var(--bg-card); |
| 374 | } |
| 375 | .search-hit { |
| 376 | padding: 0.6rem 0; |
| 377 | border-bottom: 1px solid var(--border); |
| 378 | cursor: pointer; |
| 379 | } |
| 380 | .search-hit:last-child { border-bottom: none; } |
| 381 | .search-hit-title { color: var(--accent); font-weight: 600; } |
| 382 | .search-hit-snippet { font-size: 0.86rem; color: var(--text-muted); } |
| 383 | @media (max-width: 860px) { |
| 384 | aside.sidebar { position: static; width: 100%; border-right: none; border-bottom: 1px solid var(--border); } |
| 385 | body { flex-direction: column; } |
| 386 | main.reader { margin-left: 0; padding: 1.5rem 1.1rem 3rem; } |
| 387 | } |
| 388 | </style> |
| 389 | </head> |
| 390 | <body> |
| 391 | <aside class="sidebar"> |
| 392 | <div class="brand"> |
| 393 | <div class="brand-top"> |
| 394 | <span class="brand-badge">Ridgun v0.9.32</span> |
| 395 | <div class="lang-bar"><a class="lang-link" href="../es/index.html">ES</a><a class="lang-link" href="../ca/index.html">CA</a><a class="lang-link" href="../gl/index.html">GL</a><a class="lang-link" href="../eu/index.html">EU</a><a class="lang-link" href="../en/index.html">EN</a><a class="lang-link" href="../pt/index.html">PT</a><a class="lang-link active" href="index.html">SV</a><a class="lang-link" href="../it/index.html">IT</a></div> |
| 396 | </div> |
| 397 | <h1>Boken om Ridgun</h1> |
| 398 | <p>Från noll till expert på tabulär funktionell och systemprogrammering</p> |
| 399 | </div> |
| 400 | <div class="search-box"> |
| 401 | <input type="search" id="searchInput" placeholder="Sök i boken (t.ex. ||, Tensor, RMM2, TCO...)" /> |
| 402 | </div> |
| 403 | <ul class="nav-list" id="navList"></ul> |
| 404 | <div class="sidebar-footer"> |
| 405 | <span>9 kapitel (00–08) · Svenska</span> |
| 406 | <button class="theme-btn" id="themeBtn" type="button">☀️ / 🌙 Tema</button> |
| 407 | </div> |
| 408 | </aside> |
| 409 | |
| 410 | <main class="reader"> |
| 411 | <article class="chapter" id="chapterContent"></article> |
| 412 | </main> |
| 413 | |
| 414 | <script> |
| 415 | const CHAPTERS = [{"num":"00","slug":"00-varfor-behover-jag-ridgun","file":"00-varfor-behover-jag-ridgun.md","title":"Kapitel 00: Varför behöver jag Ridgun? Jaså? Det visste jag inte... Berätta mer!","short_title":"Varför behöver jag Ridgun? Jaså? Det visste jag inte... Berätta mer!","markdown":"# Kapitel 00: Varför behöver jag Ridgun? Jaså? Det visste jag inte... Berätta mer!\n\nLåt oss vara ärliga: när någon säger *\"vi har skapat ett nytt programmeringsspråk\"* är din första naturliga — och mycket sunda — reaktion att höja på ögonbrynet och tänka:\n\n> *\"Ännu ett? Men jag har ju redan Python när det ska gå fort, Rust eller C när jag behöver prestanda, och Bash för att klistra ihop saker i terminalen. Varför i hela friden skulle jag behöva lära mig Ridgun?\"*\n\nDet är en utmärkt fråga. Och det korta svaret är: **därför att du har vant dig vid att lida av tre dagliga plågor i tron att de var oundvikliga**.\n\nLåt oss sätta namn på dem.\n\n---\n\n## Plåga nr 1: \"Tvåvärldssyndromet\" (Prototypa i ett språk, skriva om i ett annat)\n\nDu har säkert varit med om den här filmen:\n\n1. Du påbörjar ett verktyg eller en beräkningsmotor i **Python**, **JavaScript** eller **Ruby** eftersom du vill tänka på problemet, inte på pekare eller kompilatorn.\n2. Koden blir kort och vacker... men när du matar den med en fil på 500 MB eller försöker utnyttja alla 16 kärnor i din dator kryper den fram. Och om du vill distribuera ditt program till en ren server måste du paketera en halv gigabyte med virtuell miljö, tolk och dynamiska bibliotek.\n3. Uppgiven bestämmer du dig för att skriva om det i **C**, **C++** eller **Rust**. Nu flyger det fram och tar bara några hundra kilobyte, men din kod på 40 rader har förvandlats till 300 rader fulla av `unwrap()`, `&mut`, `'a`, `Arc<Mutex<...>>`, måsvingar `{}` och semikolon `;`.\n\n**Vad förändras med Ridgun?**\nI Ridgun skriver du kod som är **kortare och renare än i Python**, men när du kör `ridgunc build` får du **en enda inbyggd ELF-binär på ~350 KB** utan tolk, utan extern virtuell maskin och utan skräpsamlare (*Garbage Collector*). Det finns ingen fas där man säger *\"vi skriver om det i det snabba språket senare\"*: den rena koden där du formulerar problemet **är redan** produktionsbinären.\n\n---\n\n## Plåga nr 2: \"Att läsa andras kod (eller din egen från för 6 månader sedan) är som att leka detektiv\"\n\nTitta på hur vi skriver villkorslogik i nästan alla vanliga språk:\n\n```text\nif (status == AKTIV && (roll == ADMIN || (roll == REDAKTOR && harBehorighet))) {\n if (kvot > 0) {\n return bearbeta(anvandare);\n } else {\n return neka(\"Ingen kvot\");\n }\n} else {\n return neka(\"Obehörig\");\n}\n```\n\nVåra ögon har inte utvecklats för att para ihop nästlade måsvingar eller nysta upp trappstegsformade `if / else`-träd. När ingenjörer, matematiker eller fysiker vill förstå komplexa regler utan att göra fel skriver de inte stycken av `if / else`: **de ritar en tabell**.\n\nI Ridgun **är koden den tabellen**:\n\n```ridgun\nauktorisera String String Bool Int => String\nauktorisera \"aktiv\" \"admin\" _ kvot =\n | kvot > 0 = \"Bearbetar begäran\"\n | otherwise = \"Nekad: ingen kvot\"\nauktorisera \"aktiv\" \"redaktor\" True kvot =\n | kvot > 0 = \"Bearbetar begäran\"\n | otherwise = \"Nekad: ingen kvot\"\nauktorisera _ _ _ _ = \"Nekad: obehörig\"\n```\n\nTitta på kolumnerna:\n- Kolumn 1: statusen (`\"aktiv\"` eller `_`).\n- Kolumn 2: rollen (`\"admin\"`, `\"redaktor\"` eller `_`).\n- Kolumn 3: om behörighet finns (`True` eller `_`).\n- Kolumn 4: `kvot`.\n\nDu behöver inte köra programmet mentalt rad för rad för att veta vad som händer när en `\"redaktor\"` med behörigheten `False` kommer in: blicken glider vertikalt nedför tabellen och du ser det på en halv sekund.\n\n---\n\n## Plåga nr 3: \"Min dator har 16 kärnor, men mitt program använder bara 1 (för att jag får panik av att röra trådar)\"\n\nI dag har till och med den enklaste telefonen 8 kärnor, och varje server eller arbetsdator har mellan 12 och 32. Ändå körs 95 % av alla vardagliga program fortfarande i en enda sekventiell tråd.\n\nVarför? Därför att i imperativa språk innebär parallellisering att öppna Pandoras ask:\n- Tänk om två trådar ändrar samma uppslagsverk samtidigt? (*Data race*).\n- Tänk om jag låser `Mutex` A och sedan B i en tråd, och B och sedan A i en annan? (*Deadlock*).\n- Tänk om jag förorenar hela min kodbas med `async` och `await` uppifrån och ner?\n\nI Ridgun **är varje funktion ren och all data oföränderlig (*immutable*) som standard**. Det får en magisk konsekvens: **två uttryck som inte är beroende av varandra kan aldrig någonsin störa varandra**.\n\nDärför behöver du inte hantera trådar i Ridgun för att utnyttja din processor. Du deklarerar bara **vad som beror på vad** med parallella streck `||` och pilar `->`:\n\n```ridgun\nmanadsrapport Data => Rapport\nmanadsrapport d = kombinera nat_matt disk_matt cpu_matt\n || analysera nat d -> nat_matt\n || analysera disk d -> disk_matt\n || analysera cpu d -> cpu_matt\n```\n\nDu har bara skrivit tre rena rader som anger varifrån varje datamängd kommer. Kompilatorn ser att de tre grenarna är oberoende och vet att den kan starta dem parallellt utan minsta risk för vare sig *data race* eller *deadlock*.\n\nOch vad gör du om du behöver långlivade agenter med inkorg och isolerat tillstånd (till exempel för att hålla tusentals klientsessioner, bakgrundsarbetare eller nätverksanslutningar)? I Ridgun behöver du varken definiera `Actor`-klasser eller använda `Mutex`: **vilken vanlig funktion som helst blir en autonom agent på en enda rad med `agent`**:\n\n```ridgun\nraknare = agent (addera besok) 0\nsend 1 to raknare\nsend 5 to raknare\ntotalt = receive from raknare\nstop raknare\n```\n\nDessutom gör kompilatorn ett **smart val vid kompilering**: den analyserar statiskt djupet och kostnaden för varje funktion i `||`, `||map`, `||filter` och `agent` för att köra lätta funktioner som *green-thread*-steg utan overhead och automatiskt skicka tunga eller djupt rekursiva beräkningar till riktiga kärntrådar över flera CPU-kärnor (`SYS_clone`).\n\n---\n\n## Plåga nr 4: \"Skräpsamlaren bestämmer sig för att pausa hela världen i exakt fel ögonblick\"\n\nKlassiska funktionella språk (Haskell, OCaml, Erlang, Clojure) är underbara för att resonera kring kod, men nästan alla är beroende av en **skräpsamlare (*Garbage Collector*)** vid körning. Det utesluter dem när du behöver:\n- Förutsägbara svarstider på mikrosekundnivå.\n- Exakt kontroll över hur mycket RAM-minne en operation får förbruka innan den avbryts snyggt.\n- Skriva operativsystemverktyg (`ls`, `find`, `sh`, `doas`, `make`) eller arbeta direkt mot hårdvaruregister (`MMIO`).\n\nRidgun ger dig **hela elegansen från den rent funktionella världen, men med Ridguns minneshantering (`RMM`: statisk `RMM1` och kaskadräknad `RMM2`) plus lexikala regioner med exakt kvot (`with region`)**:\n\n```ridgun\ntolka paket String => Result\ntolka paket radata =\n with region 16_KB do\n avkoda ram radata\n```\n\nVarje tillfällig struktur frigörs deterministiskt av kompilatorn (`RMM1` / `RMM2`) i samma ögonblick som den slutar användas, och om en angripare skickar ett skadligt paket utformat för att spränga minnet klipps regionen omedelbart när den passerar byte 16 384, frigör sin arena i $O(1)$ och returnerar `Err OutOfMemory`. Inga kraschade processer, inga GC-pauser och inga minnesläckor.\n\n---\n\n## Sammanfattningsvis: När glänser Ridgun?\n\nRidgun är skapat för dig om du någonsin har velat:\n\n1. **Skriva systemverktyg, kompilatorer, parsrar eller CLI-verktyg** som startar på mikrosekunder, väger några hundra KB och inte kan krascha på grund av null-pekare eller dolda sidoeffekter.\n2. **Bygga samtidiga system och servrar med den inbyggda agentmodellen (`agent`, `send ... to`, `receive from`, `stop`)**, där varje ren funktion kan bli en agent med eller utan isolerat tillstånd och kompilatorn smart väljer mellan ultralätta *green-thread*-steg och flerkärniga operativsystemtrådar.\n3. **Programmera algoritmer, datapipelines eller tensoralgebra** där kompilatorn kontrollerar ända ner till matrisdimensionerna åt dig (`Tensor[M, K] * Tensor[K, N] => Tensor[M, N]`) innan något ens körs.\n4. **Njuta av att läsa din egen kod**: låta varje `.rg`-fil se ut som en sida ur en välformgiven bok tack vare den automatiska tabellformateraren (`stable format`).\n\nHar vi väckt din nyfikenhet? Gå vidare till **Kapitel 01** så skriver vi vårt första program på under två minuter.\n"}, {"num":"01","slug":"01-valkommen-till-ridgun","file":"01-valkommen-till-ridgun.md","title":"Kapitel 01: Din första kontakt med Ridgun (Utan hjälm, utan måsvingar och utan semikolon)","short_title":"Din första kontakt med Ridgun (Utan hjälm, utan måsvingar och utan semikolon)","markdown":"# Kapitel 01: Din första kontakt med Ridgun (Utan hjälm, utan måsvingar och utan semikolon)\n\nOkej, i Kapitel 00 övertygade jag dig om att vi inte är galna som har skapat Ridgun. Nu tänker du säkert:\n\n> *\"Mycket fint snack om tabeller och 16 kärnor, men visa mig riktig kod. Hur lång tid tar det att skriva något som fungerar utan att behöva slåss med kompilatorn?\"*\n\nDå kör vi — rakt på sak!\n\n---\n\n## 1.1. \"Hej, världen!\", men med substans\n\nI de flesta programmeringsböcker visar man ett trist `print(\"Hej världen\")` och vänder blad. Vi ska gå direkt på att skriva en funktion med riktig logik så att du ser hur Ridgun andas från första minuten.\n\nSkapa en fil som heter `hej.rg` och skriv det här:\n\n```ridgun\nhalsning String => String\nhalsning \"\" = \"Hej, mystiska resenär! (Du har inte sagt vad du heter)\"\nhalsning \"Root\" = \"Men se där, Root! Var försiktig med vad du raderar i dag.\"\nhalsning namn = \"Hej, {namn}! Välkommen till Ridgun.\"\n\nmain => ()\nmain =\n echo (halsning \"Ada\")\n echo (halsning \"Root\")\n echo (halsning \"\")\n```\n\nFör att köra det direkt:\n\n```bash\nridgunc run hej.rg\n```\n\nOch du kommer att se i din terminal:\n\n```text\nHej, Ada! Välkommen till Ridgun.\nMen se där, Root! Var försiktig med vad du raderar i dag.\nHej, mystiska resenär! (Du har inte sagt vad du heter)\n```\n\nStanna upp ett ögonblick och titta på `halsning`-blocket ovan. Märker du vad som **INTE** finns där?\n- **Det finns inget `function`, inget `def` och inget `pub fn`** (om du vill sätta `fn ::` framför signaturen går det bra, men det är valfritt).\n- **Det finns inga parenteser `(String namn)` eller måsvingar `{ ... }`** som skräpar ner skärmen.\n- **Det finns inget `if (namn == \"\") ... else if (namn == \"Root\") ... else ...`**.\n- **Det finns inget `return`**.\n\n---\n\n## 1.2. Hur din hjärna läser en `.rg`-fil\n\nLåt oss plocka isär de fyra raderna i `halsning`, för här finns redan 50 % av Ridguns filosofi:\n\n```ridgun\nhalsning String => String\nhalsning \"\" = \"Hej, mystiska resenär! (Du har inte sagt vad du heter)\"\nhalsning \"Root\" = \"Men se där, Root! Var försiktig med vad du raderar i dag.\"\nhalsning namn = \"Hej, {namn}! Välkommen till Ridgun.\"\n```\n\n1. **Den första raden är kontraktet (`halsning String => String`)**:\n Den säger: *\"Jag heter `halsning`, jag tar emot en `String` och jag ger dig tillbaka (`=>`) en annan `String`\"*. Punkt. Om någon försöker anropa mig och skicka in talet `42` kommer kompilatorn att knacka dem på axeln innan programmet ens körs.\n2. **Raderna nedanför är fallen (uppifrån och ner)**:\n - Har du skickat in den tomma strängen `\"\"`? Då returnerar jag den första meningen.\n - Har du skickat in exakt `\"Root\"`? Då returnerar jag den andra meningen.\n - Har du skickat in vad som helst annat? Då sparar jag det i variabeln `namn` och stoppar in det i texten med hjälp av `{namn}`.\n3. **Och vad är `main => ()`?**:\n Eftersom `main` inte tar några argument sätter vi `=>` direkt efter namnet. Och den returnerar `()` (den tomma typen eller *Unit*, vänner emellan), eftersom dess enda uppgift är att skriva ut saker på skärmen med `echo`.\n\n---\n\n## 1.3. \"Vänta... måste jag rada upp de där mellanslagen för hand som en medeltida skrivarmunk?\"\n\nAbsolut inte! Om du var tvungen att trycka på mellanslagstangenten och räkna kolumner med ögonmått skulle du överge Ridgun efter tio minuter (och det med rätta).\n\nDu skriver koden snabbt, med ett enda mellanslag mellan varje ord:\n\n```ridgun\nhalsning String => String\nhalsning \"\" = \"Hej, mystiska resenär!\"\nhalsning namn = \"Hej, {namn}!\"\n```\n\nOch när du kör **`stable format`** (eller trycker `TAB` / sparar filen i Emacs med `ridgun-mode`) placerar den kanoniska formateraren varje parameter under sin typ och justerar alla `=` med millimeterprecision. Du skriver snabbt; maskinen formger tabellen.\n\n---\n\n## 1.4. Från snabbt skript till stridsduglig binär med ett enda kommando\n\nNär du kör `ridgunc run hej.rg` kompilerar och startar du programmet i farten. Men föreställ dig att du har blivit klar med ditt verktyg och vill ta med det till en produktionsserver eller dela det med en kollega som inte har Ridgun installerat.\n\nDu kör:\n\n```bash\nridgunc build hej.rg -o hej\n```\n\nOch så har du `./hej`: en **inbyggd ELF-körbar fil för Linux x86_64**, ren, utan död kod (*Tree-Shaking*), med länkoptimering över hela programmet (*LTO*) och helt oberoende av någon extern tolk.\n\n---\n\n## 1.5. Den ärliga fusklappen: Varifrån kommer varje idé i Ridgun?\n\nRidgun försöker inte uppfinna ett fyrkantigt hjul på nytt; det lånar skamlöst det bästa från fyra traditioner:\n\n| Från vem | Vad Ridgun lånar | Vad det lämnar utanför (för din mentala hälsas skull) |\n|---|---|---|\n| **Haskell / ML** | Rena funktioner, mönstermatchning (*pattern matching*) per fall, algebraiska datatyper (`Option`, `Result`) och polymorfism (`A`..`Z`). | De abstrakta monaderna, de 40 `LANGUAGE`-pragmana och skräpsamlaren. |\n| **J / APL** | Besattheten av kodens tabellform, inbyggda tensorer och sekvensmasker (`s(_ + _)`). | De hieroglyfiska symbolerna som är omöjliga att skriva på ett vanligt tangentbord. |\n| **Rust / C** | Små inbyggda ELF-binärer, noll GC, minneskontroll (`with region`) och POSIX-systemanrop. | Den ständiga kampen med *borrow checker*, livstider `'a` och syntaktisk mångordighet. |\n| **Erlang / Go** | Isolerade agenter (`agent`, `send ... to`, `receive from`) och samtidighet via kanaler (`new bounded channel`). | `nil`-pekare och delade muteringar av misstag. |\n\n---\n\n## 1.6. Och det viktigaste: Vad gör Ridgun som INGEN annan har?\n\nAtt erkänna klassikerna hör till god ton, men om Ridgun bara vore en \"Greatest Hits-samling\" från andra språk skulle du inte läsa den här boken.\n\nDet finns **åtta saker** som vi har konstruerat och integrerat i Ridgun som du inte kommer att hitta tillsammans — och många av dem inte ens var för sig — i något annat nutida språk:\n\n### 1. Parallella `||`-block med `->` som är äkta parallella grafer, inte bara syntaktiskt socker\nI andra funktionella språk ordnar ett block med lokala variabler bara uttryck som sedan evalueras i en enda tråd.\nI Ridgun är **ett `||`-block med pilar `->` en riktad acyklisk graf (DAG) för parallell körning** utan att du ens behöver skriva extra nyckelord som `where`:\n```ridgun\narsrapport Int => Int\narsrapport id = intakter - utgifter\n || berakna forsaljning id -> intakter\n || berakna kostnader id -> utgifter\n```\nDu ritar flödespilarna (`->`). Kompilatorn analyserar vem som beror på vem, **verifierar statiskt att du inte har skapat någon oändlig cykel** och startar de oberoende grenarna parallellt utan att du skriver ett enda `async`, `await`, `Future` eller `Mutex`.\n\n### 2. Friktionsfri inbyggd agentmodell (`agent`) med smart trådval vid kompilering\nI andra språk tvingar aktörs- eller agentprogrammering dig att skapa specialklasser, implementera *traits*, hantera lås eller smitta ner dina funktioner med `async`.\nI Ridgun **förvandlas vilken vanlig ren funktion som helst (`fn ::` eller `op ::`) direkt till en autonom agent — med eller utan isolerat tillstånd — med hjälp av `agent`**:\n```ridgun\nhantera http (Session, String) => (Session, String)\n...\nserver = agent hantera http startsession\nsend \"GET /profil\" to server\nsvar = receive from server\nstop server\n```\nÄnnu bättre: kompilatorn **analyserar funktionens djup och beräkningskostnad vid kompilering** i både `agent`, `||` och `||map`. Om funktionen är lättviktig körs den som en omedelbar *green thread* utan kostnaden för att värma upp operativsystemtrådar; om den är en tung eller djupt rekursiv beräkning skickas den automatiskt ut parallellt över riktiga kärntrådar (`SYS_clone`) på dina CPU-kärnor.\n\n### 3. Koden som en tvådimensionell tabell där signaturen är kolumnrubriken\nI alla andra språk lever typsignaturen sitt eget liv på en rad och funktionskroppen ligger nedanför som ett vanligt textstycke.\nI Ridgun **är typsignaturen bokstavligen tabellens rubrikrad**, och varje fall nedanför justerar varje mönster rakt under sin typ och varje `=` under `=>`:\n```ridgun\ndividera Int Int => Option\ndividera _ 0 = None\ndividera a b = Some (a / b)\n```\nIngen annan behandlar signaturen och ekvationerna som en enda visuell matris som verifieras av kompilatorn och formges automatiskt av `stable format`.\n\n### 4. Typade och justerade frasoperatorer (*N-ära Mixfix*) (`op ::`)\nI de flesta språk får du antingen nöja dig med `+`, `-`, `*` eller på sin höjd definiera en kryptisk binär operator som `<|>` som ingen vet vad den betyder.\nI Ridgun kan du skapa **operatorer som är läsbara fraser med så många typade platser du vill** (inklusive kontextuella ord som `type` eller `with`):\n```ridgun\nop :: Int begransad mellan Int och Int => Int\n x begransad mellan min och max =\n | x < min = min\n | x > max = max\n | otherwise = x\n```\nOch sedan skriver du i din kod `hastighet begransad mellan 0 och 120`. Det läses som vanlig svenska (eller engelska), men är till 100 % typat och kompilerat till maskinkod.\n\n### 5. Visuella masker över sekvenser (`s(_ + _)` och `-> (+ _ _ +) ->`)\nHar du någonsin behövt skriva en hel sallad av index eller packa upp en tupel med dummyvariabler bara för att behålla två specifika positioner?\nI Ridgun skickar du direkt in en **visuell mask**:\n- `data(_ + _)`: kastar det första (`_`), behåller det andra (`+`), kastar det tredje (`_`).\n- `tolka paket \"v0.9.9\" -> (+ _ _ +) -> kombinera kod -> sammanfattning`: filtrerar en tupel med 4 element mitt i en pipeline och skickar det 1:a och 4:e direkt som argument till nästa funktion.\nNoll indexaritmetik, noll *off-by-one*-fel.\n\n### 6. Polymorfism med \"noll brus\" (`A`..`Z`) styrd av din domän\nI Rust, TypeScript eller Java måste du fylla raden med vinkelparenteser när en funktion är generisk: `fn byt_plats<A, B>(par: (A, B)) -> (B, A)`.\nI Ridgun använder du helt enkelt en fristående versal:\n```ridgun\nbyt plats (A, B) => (B, A)\nbyt plats (x, y) = (y, x)\n```\n*\"Men tänk om jag i mitt program vill ha en riktig typ som heter `type A`?\"* — Inga problem: i Ridgun **är det dina `type`-deklarationer som bestämmer**. Om `type A` inte finns är `A` generisk; i samma ögonblick som du definierar `type A = ...` blir den din konkreta typ i hela modulen.\n\n### 7. Noll konstiga konfigurationsfiler: `build.rg` är ren Ridgun\nGlöm att behöva lära dig TOML för Cargo, JSON för npm, XML för Maven eller den arkaiska syntaxen i `Makefile` med osynliga tabulatorer. I Ridgun är receptet som bygger ditt projekt (`build.rg`) **bara ännu en `.rg`-fil**, med samma rena funktioner och samma mönstermatchning som resten av din kod.\n\n### 8. Den \"heliga treenigheten\" som verkade omöjlig: Haskell-nivå + RMM-minne utan GC eller Lifetimes + Binärer på ~350 KB\nFram till i dag var du tvungen att välja:\n- Om du ville ha ren funktionell uttrycksfullhet (Haskell, OCaml, Elixir) betalade du med en skräpsamlare och en tung körtidsmiljö.\n- Om du ville ha pyttesmå systembinärer utan skräpsamlare (C, Rust, Zig) betalade du genom att hantera pekare eller brottas med *borrow checker* och skriva imperativ kod full av `let mut`.\n\nRidgun bryter det dilemmat genom att kombinera **Ridgun Memory Management (`RMM`: statisk `RMM1` och kaskadräknad `RMM2`)**, **lexikala regioner (`with region`)** som frigör hela arenor i $O(1)$, **svansrekursion som omvandlas till inbyggda loopar (`loop`)** samt **beskärning av anropsgrafen (*Tree-Shaking*)** från `main`. Resultatet: du skriver deklarativ kod på allra högsta nivå och får en fristående ELF-körbar fil på **~350 KB** som kan mäta sig öga mot öga med verktyg skrivna i C.\n\nNu ligger korten på bordet: låt oss gå vidare till **Kapitel 02** för att sätta **`ridgunc`** och **`stable`** i arbete.\n"}, {"num":"02","slug":"02-forsta-stegen-och-verktyg","file":"02-forsta-stegen-och-verktyg.md","title":"Kapitel 02: Dina två bästa vänner: `ridgunc` och `stable` (Noll YAML-filer, jag lovar)","short_title":"Dina två bästa vänner: `ridgunc` och `stable` (Noll YAML-filer, jag lovar)","markdown":"# Kapitel 02: Dina två bästa vänner: `ridgunc` och `stable` (Noll YAML-filer, jag lovar)\n\nDet finns språk vars kompilator är underbar, men vars projektsystem verkar vara konstruerat av din värsta fiende: än är det en `Makefile` på 400 rader med osynliga tabulatorer, än en oändlig `pom.xml`, än en `webpack.config.js` som slutar fungera om du tittar för länge på den...\n\nI Ridgun gav vi oss själva ett mycket enkelt löfte redan från första dagen:\n\n> *\"Det ska bara finnas två körbara program i hela ekosystemet (`ridgunc` och `stable`), båda ska vara skrivna i Ridgun självt, och projektets konfigurationsfil (`build.rg`) ska vara helt vanlig Ridgun-kod. Ingen JSON, ingen YAML, ingen TOML och inga konstiga påhitt.\"*\n\nLåt oss se hur de används.\n\n---\n\n## 2.1. `ridgunc`: Prickskytten för enskilda filer\n\nNär du har en enskild `.rg`-fil framför dig och vill testa en snabb idé, analysera dess typer eller kompilera en körbar fil pratar du direkt med **`ridgunc`**.\n\nDen har bara 4 kommandon som du verkligen behöver komma ihåg:\n\n```bash\n# 1. \"Kompilerar det här eller har jag gjort bort mig med någon typ?\"\nridgunc check experiment.rg\n\n# 2. \"Kör det nu!\" (Kompilerar och kör i ett svep)\nridgunc run experiment.rg\n\n# 3. \"Gör en inbyggd ELF-binär färdig att ta med\"\nridgunc build experiment.rg -o mitt_program\n\n# 4. \"Ta fram mellanartefakten med bytekod (.rgc)\"\nridgunc compile experiment.rg -o experiment.rgc\n```\n\n### Den dolda superkraften i `ridgunc check`\nNär du kör `ridgunc check` säger den inte bara *\"0 fel\"*. Den avslöjar också vilken strategi den statiska analysatorn har valt för var och en av dina funktioner:\n- **`InlineSequential`**: *\"Den här funktionen är liten och rak; jag kör den direkt i linje utan att lägga på någon schemaläggningskostnad\"*.\n- **`LazyStealableTask`**: *\"Här finns rekursion eller en parallell graf `||`; jag förbereder den så att andra processorkärnor kan stjäla arbete om det behövs\"*.\n\n### Skalpellprecisionen i `ridgunc build` (Varför dina binärer inte väger 20 MB)\nNär du kör `ridgunc build` nöjer sig kompilatorn inte med att spotta ur sig all kod från de bibliotek du har importerat:\n1. Den börjar i din `main`-funktion och vandrar genom anropsgrafen för att se **vilka funktioner du faktiskt använder**. Om du har importerat ett enormt bibliotek med 80 funktioner men bara anropar 2, kastas de andra 78 bort innan de ens når assemblern (*Tree-Shaking*).\n2. Den letar upp alla svansrekursiva funktioner och omvandlar dem till inbyggda `loop`-snurror som förbrukar **0 byte stackminne**.\n3. Den kör slutlänkningen med global optimering (*fat LTO*) och rensar bort DWARF-felsökningsskräp för att ge dig en kompakt och knivskarp binär (~350 KB).\n\n---\n\n## 2.2. `stable`: När ditt projekt växer och du vill ha ordning\n\nEn enskild fil är toppen för ett skript, men så fort du har flera moduler, delade bibliotek och tester behöver du en dirigent. Det är **`stable`**.\n\nMappstrukturen i ett Ridgun-projekt rymmer inga mysterier:\n\n```text\nmitt-superverktyg/\n├── build.rg # Projektmanifestet (det är Ridgun-kod!)\n├── src/\n│ ├── main/\n│ │ └── ridgun/\n│ │ ├── lib/ # Dina återanvändbara moduler (`import verktyg`)\n│ │ └── app/\n│ │ └── main.rg # Startpunkt (`main => ()`)\n│ └── test/\n│ └── ridgun/ # Dina testsviter (`test *.rg`)\n│ └── test allt.rg\n└── target/ # Där de kompilerade binärerna dyker upp\n```\n\n---\n\n## 2.3. `build.rg`: En konfigurationsfil som aldrig ljuger för dig\n\nVarför vägrar vi att använda YAML eller TOML för att konfigurera ett Ridgun-projekt?\nDärför att i YAML råkar du skriva två mellanslag fel i indraget och märker det inte förrän driftsättningen kraschar. Eftersom **`build.rg` är en Ridgun-fil** har den däremot statiska typer, kontrolleras med `stable check` och justeras automatiskt med `stable format`:\n\n```ridgun\ntype ProjectInfo =\n name: String\n version: String\n edition: String\n\nproject => ProjectInfo\nproject = ProjectInfo \"mitt-superverktyg\" \"0.1.0\" \"2026\"\n\nsource dir => String\nsource dir = \"src/main/ridgun\"\n\ntest dir => String\ntest dir = \"src/test/ridgun\"\n\ntarget dir => String\ntarget dir = \"target\"\n\n-- Valfritt: aktivera strikt läge för signaturer och namn (inaktiverat som standard)\nstrict mode => Bool\nstrict mode = True\n```\n\nOm du stavar fel på ett fält varnar kompilatorn själv. Inga överraskningar.\n\n### Strikt läge (`--strict` / `strict mode = True`)\nSom standard är strikt läge **inaktiverat** i både `ridgunc` och nya projekt som skapas med `stable new` eller `stable init`, så att du kan bygga prototyper i full frihet. När du vill låsa den kanoniska stilen i ett projekt (som vi gör i Ridguns egen kompilator) kan du skicka `--strict` till `ridgunc` eller lägga till `strict mode = True` i din `build.rg`. Strikt läge kräver två elegansregler:\n1. **Namn på `fn ::` och `op ::` med naturliga mellanslag, utan `_`**: deklarationer måste använda mellanslag (`fn :: berakna skatt`, aldrig `fn :: berakna_skatt`).\n2. **Flertalsreturer åtskilda med mellanslag efter `=>`**: när en funktion eller operator returnerar flera värden skrivs dess utdatasignatur som `=> Int Int` eller `=> Tillstand Int` (aldrig `=> (Int, Int)` med parenteser eller kommatecken).\n\n---\n\n## 2.4. Din dagliga rutin med `stable` (De 4 fantastiska)\n\nNär du arbetar inne i ditt projekt kokar din vardag ner till fyra kommandon:\n\n### 1. `stable format` — Slutet på alla kodstilsdiskussioner i teamet\n```bash\nstable format\n```\nSätter din kollega tre mellanslag före `=>` medan du sätter ett? Det spelar ingen roll. Du kör `stable format` och på mindre än en sekund är **alla** `.rg`-filer i förrådet uppradade som en schweizisk tabell.\n\n### 2. `stable check` — Den omedelbara radarn\n```bash\nstable check\n```\nGår igenom alla moduler i `src/main/ridgun/`, verifierar typer, konstruktorer, aritet och tensordimensioner, och ger dig utslaget modul för modul.\n\n### 3. `stable test` — Sov gott om natten\n```bash\nstable test\n```\nLetar upp alla testsviter `src/test/ridgun/test *.rg`, kör dem och kontrollerar varje `assert equals` och `assert true`.\n\n```ridgun\n-- Exempel på src/test/ridgun/test matte.rg\nimport test\n\ndubbel Int => Int\ndubbel x = x * 2\n\nmain => ()\nmain =\n assert equals (dubbel 21) 42\n assert true ((dubbel 5) > 0)\n```\n\n### 4. `stable built` (och `stable clean`) — Ut i produktion\n```bash\nstable built\n```\nKompilerar alla inbyggda mål i `target/`. Och om du någon dag vill radera `target/` och börja om från rent bord: `stable clean`.\n\n---\n\n## 2.5. Hur importerar jag en fil från en annan? (`import`)\n\nInga helvetiska relativa sökvägar av typen `../../../lib/grejer.rg`. Om du har en fil `src/main/ridgun/lib/strangar.rg` skriver du helt enkelt längst upp i vilken annan fil som helst:\n\n```ridgun\nimport strangar\n```\n\nOch klart: alla funktioner och typer i `strangar.rg` är tillgängliga precis som om de låg i din egen fil. Men vad händer om modul `A` gör `import strangar`, modul `B` också gör `import strangar` och din `main.rg` importerar både `A` och `B`? Ta det lugnt: Ridguns laddare kommer ihåg vilka kanoniska filer den redan har läst och **inkluderar den bara en gång**.\n\nNu när du har full koll på verktygslådan går vi vidare till **Kapitel 03** för att bemästra funktioner, typer, block och knep med textsträngar.\n"}, {"num":"03","slug":"03-funktioner-typer-och-justering","file":"03-funktioner-typer-och-justering.md","title":"Kapitel 03: Funktioner, typsignaturer och konsten att skriva kod som en tabell","short_title":"Funktioner, typsignaturer och konsten att skriva kod som en tabell","markdown":"# Kapitel 03: Funktioner, typsignaturer och konsten att skriva kod som en tabell\n\nDet finns en fråga som varje programmerare ställer sig första gången de ser funktionell kod:\n\n> *\"Om det inte finns några klasser här, inga objekt och inga variabler som ändrar värde... var stoppar jag då in min logik?\"*\n\nI **funktioner**. Men inte i sådana där funktioner på 200 rader fulla av booleska flaggor som vi alla har lidit av någon gång, utan i små, raka funktioner som är så lätta att läsa att de ser ut som en tabell på en whiteboard.\n\nLåt oss se hur de byggs upp.\n\n---\n\n## 3.1. Två sätt att presentera en funktion (Du väljer kostymen)\n\nI Ridgun börjar varje funktion med sin **typsignatur** (vad som går in och vad som kommer ut efter `=>`) och därunder följer dess **implementeringsklausuler** (med `=`).\n\nDu kan skriva rubrikraden på två sätt:\n\n### Alternativ A: Rakt på sak (utan prefix)\n```ridgun\ntillampa rabatt Int Int => Int\ntillampa rabatt pris procent = pris - (pris * procent / 100)\n```\n\n### Alternativ B: Med uttrycklig etikett (`fn ::`)\n```ridgun\nfn :: tillampa rabatt Int Int => Int\n tillampa rabatt pris procent = pris - (pris * procent / 100)\n```\n\n*\"Hallå där, varför finns båda två?\"*\nDärför att smaken är som baken:\n- Vissa föredrar att funktioner börjar ända ute i vänstermarginalen utan att behöva skriva `fn ::` varje gång (pilen `=>` ropar trots allt redan ut över hela rummet att den raden är en typsignatur).\n- Andra föredrar att ha en vänsterkolumn vigd åt etiketterna (`fn ::`, `op ::`, `type`, `import`) för att snabbt kunna överblicka filen visuellt.\n\nKompilatorn och `stable format` förstår båda två till fullo. Dessutom kan orden `fn` och `op` användas fritt som en del av namnet på vilken funktion eller operator som helst (till exempel `fn :: op`, `op :: fn` eller `op :: op`), och om en funktion returnerar flera värden skrivs returtyperna i kanoniskt/strikt läge åtskilda med mellanslag efter `=>` (`dividera med rest Int Int => Int Int`).\n\n---\n\n## 3.2. Kolumnernas magi: varför dina ögon får vila\n\nTitta på den här funktionen som beräknar fraktkostnaden beroende på land och om leveransen är brådskande:\n\n```ridgun\nfraktkostnad String Bool Int => Int\nfraktkostnad \"SE\" False _ = 50\nfraktkostnad \"SE\" True _ = 120\nfraktkostnad _ False vikt = 100 + (vikt * 20)\nfraktkostnad _ True vikt = 250 + (vikt * 40)\n```\n\nGör testet: täck för den högra halvan av skärmen och titta bara på de tre indatakolumnerna:\n- Första kolumnen (`String`): `\"SE\"`, `\"SE\"`, `_`, `_`.\n- Andra kolumnen (`Bool`): `False`, `True`, `False`, `True`.\n- Tredje kolumnen (`Int`): `_`, `_`, `vikt`, `vikt`.\n\nSer du någon logisk lucka? Ingen alls: alla 4 möjliga kombinationer ligger mitt framför näsan på dig, vertikalt uppradade under `String`, `Bool` och `Int`. I ett traditionellt `if / else`-block skulle du behöva läsa 18 rader för att vara säker på att du inte har glömt något enskilt fall.\n\n---\n\n## 3.3. Grundtyperna och en present så att du slipper räkna nollor (`_KB`, `_MB`, `_GB`)\n\nDe skalära typerna i Ridgun är raka och utan överraskningar:\n\n| Typ | Vad det egentligen är | Exempel |\n|---|---|---|\n| `Int` | 64-bitars heltal med tecken (`i64`) | `0`, `42`, `-100`, `0xFF00`, `1_000_000` |\n| `U64` | 64-bitars heltal utan tecken (`u64`) med inbyggd modulär och bitvis aritmetik | `u64 0`, `u64 0x6a09e667f3bcc908`, `a ^ b`, `a << u64 13` |\n| `Float` / `Real` | Decimaltal med dubbel precision (`f64`) | `3.14159`, `0.001`, `-2.5` |\n| `String` | Oföränderlig textsträng | `\"Hej\"`, `'ra\\sokvag'` |\n| `Char` | Teckenkod | Returneras av `str char at` |\n| `Bool` | Klassisk boolesk typ | `True`, `False` |\n| `()` | Tom (*Unit*, när du bara skriver ut eller gör I/O) | `()` |\n\n### Trött på att skriva `65536` eller `1048576` och hålla tummarna för att du inte har tappat en siffra?\nI Ridgun godtar numeriska literaler direkt suffixen **`_KB`**, **`_MB`** och **`_GB`**, utöver understreck `_` för att skilja siffergrupper åt:\n\n```ridgun\nbuffertstorlek => Int\nbuffertstorlek = 64_KB -- Kompilatorn översätter det till 65536\n\nfilgrans => Int\nfilgrans = 16_MB -- Kompilatorn översätter det till 16777216\n\noktettmask => Int\noktettmask = 0xFF_00 -- Rent och läsbart hexadecimalt tal\n```\n\n---\n\n## 3.4. Dubbla citattecken (`\"...\"`) kontra enkla citattecken (`'...'`)\n\nI många språk gör enkla och dubbla citattecken exakt samma sak (ett slöseri). I Ridgun har vart och ett av dem ett glasklart uppdrag:\n\n### 1. Dubbla citattecken (`\"...\"`): Smarta och interpolerade\nDe tolkar kontrollsekvenser (`\\n`, `\\t`, `\\\"`, `\\\\`) och **evaluerar varje variabel eller uttryck som du sätter inom måsvingar `{...}`**:\n\n```ridgun\nordersammanfattning String Int Int => String\nordersammanfattning vara antal pris =\n \"Du har beställt {antal}x {vara}. Totalt att betala: {antal * pris} kronor.\"\n```\n\n*(Tips: om du behöver skriva en bokstavlig måsvinge inuti dubbla citattecken — till exempel när du genererar ett skalskript `\"$\\{VAR:-default\\}\"` eller JSON — kan du föregå den med omvänt snedstreck `\\{` och `\\}` eller dubblera den `{{` och `}}`).*\n\n### 2. Enkla citattecken (`'...'`): Råa och bokstavliga (*Raw Strings*)\nDet du skriver inom enkla citattecken kommer ut **exakt som det står**, utan att röra vare sig omvända snedstreck `\\` eller måsvingar `{}`. Perfekt när du genererar kod i ett annat språk, skriver skalkommandon eller arbetar med sökvägar fulla av snedstreck:\n\n```ridgun\nsed kommando => String\nsed kommando = 's/\\([0-9]+\\)/[\\1]/g'\n```\n\n### Din verktygslåda för strängar (`String`)\nAtt slå ihop strängar är så enkelt som att addera dem med `+`: `\"Hej, \" + namn`. Och när du behöver utföra finlir på en text har du dessa inbyggda funktioner redo utan att behöva importera något:\n\n- `str len s` $\\rightarrow$ längden på `s`.\n- `str char at s i` $\\rightarrow$ numerisk kod (`Int`) för tecknet på position `i` (`-1` om du hamnar utanför).\n- `str slice s start slut` $\\rightarrow$ klipper ut från `start` till `slut` (exklusive `slut`).\n- `char from code c` $\\rightarrow$ omvandlar en numerisk kod (`Int`, t.ex. `10` för `\\n` eller `34` för `\"`) till en `String` med 1 tecken.\n- `str contains s nal` och `str starts with s prefix` $\\rightarrow$ returnerar `True` eller `False`.\n- `int to str n` och `str to int s` $\\rightarrow$ omvandlar från tal till text och tvärtom (`str to int` förstår till och med `\"0xFF\"`!).\n\n---\n\n## 3.5. Flerradiga block, den universella regeln för `=` och `mut`-variabler\n\nNär en funktion inte får plats på en enda rad gör du en radbrytning efter `=` och drar in blocket.\n\nTitta på hur ett block läses steg för steg:\n\n```ridgun\nberakna faktura Int Int => Int\nberakna faktura bas moms_pct =\n skatt = bas * moms_pct / 100\n expeditionsavgift = 50\n echo \"Specifikation -> Bas:\" bas \"Skatt:\" skatt\n bas + skatt + expeditionsavgift\n```\n\nFyra gyllene regler som gör blocken i Ridgun rena och enhetliga:\n1. **Oföränderligt (*immutable*) som standard utan `let` eller `const`**: du skriver `skatt = ...` och har direkt din lokala oföränderliga konstant. Om du av misstag försöker skriva över `skatt = 99` längre ner i samma block bromsar kompilatorn dig tvärt.\n2. **Uttryckliga föränderliga variabler med `mut`**: när du verkligen vill uppdatera en lokal ackumulator steg för steg inuti en funktion deklarerar du den med **`mut`** och tilldelar den sedan fritt nya värden med `=`:\n ```ridgun\n tillampa tillagg Int => Int\n tillampa tillagg pris =\n mut total = pris\n total = total + 10\n total = total * 2\n total\n ```\n *(Och om `total` håller en lista eller struktur i minnet lägger Ridguns **`RMM2`**-policy till `+1` på det nya värdet innan den drar av `-1` från det gamla, och frigör det omedelbart om ingen annan använder det).*\n3. **Den universella regeln för `=`**: efter **vilket `=` som helst** (i en funktion, i en operator, i en lokal variabel `x =` eller i en villkorsgren) kan du alltid placera vilken som helst av Ridguns tre blockformer:\n - **`(ingenting)`**: indragna sekventiella rader (som ovan).\n - **`|`**: ett träd av villkorsvakter.\n - **`||`**: en graf av parallella beräkningar med `->`.\n4. **Det sista uttrycket är alltid resultatet**: `bas + skatt + expeditionsavgift` är vad `berakna faktura` returnerar. Utan `return`.\n\nI **Kapitel 04** ska vi se hur man fattar komplexa beslut — inklusive beslutsträd i flera nivåer med `|.` — utan att någonsin skriva ett `if/else` eller en `while`-loop: välkommen till världen av **booleska vakter** och **svansrekursion utan extra kostnad**.\n"}, {"num":"04","slug":"04-monstermatchning-och-vakter","file":"04-monstermatchning-och-vakter.md","title":"Kapitel 04: Adjö till `if/else`, adjö till `while` (Mönstermatchning, vakter och TCO)","short_title":"Adjö till `if/else`, adjö till `while` (Mönstermatchning, vakter och TCO)","markdown":"# Kapitel 04: Adjö till `if/else`, adjö till `while` (Mönstermatchning, vakter och TCO)\n\nNär du berättar för någon att det i Ridgun **varken finns nyckelorden `if`, `else`, `switch`, `for` eller `while`**, brukar de titta på dig som om du just sagt att du tänker bygga ett hus utan hammare och spik:\n\n> *\"Finns det inget `if` och inget `while`? Hur i hela friden fattar jag då ett beslut eller går igenom en miljon datapunkter?\"*\n\nDet visar sig att `if/else` och `while` är ganska grovhuggna verktyg som vi har ärvt från hur hoppinstruktioner (`GOTO`) fungerade på 50-talet. I Ridgun ersätter vi dem med tre pusselbitar som passar som handen i handsken:\n1. **Mönstermatchning (*Pattern Matching*)** (när du väljer väg utifrån datans **form eller exakta värde**).\n2. **Booleska vakter `|`** (när du väljer väg utifrån ett **villkor eller intervall**).\n3. **Svansrekursion med TCO** (som kompilatorn under huven omvandlar till en blixtsnabb inbyggd `loop`-snurra).\n\nLåt oss se dem i aktion.\n\n---\n\n## 4.1. Mönstermatchning: När argumentet redan ger dig svaret\n\nI föregående kapitel fick vi redan en förhandstitt. I stället för att ta emot en generisk variabel `x` och öppna fem `if (x == ...)` inuti funktionen lägger du i Ridgun fallen direkt vid funktionens ingång:\n\n```ridgun\nhttp kod Int => String\nhttp kod 200 = \"OK: Allt gick som på räls\"\nhttp kod 301 = \"Permanent flyttad\"\nhttp kod 404 = \"Hittades inte (har du tittat under soffan?)\"\nhttp kod 500 = \"Det brinner i servern\"\nhttp kod n = \"Okänd kod: {n}\"\n```\n\nRidgun provar raderna **uppifrån och ner**:\n- Om `404` kommer in hoppar den direkt till tredje raden.\n- Om `418` kommer in stämmer ingen av de fyra första raderna, så den faller ner till den sista (`n`), som fångar upp vilket heltal som helst och ger det namnet `n` så att du kan skriva ut det.\n- Och om du i det sista fallet inte ens bryr dig om vilket tal det var? Då sätter du ett understreck `_` (*jokertecken*) och glömmer det: `http kod _ = \"Annan kod\"`.\n\n---\n\n## 4.2. Booleska vakter (`|`): Din skalpell för intervall, villkorsstyrda variabler och beslutsträd\n\n*\"Okej, mönstermatchning är häftigt när jag letar efter `200` eller `404`. Men vad gör jag om jag vill kontrollera om `betyg >= 5` eller om `alder > 18 and alder < 65`? Jag tänker ju inte skriva 47 rader med alla tal från 18 till 65!\"*\n\nNaturligtvis inte! Det är precis vad **vakter (`|`)** är till för.\n\nNär resultatet beror på en olikhet eller en logisk kombination öppnar du efter funktionens `=` (eller efter vilken lokal variabel som helst) en trappa av lodräta streck `|`:\n\n```ridgun\nbedom Int => String\nbedom betyg =\n | betyg < 0 = \"Omöjligt betyg (minuspoäng?)\"\n | betyg < 5 = \"Underkänt\"\n | betyg < 7 = \"Godkänt\"\n | betyg < 9 = \"Väl godkänt\"\n | betyg <= 10 = \"Mycket väl godkänt\"\n | otherwise = \"Du har sprängt skalan\"\n```\n\nTitta noga:\n- Likhetstecknet `=` i rubrikraden (`bedom betyg =`) justeras rakt under `=>` precis som i vilken annan funktion som helst.\n- Därunder läses det uppifrån och ner precis som en pristabell: varje rad `| villkor = resultat` kontrolleras i tur och ordning. Så fort en ger `True` returneras det resultatet och allt är klart.\n- På slutet sätter du **`| otherwise = ...`**, som bokstavligen betyder *\"i alla andra fall\"* (ditt skyddsnät så att ingen väg någonsin blir utan returvärde).\n\n### Boolesk logik med tydliga gemener (`and`, `or`, `xor`, `not`)\nHar du lagt märke till att många språk använder `|` för bitar, `||` för booleska värden, `!` för negation... och när du läser ett komplext villkor ser det ut som om en katt har promenerat över tangentbordet (`if (!a && (b || c))`)?\n\nI Ridgun, där `|` redan är den heliga symbolen för vakter och algebraiska datatyper och `||` är parallellitetsoperatorn, **skrivs de booleska operatorerna med tydliga ord i gemener**:\n\n- **`and`**: båda sakerna är uppfyllda med kortslutningsutvärdering (`alder >= 18 and har_korkort`).\n- **`or`**: minst en är uppfylld med kortslutningsutvärdering (`dag == \"lordag\" or dag == \"sondag\"`).\n- **`xor`**: antingen det ena eller det andra är uppfyllt, men inte båda samtidigt.\n- **`not`**: vänder på det booleska värdet (`not (ar tom text)`).\n- **`<`, `>`, `<=`, `>=`**: jämför både tal (`Int`, `Float`) och **`String`-strängar i lexikografisk UTF-8-ordning** (`\"alfa\" < \"beta\"`).\n\nTitta så rent det klassiska problemet med skottår blir:\n\n```ridgun\nar skottar Int => Bool\nar skottar a =\n | (a % 400) == 0 = True\n | (a % 4) == 0 and (a % 100) != 0 = True\n | otherwise = False\n```\n\nNoll kryptiska symboler. Någon som inte kan Ridgun kan läsa det och förstå det vid första anblicken.\n\n### Villkorsstyrda lokala variabler (`x =` + `|`)\nEftersom varje `=` i Ridgun följer samma regel **kan du också använda `|` för att tilldela en lokal variabel** utan att behöva skapa en separat hjälpfunktion:\n\n```ridgun\nbiljettpris Int Bool => Int\nbiljettpris bas ar_storfamilj =\n rabatt =\n | ar_storfamilj = 20\n | bas > 100 = 10\n | otherwise = 0\n bas - (bas * rabatt / 100)\n```\n\n### Nästlade beslutsträd och den kompakta avgränsaren `|.`\n*\"Men tänk om jag inuti en gren `| villkor =` eller `| otherwise =` vill öppna ett nytt underträd av vakter `|` på 3 eller 4 nivåers djup och sedan återvända till en högre nivå?\"*\n\nDu kan nästla `|` inuti `|` hur många nivåer du vill. Och när ett nästlat `|`-block avslutas men fler grenar på en föräldranivå (eller fler satser i blocket) följer nedanför, sätter du **`|.`** i slutet av dess sista rad (`| otherwise = varde |.`) för att utan minsta tvetydighet markera att underträdet stängs och att du återvänder till föregående nivå:\n\n```ridgun\ndirigera anrop Int Int Bool Bool Int Int => Int\ndirigera anrop metod roll signerad ar_admin storlek_kb begransad =\n | metod == 0 =\n | storlek_kb == 0 = 204\n | otherwise = 200 |.\n | metod == 1 =\n | not signerad = 401\n | otherwise =\n -- Nivå 2: signerat POST-anrop\n | begransad > 0 =\n -- Nivå 3: kontroll av rate-limit\n | ar_admin =\n -- Nivå 4: undantag för administratörer\n | storlek_kb > 10000 = 413\n | otherwise = 202 |.\n | otherwise = 429 |.\n | storlek_kb > 1000 =\n -- Nivå 3: vi har återvänt från Nivå 4 tack vare `|.`\n | roll >= 2 and ar_admin = 201\n | otherwise = 413 |.\n | otherwise = 201 |.\n | otherwise = 405\n```\n\nLägg märke till hur rent det är:\n- I ett enkelt träd med 1 nivå (eller i slutet av hela funktionen) **behöver du aldrig sätta ut `|.`** (det vore bara onödigt brus).\n- Du skriver bara `|.` när du stänger en nästlad gren och en gren på en högre nivå fortsätter nedanför.\n\n### Flerradiga block inuti en vakt (`| villkor =` + indraget block)\nPrecis som du efter `=` i en vanlig funktion kan öppna ett indraget block på flera rader, **kan du efter `=` i vilken vakt som helst (`| villkor =` eller `| otherwise =`) också göra en radbrytning och öppna ett sekventiellt block**:\n\n```ridgun\njustera fonster Int Int => Int\njustera fonster idx grans =\n | idx >= grans =\n tak = grans - 1\n skalad = tak * 2\n skalad + 10\n | otherwise =\n nasta = idx + 1\n nasta * 2\n```\n\nVarje gren i vakten har sitt eget rena lokala block, och dess sista rad är värdet som den grenen returnerar.\n\n---\n\n## 4.3. \"Utan `while`? Kommer inte stacken att sprängas om jag går igenom en stor fil?\"\n\nLåt oss prata om elefanten i rummet.\n\nOm du kommer från Python, Java eller JavaScript har du fått lära dig sedan barnsben att *\"rekursion är elegant på svarta tavlan på universitetet, men i verkligheten svämmar stacken över (`StackOverflowError`) efter 1 000 varv; använd en `while`-loop\"*.\n\nDet stämmer i språk som **inte** optimerar svansanrop. Men i ett funktionellt systemspråk som Ridgun **ÄR svansrekursion en `while`-loop förklädd till en ren funktion**.\n\n### Vad är skillnaden mellan vanlig rekursion och svansrekursion?\nTitta på dessa två funktioner som räknar baklänges från `n` till `0` och summerar talen:\n\n```ridgun\n-- Version A: VANLIG rekursion (lämnar kvar väntande arbete till tillbakavägen)\nsummera langsamt Int => Int\nsummera langsamt 0 = 0\nsummera langsamt n = n + (summera langsamt (n - 1))\n\n-- Version B: SVANSREKURSION (håller räkningen uppdaterad i `ackumulerat`)\nsummera snabbt loop Int Int => Int\nsummera snabbt loop 0 ackumulerat = ackumulerat\nsummera snabbt loop n ackumulerat = summera snabbt loop (n - 1) (ackumulerat + n)\n```\n\n- I **Version A** måste funktionen vänta på att `summera langsamt (n - 1)` blir klar innan den kan beräkna `n + ...`. Det tvingar datorn att spara `n` på stacken i varje steg.\n- I **Version B** är anropet till `summera snabbt loop` **det absolut sista som händer på raden**. Inget väntande arbete finns kvar efter det. Du skickar redan med den uppdaterade summan i `ackumulerat + n`.\n\n### Trolltricket i `ridgunc` (TCO: *Tail-Call Optimization*)\nNär `ridgunc` kompilerar `summera snabbt loop` ser den att funktionen anropar sig själv i slutet av klausulen och tänker:\n\n> *\"Varför skulle jag skapa en ny stackram när den nuvarande inte längre behövs till någonting? Jag skriver över `n` med `n - 1`, skriver över `ackumulerat` med `ackumulerat + n` och hoppar tillbaka till början med en inbyggd `loop { ... continue; }`.\"*\n\nResultat:\n1. Du kan anropa `summera snabbt loop 100_000_000 0` (hundra miljoner varv) och **det kommer att förbruka exakt 0 extra byte på stacken**.\n2. Det går lika snabbt som en handskriven `while`-loop i Rust eller C, men utan att du har behövt deklarera en enda muterbar variabel i din Ridgun-kod.\n\n---\n\n## 4.4. Mästarmönstret som du kommer att använda i varje Ridgun-program\n\nVarje gång du i ett annat språk skulle tänka *\"jag gör en `while`-loop med ett index `i` och en ackumulator\"*, skriver du i Ridgun ett funktionspar som detta (den rena huvudfunktionen och dess svansrekursiva `_loop`-hjälpare):\n\n```ridgun\nsok tecken loop String Int Int Int => Int\nsok tecken loop text pos slut sokt =\n | pos >= slut = -1\n | (str char at text pos) == sokt = pos\n | otherwise = sok tecken loop text (pos + 1) slut sokt\n\nsok tecken String Int => Int\nsok tecken text sokt = sok tecken loop text 0 (str len text) sokt\n```\n\nTitta på de tre vakterna i `sok tecken loop`:\n1. Har jag nått slutet (`pos >= slut`)? Returnera `-1` (slut på loopen).\n2. Hittade jag tecknet på `pos`? Returnera `pos` (slut på loopen).\n3. Är det inte det här tecknet? Gå vidare till nästa (`pos + 1`) med ett svansanrop (som kompilatorn omvandlar till `continue;`).\n\nRent, omöjligt att få buggar från överskrivna globala variabler och snabbt som blixten.\n\nI **Kapitel 05** ska vi ta oss an datasamlingar: **listor, tupler, funktioner som tar emot oändligt många argument (`...`) och sekvensmasker i J/APL-stil**.\n"}, {"num":"05","slug":"05-listor-tupler-och-sekvenser","file":"05-listor-tupler-och-sekvenser.md","title":"Kapitel 05: Listor, tupler och ninjatricket med sekvenser","short_title":"Listor, tupler och ninjatricket med sekvenser","markdown":"# Kapitel 05: Listor, tupler och ninjatricket med sekvenser\n\nEtt program som bara flyttar ett tal eller en text i taget gör inte mycket nytta. I verkliga livet hanterar du fillistor, rader från en databas, nätverkspaket eller koordinater.\n\nFör det ger Ridgun dig tre olika behållare, var och en utformad för en mycket specifik uppgift:\n1. **Listor (`[T]`)**: *\"Jag har många element av samma typ (eller inga alls) och vill gå igenom dem\"*.\n2. **Tupler (`(A, B)`)**: *\"Jag vill returnera ett par eller en trio av olika saker tillsammans utan att skapa en ny typ\"*.\n3. **Sekvenser och masker (`s(_ + _)`, `(+ _ _ +)`)**: *\"Jag vill filtrera eller stuva om argument i farten som om jag hade ett matematiskt durkslag\"*.\n\nVi tar dem en i taget.\n\n---\n\n## 5.1. Listor (`[T]`): Vårt dagliga bröd\n\nOm du i Ridgun sätter hakparenteser runt en typ har du en lista av den typen:\n- `[Int]` är en lista med heltal: `[10, 20, 30]`.\n- `[String]` är en lista med texter: `[\"apple\", \"paron\"]`.\n- `[]` är den tomma listan (jokertecknet som passar till varje `[T]`).\n\n> *\"Hallå, kan jag stoppa in ett tal och en text tillsammans i samma lista, typ `[1, \"tva\"]`?\"*\n> Som den står, **nej** (och tacka kompilatorn för att den hindrar dig, för på så sätt kommer en summering i produktion aldrig att explodera när den stöter på en oväntad text). I Kapitel 06 ska vi se hur man löser fallet `[1, \"tva\"]` med fullständig elegans med hjälp av en algebraisk datatyp (precis som i Haskell).\n\n### Hur man delar upp en lista utan index `i`, `j`, `k`: `[]` och `(x:xs)`\nI imperativa språk innebär det oftast `for (int i = 0; i < lista.size(); i++)` att gå igenom en lista, med den klassiska risken att räkna ett steg fel (*off-by-one*).\n\nI Ridgun räknar du inte index; **du plockar isär listan från huvudet**:\n- `[]`: matchar om listan är tom.\n- `(x:xs)`: matchar om listan har minst ett element. Den lägger det första elementet i `x` (**huvudet**) och resten av listan i `xs` (**svansen**).\n\nTitta så smidigt det är att summera en lista eller räkna hur många element den har:\n\n```ridgun\nsummera lista [Int] => Int\nsummera lista [] = 0\nsummera lista (x:xs) = x + (summera lista xs)\n\nrakna element [A] => Int\nrakna element [] = 0\nrakna element (_:xs) = 1 + (rakna element xs)\n```\n\nOch en teknisk detalj som kommer att göra dig glad: i Ridgun **kopierar inte `(x:xs)` resten av listan i minnet** när svansen `xs` plockas ut. Internt är det en vy över samma vektor som bara flyttar fram startpekaren med `1` (omedelbart i $O(1)$).\n\n### Du kan plocka fram flera element i ett svep\nMönstret `:` är otroligt användbart när du tolkar kommandon eller protokoll:\n\n```ridgun\ntolka kommando [String] => String\ntolka kommando [] = \"Du har inte skrivit något\"\ntolka kommando (\"hjalp\":_) = \"Visar hjälpen...\"\ntolka kommando (\"kopiera\":kalla:mal:[]) = \"Kopierar från {kalla} till {mal}\"\ntolka kommando (cmd:_) = \"Okänt kommando: {cmd}\"\n```\n\nTitta på tredje raden: `(\"kopiera\":kalla:mal:[])` kontrollerar i ett enda slag att listan har **exakt 3 element**, att det första är `\"kopiera\"`, och serverar det andra och tredje på silverfat i `kalla` och `mal`. Försök skriva det i C eller Java så får du se hur många rader med `args.length == 3 && args[0].equals(\"kopiera\")` det blir.\n\n### Slå ihop listor med dubbla kolon (`::`)\nNär du befinner dig till höger om `=` (i ett uttryck) och vill foga ihop två listor använder du **`::`**:\n\n```ridgun\nfoga listor [Int] [Int] => [Int]\nfoga listor a b = a :: b\n\nlagg till sist [Int] Int => [Int]\nlagg till sist xs x = xs :: [x]\n```\n\n*(Snabb minnesregel: ett enkelt `:` i mönster plockar isär listan; dubbla `::` i uttryck fogar ihop två listor).*\n\nOch om du verkligen vill hämta element nummer 5 direkt utan att stega igenom något? Använd hakparenteser direkt efter namnet: `min_lista[5]`.\n\n---\n\n## 5.2. Variadiska funktioner (`T...`): \"Skicka in hur många du vill!\"\n\nIbland vill du att den som anropar din funktion bekvämt ska kunna skriva `max av 4 19 2 88 7`, utan att tvingas linda in talen i hakparenteser `[4, 19, 2, 88, 7]`.\n\nSätt tre punkter **`...`** efter den sista typen i din signatur, så får du inuti funktionen automatiskt in argumenten paketerade som en lista:\n\n```ridgun\nsummera flera Int... => Int\nsummera flera tal = summera lista tal\n\nmain => ()\nmain =\n echo (summera flera 10 20 30) -- Skriver ut 60\n echo (summera flera 1 2 3 4 5 6 7) -- Skriver ut 28\n```\n\n---\n\n## 5.3. Tupler: När en funktion vill returnera mer än en sak\n\nI många språk är det en plåga att returnera två saker från en funktion: antingen skapar du en fånig hjälpklass `ResultatMedPosition`, eller så skickar du med utdatapekare via referens.\n\nI Ridgun returnerar du en **tupel** `(A, B)`:\n\n```ridgun\nkvot och rest Int Int => (Int, Int)\nkvot och rest a b = (a / b, a % b)\n```\n\nDu kan till och med spara in parenteserna på signaturraden om du tycker att det ser renare ut:\n`kvot och rest Int Int => Int Int`.\n\n### Hur man öppnar en tupel\nPrecis som du skapar den med `(a, b)` öppnar du den i argumenten till vilken funktion som helst med `(kvot, rest)`:\n\n```ridgun\nforklara division (Int, Int) => String\nforklara division (kvot, rest) = \"Det går {kvot} gånger och blir {rest} över\"\n```\n\n### Stjärndetaljen: Automatisk uppackning mellan funktioner\nAnta att du har `kvot och rest` (som returnerar en tupel med 2 heltal) och en annan funktion `summera par Int Int => Int` (som förväntar sig 2 fristående heltal). I Ridgun behöver du inte packa upp tupeln för hand i en mellanliggande variabel; du kan koppla in den ena funktionen rakt i den andra:\n\n```ridgun\nsummera par Int Int => Int\nsummera par x y = x + y\n\nmain => ()\nmain =\n -- kvot och rest 17 5 returnerar (3, 2), och summera par tar emot 3 och 2 direkt:\n echo (summera par (kvot och rest 17 5)) -- Skriver ut 5\n```\n\n---\n\n## 5.4. Ninjatricket: Sekvenser och positionsmasker (`s(_ + _)`, `(+ _ _ +)`)\n\nHär kommer en av Ridguns mest originella juveler, ärvd rakt från vektorspråk som J och APL.\n\nFöreställ dig att du tar emot en rad argument med sekvensmönstret **`(s)`** och bara vill behålla några och kasta andra utan att deklarera fem variabler med påhittade namn (`_a`, `b`, `_c`, `d`...).\n\nDå lägger du på en **tupelmask med `+` (behåll) och `_` (kasta)** på `s`:\n\n- **`s(_ + _)`**: av 3 element, kasta det första (`_`), behåll det andra (`+`) och kasta det tredje (`_`).\n- **`s(+ _ +)`**: behåll det första och det tredje; returnera sekvensen med dessa två.\n- **`s(_ _ +...)`**: kasta de två första (`_ _`) och tillämpa `+...` **på alla efterföljande element**, oavsett hur många de är.\n\nSe hur det fungerar i praktiken:\n\n```ridgun\nden i mitten Int Int Int => Int\nden i mitten (s) = s(_ + _)\n\nkasta tva forsta Int... => [Int]\nkasta tva forsta (s) = s(_ _ +...)\n\nmain => ()\nmain =\n echo (den i mitten 100 42 999) -- Skriver ut 42\n echo (kasta tva forsta 1 2 10 20 30) -- Skriver ut [10, 20, 30]\n```\n\nOch det bästa av allt: du kan skjuta in en positionsmask **`(+ _ _ +)`** **rakt in i en idiomatisk `->`-pipeline**! Om en funktion returnerar en tupel med flera värden och nästa funktion bara behöver två av dem, filtrerar du tupeln i farten och Ridgun packar upp de överlevande elementen direkt som separata argument till nästa steg:\n\n```ridgun\n-- tolka paket returnerar 4 värden: (Int, Int, [String String], String)\n-- (+ _ _ +) behåller det 1:a (code) och det 4:e (msg), och skickar dem till kombinera kod:\ntolka paket \"v0.9.9\" -> (+ _ _ +) -> kombinera kod -> sammanfattning\n```\n\nOch om du dessutom använder kommaoperatorn `,` utanför parenteser (`lista1 , lista2`), plattar Ridgun ut båda samlingarna till en enda sammanhängande sekvens.\n\nI **Kapitel 06** ska vi ta steget som förvandlar en funktionell programmerare till en förstklassig arkitekt: **att skapa dina egna algebraiska datatyper (ADT), skriva polymorfa funktioner med `A`..`Z` och skräddarsy dina egna operatorer**.\n"}, {"num":"06","slug":"06-algebraiska-datatyper-och-polymorfism","file":"06-algebraiska-datatyper-och-polymorfism.md","title":"Kapitel 06: Algebraiska datatyper (ADT), polymorfism och varför vi inte vill ha `null` eller `Any` här","short_title":"Algebraiska datatyper (ADT), polymorfism och varför vi inte vill ha `null` eller `Any` här","markdown":"# Kapitel 06: Algebraiska datatyper (ADT), polymorfism och varför vi inte vill ha `null` eller `Any` här\n\nÅr 1965 uppfann Tony Hoare null-referensen (`null` / `nil`). Fyrtio år senare bad han offentligt om ursäkt och kallade den *\"mitt miljarddollarsmisstag\"*.\n\nVarför? Därför att i språk med `null` lovar en funktion i sin signatur att den ska ge dig en `Anvandare`... och när du minst anar det returnerar den `null` och sänker servern klockan tre på natten.\n\nOch precis samma sak händer med objektarv och typen `Any` (eller `Object`): du stoppar in ett tal och en text i en lista `[1, \"tva\"]`, språket rycker på axlarna och säger *\"okej, då är det här en `List[Any]` nu, lycka till med att gissa vad som ligger i den när du går igenom den\"*.\n\nI Ridgun rycker vi upp de två problemen med rötterna med hjälp av **algebraiska datatyper (ADT)** och **parametrisk polymorfism**. Det låter som namnet på en tung universitetskurs, men om fem minuter kommer du att se att det är världens mest naturliga sätt att modellera data.\n\n---\n\n## 6.1. Produkttyper (Poster): Dina vanliga `struct`, men med superkrafter\n\nNär du vill gruppera flera uppgifter som hör till samma enhet (till exempel en server med dess namn, IP-adress och port) definierar du en **`type`** med dess fält:\n\n```ridgun\ntype Server = host: String, port: Int, tls_aktiv: Bool\n```\n\nBara genom att skriva den enda raden ger Ridgun dig **fyra saker** helt automatiskt:\n\n### 1. Konstruktorn `Server`\n```ridgun\nmin nod => Server\nmin nod = Server \"api.exempel.se\" 443 True\n```\n\n### 2. En ren *getter*-funktion för varje fält (`host`, `port`, `tls_aktiv`)\nDu behöver inte skriva `s.getHost()` eller något liknande; varje fältnamn är direkt en funktion som plockar ut det värdet:\n\n```ridgun\nanslutnings url Server => String\nanslutnings url srv = \"Anslut till \" + (host srv) + \" på port {port srv}\"\n```\n\n### 3. Funktionell uppdatering av poster (`with falt: varde`)\nFöreställ dig en konfigurationspost med 12 eller 15 fält (som flaggorna till ett `ls`-kommando eller en webbserver) där du bara vill ändra ett eller två fält utan att röra resten. I stället för att bygga om posten genom att skicka in alla 15 fält för hand använder du **`with`** och kolon **`:`** (exakt som i `type`-definitionen):\n\n```ridgun\naktivera dev lage Server => Server\naktivera dev lage srv = srv with port: 8080, tls_aktiv: False\n```\n\nDet bästa av två världar:\n- I din kod är det **100 % oföränderligt och säkert** (kompilatorn kontrollerar att `port` och `tls_aktiv` finns i `Server` och har rätt typ).\n- Under huven återanvänder den inbyggda körbara filen minnet *in-place* (`Arc::try_unwrap`) utan att kopiera övriga fält om `srv` inte delas med någon annan.\n\n### 4. Fullständig mönstermatchning om du vill öppna posten direkt\n```ridgun\nar saker port Server => Bool\nar saker port (Server _ 443 True) = True\nar saker port _ = False\n```\n\n---\n\n## 6.2. Summatyper (Varianter med `|`): Hur man pensionerar `null`, undantag och arv\n\nNu kommer det riktigt fina.\nEn vanlig post har `host` **OCH** `port` **OCH** `tls_aktiv`.\nMen i verkliga livet behöver du ofta säga: *\"Ett betalningssätt är **ANTINGEN** ett kort med dess nummer, **ELLER** en överföring med dess IBAN, **ELLER** kontanter (som inte bär på någon extra data)\"*.\n\nI objektorientering skulle du behöva skapa ett gränssnitt `Betalningssatt`, tre underklasser i tre olika filer, konstruktorer, `instanceof`... I Ridgun är det **en enda rad**:\n\n```ridgun\ntype Betalningssatt = Kort String Int | Overforing String | Kontant\n```\n\nOch titta vad som händer när du bearbetar ett `Betalningssatt` i en funktion:\n\n```ridgun\nbeskriv betalning Betalningssatt => String\nbeskriv betalning (Kort num _) = \"Betalning med kort som slutar på {num}\"\nbeskriv betalning (Overforing iban) = \"Överföring från konto {iban}\"\nbeskriv betalning Kontant = \"Kontant betalning i kassan\"\n```\n\nVarje variant (`Kort`, `Overforing`, `Kontant`) bär endast med sig de data som är meningsfulla för just den. Det är **omöjligt** att skapa en `Kontant`-betalning som av misstag har ett `iban` hängande på släp.\n\n---\n\n## 6.3. \"Och hur stoppar jag in `[1, \"tva\"]` i en lista utan att använda `Any`?\"\n\nLåt oss återvända till tiotusenkronorsfrågan. Föreställ dig att du läser en CSV- eller JSON-fil där en cell kan vara ett heltal, en text eller helt tom.\n\nOm du hade en typ `Any` skulle du stoppa in `[1, \"tva\"]` och förlora all hjälp från kompilatorn: från det ögonblicket skulle varje operation på listan vara som att gå med förbundna ögon.\n\nI Ridgun (precis som i Haskell eller Rust) skapar du på två sekunder en summatyp som beskriver exakt vilka saker som kan bo i den listan:\n\n```ridgun\ntype Cellvarde = Heltal Int | Text String | Tom\n\nformatera cell Cellvarde => String\nformatera cell (Heltal n) = \"Tal: {n}\"\nformatera cell (Text s) = \"Text: {s}\"\nformatera cell Tom = \"(tom)\"\n\nmin rad => [Cellvarde]\nmin rad = [Heltal 1, Text \"tva\", Tom]\n```\n\nSer du skillnaden?\n- Med `Any` vet kompilatorn inte om det ligger heltal, strängar eller en USB-ansluten kaffebryggare i listan.\n- Med `[Cellvarde]` kan du blanda tal och texter i samma lista, **men kompilatorn vet till 100 % att endast dessa tre möjligheter existerar** och tvingar dig att packa upp varje fall (`Heltal n`, `Text s`, `Tom`) innan du använder det. Total säkerhet utan att förlora en millimeter i flexibilitet.\n\n---\n\n## 6.4. `Option` och `Result`: När något kan saknas eller gå fel\n\nEftersom det varken finns `null` eller undantag som exploderar i luften (`throw new Exception()`) i Ridgun, har språket två universella summatyper inbyggda från start:\n\n1. **`Option`**: antingen har du **`Some varde`**, eller så har du **`None`** (ingenting).\n2. **`Result`**: antingen gick operationen bra (**`Ok varde`**), eller så misslyckades den av en konkret anledning (**`Err fel`**).\n\n```ridgun\nsaker division Int Int => Result\nsaker division _ 0 = Err \"Hallå där! Det går inte att dividera med noll\"\nsaker division a b = Ok (a / b)\n\nskriv ut res Result => ()\nskriv ut res (Ok n) = echo \"Resultatet är {n}\"\nskriv ut res (Err msg) = echo \"Kontrollerat fel: {msg}\"\n```\n\nIngen kan ignorera ett fel av slarv eftersom själva typen `Result` tvingar dig att titta efter om det ligger ett `Ok` eller ett `Err` inuti.\n\n---\n\n## 6.5. Parametrisk polymorfism: Generiska funktioner med `A`, `B`, `T`...\n\nAnta att du skriver en funktion som vänder på ett par `(x, y)` eller hämtar det första elementet i en lista. Spelar det verkligen någon roll om listan består av `Int`, `String` eller `Server`? Inte det minsta! Algoritmen är identisk.\n\nI Ridgun fungerar **vilken enskild versal som helst (`A` till `Z`)** i en typsignatur automatiskt som en **polymorf jokertyp (typvariabel)**:\n\n```ridgun\nsakert huvud [A] A => A\nsakert huvud [] standard = standard\nsakert huvud (x:_) _ = x\n\nvand par (A, B) => (B, A)\nvand par (x, y) = (y, x)\n```\n\nLägg märke till magin i `sakert huvud [A] A => A`:\n- Det är inte ett okontrollerat `Any`: det säger att **listans typ `[A]`, typen på värdet `standard` (`A`) och den returnerade typen (`A`) måste vara exakt samma**.\n- Om du anropar `sakert huvud [10, 20] 0` knyter kompilatorn ihop säcken (`A = Int`) och ger dig en `Int`.\n- Om du anropar `sakert huvud [\"a\", \"b\"] \"ingen\"` knyter den ihop säcken (`A = String`) och ger dig en `String`.\n- Men om du försöker fuska och anropar `sakert huvud [10, 20] \"ingen\"` — pang! Kompilatorn tvärbromsar dig eftersom det första argumentet säger att `A` är `Int` medan det andra säger att `A` är `String`.\n\n---\n\n## 6.6. Skapa dina egna operatorer (`op ::`): Från vektorer till skräddarsydda fraser\n\nVarför skulle bara de inbyggda talen ha rätt att använda `+` eller `*`? Och varför nöja sig med de gamla vanliga operatorerna när du kan uppfinna den perfekta syntaxen för ditt problem?\n\nMed **`op ::`** (eller direkt utan prefix om du använder operatormönster) kan du göra två konststycken:\n\n### 1. Lära `+`, `-`, `*`, `/`, `%` att räkna med dina egna typer\n```ridgun\ntype Komplext = real: Int, imag: Int\n\nop :: Komplext + Komplext => Komplext\n a + b = Komplext ((real a) + (real b)) ((imag a) + (imag b))\n```\n\n### 2. Skapa *Mixfix*-operatorer (som läses som naturliga meningar, inklusive `type` och `with`)\nI en operatorsignatur är **ord med inledande versal (`Int`, `String`, `A`..`Z`) eller inom hakparenteser/parenteser (`[Int]`, `(A, B)`) platserna för argumenten**, och **orden med gemener är en del av operatorns fras** (även så vanliga ord som `type` eller `with`, som i Ridgun är kontextuella och aldrig låser dig):\n\n```ridgun\nop :: om Bool sa A annars A => A\n om True sa v annars _ = v\n om False sa _ annars f = f\n\nop :: format String type String with Int => String\n format label type kind with w = \"{label} ({kind}, width={w})\"\n\nmain => ()\nmain =\n meddelande = om (10 > 5) sa \"Tio vinner!\" annars \"Omöjligt\"\n echo meddelande\n echo (format \"panel\" type \"bordered\" with 80)\n```\n\nDu har precis tillverkat din egen polymorfa ternära operator och ett formaterings-DSL på **3 rader** i Ridgun.\n\n---\n\n## 6.7. Delade konstruktorer, nakna typvarianter, `expand type` och naturliga mellanslag i `fn ::`\n\nRidgun gör algebraiska datatyper och funktioner ännu mer naturliga och utbyggbara:\n\n1. **Delade konstruktornamn mellan typer**: Olika `type`-deklarationer kan återanvända samma konstruktornamn (t.ex. `Error`, `Var`, `Lit`) med samma eller olika aritet — typkontrollanten avgör vilken typ som avses utifrån kolumnens signatur.\n2. **Nakna typvarianter utan upprepning (`type Something = String | Int | MyStruct Float Int`)**: När en variant är en inbyggd typ (`String`, `Int`, `Float`/`Real`, `Bool`, `Char`) behöver du inte skriva `Int Int` eller `String String`. Du kan skicka in nakna värden (`\"hej\"`, `42`) eller explicita konstruktorer (`String \"hej\"`, `Int 42`), och matcha både litteraler (`\"admin\"`, `0`) och typade mönster (`(String s)`, `(Int n)`).\n3. **Öppen typutvidgning (`expand type`) och automatisk sammanslagning av `fn ::`-klausuler**: Med `expand type` kan du lägga till nya varianter i en summatyp eller nya fält i en posttyp. Om du deklarerar `fn ::` igen för samma funktion slås de nya mönsterklausulerna ihop automatiskt **före** en eventuell `_`-reservklausul (utan att du behöver skriva `expand fn`).\n4. **Naturliga mellanslag `\" \"` istället för `_` i `fn ::` och filnamn**: Precis som i `op ::` kan funktionsnamn i `fn ::`, anrop till inbyggda funktioner (`assert equals`, `str len`, `read file`) och `.rg`-filnamn (`test core language.rg`) skrivas med naturliga mellanslag:\n\n```ridgun\ntype Something = String | Int | MyStruct Float Int\n\nfn :: beskriv nagot Something => String\n beskriv nagot \"admin\" = \"special_admin\"\n beskriv nagot 0 = \"noll\"\n beskriv nagot (String s) = \"text:{s}\"\n beskriv nagot (Int n) = \"heltal:{n}\"\n beskriv nagot (MyStruct kvot ant) = \"struktur:{kvot}:{ant}\"\n beskriv nagot _ = \"annat\"\n\nexpand type Something = Bool\n\nfn :: beskriv nagot Something => String\n beskriv nagot (Bool b) = \"boolesk:{b}\"\n```\n\n### 5. Egna generiska typer (`type Result T E`, `type Page T`) och modulnamnrymder (`import ... as`, `mod.Typ`)\nUtöver polymorfa funktioner kan du deklarera **egna generiska summatyper och posttyper** med typparametrar (`A`..`Z`), samt organisera typer, konstruktorer, fält och funktioner med samma namn i olika moduler utan namnkrockar (`module ::`, `import db as d`, `http.Config`, `d.Config`). Varje modul har **strikt importsynlighet i 3 nivåer**: okvalificerade namn slås upp först i **(1) modulens egna deklarationer** (inklusive flera filer som delar `module :: namn`), därefter i **(2) dess direkta `import`-moduler** och sist i **(3) dess transitiva importer**, så att syskonmoduler eller huvudapplikationen aldrig läcker in i importerade bibliotek:\n\n```ridgun\ntype Result T E = Ok T | Err E\ntype Page T = items: [T], total: Int\n\nfn :: packa upp ok (Result A String) A => A\n packa upp ok (Ok v) _ = v\n packa upp ok (Err _) d = d\n```\n\nI **Kapitel 07** ska vi sätta alla kärnor i din processor i arbete samtidigt utan att fälla en enda svettdroppe: **högre ordningens funktioner (`map`, `||map`, `filter`, `||filter`, `fold`), lexikala closures (`(x => expr)`), parallella `||`-grafer med `->` och samtidiga kanaler**.\n"}, {"num":"07","slug":"07-hogre-ordningen-och-dag-parallellism","file":"07-hogre-ordningen-och-dag-parallellism.md","title":"Kapitel 07: Högre ordningens funktioner och svettfri parallellism (Utan `Mutex`, utan `Deadlocks`)","short_title":"Högre ordningens funktioner och svettfri parallellism (Utan `Mutex`, utan `Deadlocks`)","markdown":"# Kapitel 07: Högre ordningens funktioner och svettfri parallellism (Utan `Mutex`, utan `Deadlocks`)\n\nI nästan alla programmeringsspråk finns det ett dramatiskt ögonblick i ett projekts liv: dagen då någon på ett möte säger:\n\n> *\"Det här går långsamt. Vi måste parallellisera det med trådar.\"*\n\nDet blir knäpptyst i rummet. Alla vet vad som väntar härnäst: veckor av jakt på spöklika *race conditions* som bara inträffar på tisdagar vid fullmåne, ömsesidiga låsningar (*deadlocks*) och fel som inte går att återskapa.\n\nNär någon i Ridgun säger *\"vi måste parallellisera det\"*, räcker det med att sätta `||` framför dina listoperationer (**`||map`** och **`||filter`**) eller lägga dina beräkningar i ett parallellt `||`-block med pilar `->` och gå och ta en kaffe.\n\nVarför? Därför att **när dina funktioner är rena och dina data är oföränderliga (*immutable*) som standard, kan två processorkärnor som arbetar samtidigt aldrig trampa på varandras slangar**.\n\nLåt oss gå igenom det steg för steg.\n\n---\n\n## 7.1. Funktioner som tar emot funktioner: `map`, `||map`, `filter`, `||filter` och `fold`\n\nI Ridgun är en funktion ett värde som alla andra. Du kan skicka in den som parameter precis som du skickar in talet `7`.\n\nSpråket har inbyggda samlingskombinatorer för att omvandla listor utan att skriva en enda manuell rekursion, både i sekventiellt läge (`map`, `filter`, `fold`) och i flerkärnigt parallellt läge med prefixet `||` (**`||map`**, **`||filter`**):\n\n### 1. `map` (sekventiell) och `||map` (parallell över flera kärnor)\nAnta att du har en funktion `tung Int => Int` och en lista med tal:\n\n```ridgun\ntung Int => Int\ntung x = (x * x) + (x * 3)\n\nmain => ()\nmain =\n data = [1, 2, 3, 4, 5, 6, 7, 8]\n -- Strikt sekventiell från vänster till höger:\n r1 = map tung data\n -- Parallell över flera kärnor med prefixet `||`:\n r2 = ||map tung data\n echo r1\n echo r2\n```\n\n- Med **`map`** tillämpar Ridgun funktionen element för element från vänster till höger i den aktuella tråden (perfekt för små listor eller funktioner med ordnade in-/utmatningseffekter).\n- Med **`||map`** fördelar Ridguns körtidsmiljö elementen i `data` mellan arbetstrådarna i din processor och bygger upp slutlistan **i exakt samma ordning**, vilket garanterar att `||map f xs == map f xs`.\n\n### 2. `filter` (sekventiell) och `||filter` (parallell): Behåll bara dem som uppfyller ett villkor\nDu skickar in en funktion som returnerar `Bool` (ett *predikat*) och en lista:\n\n```ridgun\nar positiv Int => Bool\nar positiv n = n > 0\n\nmain => ()\nmain =\n rena = filter ar positiv [-5, 10, 0, -2, 42]\n rena_par = ||filter ar positiv [-5, 10, 0, -2, 42]\n echo rena -- Skriver ut [10, 42]\n echo rena_par -- Skriver ut [10, 42]\n```\n\n### 3. `fold`: Reducera en hel lista till ett enda resultat\nDu skickar in en kombinerande funktion med två argument `(Ackumulerat Element => Ackumulerat)`, startvärdet och listan:\n\n```ridgun\nackumulera produkt Int Int => Int\nackumulera produkt acc x = acc * x\n\nmain => ()\nmain =\n echo (fold ackumulera produkt 1 [2, 3, 4, 5]) -- 1 * 2 * 3 * 4 * 5 = 120\n```\n\n### Hur skriver jag en egen funktion som tar emot en annan funktion?\nHur enkelt som helst: i typsignaturen sätter du den inbjudna funktionens signatur inom parentes `(Indata => Utdata)`:\n\n```ridgun\nkor tva ganger (A => A) A => A\nkor tva ganger f x = f (f x)\n```\n\n### 4. Idiomatiska pipelines från vänster till höger (`->`) — 100 % Ridgun-stil!\nNär du kedjar ihop flera transformationer (`map`, `filter`, `fold` eller dina egna funktioner och `op ::`-operatorer) tvingar nästlade parenteser från höger till vänster (`compact l (filter g (map f xs))`) dig att läsa inifrån och ut.\n\nI Ridgun läses den **rekommenderade idiomatiska stilen (`2b`)** från vänster till höger med pipeline-operatorn **`->`**, där **det som kommer från vänster alltid går in som första argument** till nästa funktion eller `op ::`:\n\n```ridgun\n-- Rekommenderad idiomatisk stil i Ridgun (2b):\nxs map (x => x * 2) -> filter (x => x > 10) -> fold (acc x => acc + x) 0 -> resultat\n\n-- Och om en funktion returnerar en tupel filtrerar du den med en mask och den packas upp automatiskt:\ntolka paket \"v0.9.9\" -> (+ _ _ +) -> kombinera kod -> sammanfattning\n```\n\nDessutom kan varje uttryck med sidoeffekter (skriva en fil, anropa systemet) stå på en egen rad utan `echo` eller dummyvariabler `_ =`, eller avslutas med `-> ()` om du uttryckligen vill kasta returvärdet.\n\n### 5. Lexikala closures och anonyma funktioner (`(x => expr)`, `(acc x => expr)`)\nNär du vill skicka in en kort funktion i farten eller fånga lokala variabler från det omgivande scopet (som en offset, ett prefix eller en aktiv session) utan att deklarera en separat toppnivåfunktion använder du en **lexikal closure** inom parentes med **`=>`**:\n\n```ridgun\nfn :: bearbeta med session => [Int]\n bearbeta med session =\n offset = 10\n bonus = 3\n adderade = map (x => x + offset) [1, 2, 3]\n filtrerade = filter (x => x >= bonus) [1, 2, 3, 4]\n total = fold (acc x => acc + x + bonus) 0 [1, 2, 3]\n par = map ((a b) => a + b + offset) [(1, 2), (3, 4)]\n adderade :: filtrerade :: [total] :: par\n```\n\nFem regler håller lambdauttryck rena och entydiga:\n- **Obligatoriska parenteser**: varje lambda skrivs alltid inom parentes `(... => ...)`.\n- **Lambda utan parametrar (`(=> expr)`)**: precis som `fn :: main => ()` inte har `()` före `=>`, skrivs en parameterlös lambda `(=> expr)` (och dess typ är `(=> Typ)`), aldrig `(() => expr)`.\n- **Flera parametrar kontra tupel (`(a b => ...)` vs. `((a b) => ...)`)**: `(acc x => ...)` tar två separata parametrar, medan `((a b) => ...)` tar en enda tupel och destrukturerar den.\n- **Flerradig kropp**: om du lägger en radbrytning efter `=>` kan du skriva ett indenterat flerstegsblock före det avslutande `)`:\n ```ridgun\n dubblade = map (x =>\n steg = x * 2\n steg + offset\n ) [1, 2, 3]\n ```\n- **Versaler kontra gemener**: `(Conn => Conn)` är en funktionstyp (stor begynnelsebokstav) och `(conn => conn)` är ett lambdavärde (liten begynnelsebokstav).\n\nFångade variabler (`offset`, `bonus`) hanteras deterministiskt med `RMM1`/`RMM2` — noll minnesläckor och noll skräpsamlingspauser.\n\n---\n\n## 7.2. Kronjuvelen: `||`-block med `->` som parallella grafer (DAG)\n\nDet är här Ridgun förändrar ditt sätt att tänka.\n\nNär du i ett vanligt imperativt språk skriver tre rader efter varandra:\n1. Först körs rad 1.\n2. Sedan rad 2 (även om den inte har det minsta med rad 1 att göra).\n3. Sedan rad 3.\n\nDet är att tvinga datorn att arbeta med skygglappar. När du i Ridgun använder parallella streck **`||`** med pilar **`->`** (utan att behöva skriva något nyckelord som `where`), ger du inte sekventiella order: du ritar en **riktad acyklisk graf (DAG)** som anger vilken beräkning som matar vilken variabel:\n\n```ridgun\nfib Int => Int\nfib 0 = 0\nfib 1 = 1\nfib n = (fib (n - 1)) + (fib (n - 2))\n\nfact Int => Int\nfact 0 = 1\nfact n = n * (fact (n - 1))\n\nsuper berakning => Int\nsuper berakning = vanster_gren + hoger_gren\n || fib 10 -> vanster_gren\n || fact 6 -> hoger_gren\n```\n\nLäs det högt:\n- *\"Jag vill beräkna `vanster_gren + hoger_gren`, medan `fib 10` parallellt (`||`) går in i `vanster_gren` (`->`) och `fact 6` går in i `hoger_gren` (`->`).\"*\n\n### Vad `ridgunc` gör bakom kulisserna med dina `||`-rader:\n1. Den tittar på pilarna `->` och bygger upp beroendeträdet (DAG).\n2. **Den fångar cykler statiskt**: om du av misstag skriver `|| a + 1 -> b` och `|| b + 1 -> a`, säger kompilatorn genast ifrån: *\"Stopp där! Här finns ett cirkulärt beroende\"* och vägrar kompilera en oändlig låsning.\n3. Den ser att `fib 10` och `fact 6` inte är beroende av varandra, så de får grönt ljus att köras parallellt innan de summeras i `vanster_gren + hoger_gren`.\n\nDu kan till och med bygga en pipeline i flera våningar inuti samma `||`-block — antingen under uttrycket eller direkt efter `=` — och kompilatorn räknar själv ut vilka våningar som kan köras samtidigt och vilka som måste vänta:\n\n```ridgun\nkvartalsbalans Int => Int\nkvartalsbalans bas =\n || bas * 100 -> bruttoforsaljning\n || bas * 40 -> fasta_kostnader\n || bruttoforsaljning - fasta_kostnader -> bruttovinst ||.\n bruttovinst * 80 / 100\n```\n\nLägg märke till detaljen **`||.`** i slutet av den sista `||`-raden: precis som `|.` stänger ett nästlat vaktträd, stänger **`||.`** det parallella `||`-blocket när vanliga sekventiella satser följer nedanför. Här startar `bruttoforsaljning` och `fasta_kostnader` parallellt; när båda är klara beräknas `bruttovinst`, och slutligen returneras `bruttovinst * 80 / 100`. Allt utan ett enda `async`, `Future`, `Promise` eller `Mutex`.\n\n---\n\n## 7.3. Genvägen `||` utan namn: Parallella rör som returnerar en tupel\n\nMen tänk om du bara vill starta två eller tre beräkningar parallellt och samla ihop dem i en tupel utan att ens behöva hitta på variabelnamn med `->`?\n\nDå använder du `||` direkt:\n\n```ridgun\nparallellt par Int => (Int, Int)\nparallellt par n =\n || fib n\n || fact n\n```\n\nRakt, visuellt och returnerar tupeln `(fib n, fact n)`.\n\n---\n\n## 7.4. När du vill hålla i ratten själv: den inbyggda agentmodellen (`agent`, `send ... to`, `receive from`) och CSP-kanaler\n\nDen automatiska parallellismen i `||`-block och `||map` täcker 90 % av fallen. Men när du bygger en beständig server, isolerade användarsessioner, en jobbkö eller en producent–konsument-pipeline vill du ha **samtidiga agenter med isolerat minne och statiskt typad meddelandehantering**.\n\nI Ridgun behövs inget särskilt nyckelord som `actor ::`: **vilken vanlig funktion som helst (`fn ::` eller `op ::`) förvandlas till en samtidig agent på en enda rad med `agent`**:\n\n### 1. Tillståndslösa och tillståndsbärande agenter (`agent`, `send ... to`, `receive from`, `stop`)\n- `ag = agent (min funktion)`: gör om en funktion `M => R` till en tillståndslös agent av typen `Agent M R`.\n- `ag = agent (funktion med tillstand) starttillstand`: gör om en funktion `S M => S` (eller `S M => S R`) till en agent med isolerat tillstånd som minns sitt tillstånd från meddelande till meddelande utan en enda `Mutex`.\n- `send msg to ag` (eller med flera argument: `send a b to ag`): skickar ett typat meddelande till agentens inkorg.\n- `res = receive from ag` (eller icke-blockerande `try receive from ag`): hämtar nästa svar ur agentens utkorg.\n- `stop ag`: stoppar agenten och frigör dess tillstånd deterministiskt via `RMM1`/`RMM2`.\n\n```ridgun\nfn :: addera besok Int Int => Int\n addera besok ack n = ack + n\n\nfn :: bearbeta parti Int Int => Int\n bearbeta parti id t = (id * 100) + t\n\nfn :: main => ()\n main =\n raknare = agent (addera besok) 10\n send 5 to raknare\n send 7 to raknare\n v1 = receive from raknare\n v2 = receive from raknare\n stop raknare\n\n arbetare = agent (bearbeta parti)\n send 3 25 to arbetare\n parti = receive from arbetare\n stop arbetare\n echo \"Besök:\" v1 \"->\" v2 \"| Parti:\" parti\n```\n\n### 2. Smart val vid kompilering (*Green Threads* vs. Riktiga Kärntrådar)\nEn vanlig fråga är: *\"Skapar `||`-block, `||map` och `agent`-agenter alltid operativsystemtrådar, eller körs de som lätta uppgifter?\"*\n\nI Ridgun **fattar kompilatorn det beslutet åt dig genom att statiskt analysera varje funktion**:\n- **Lätta funktioner (`TierTrivial` / `StratInlineSequential`)**: Om funktionen du skickar till `||`, `||map`, `||filter` eller `agent` har litet djup (aritmetik, strängformatering, snabba tillståndsövergångar i en HTTP-session) skulle det kosta mer att värma upp operativsystemtrådar än själva beräkningen. Kompilatorn kör den som ett ultralätt *green-thread*-steg utan `SYS_clone`-overhead.\n- **Tunga eller djupt rekursiva beräkningar (`TierDynamicRecursive` / `TierHeavyCPU`)**: Om funktionen har djup rekursion (som `fib` eller `fact`) eller tensoralgebra (`einsum`, `hadamard`, `@`) genererar kompilatorn automatiskt flerkärnig utskickning över **riktiga kärntrådar (`SYS_clone`)**, och bearbetar `||`-grenar eller `agent`-meddelandekön i äkta hårdvaruparallellism över alla dina CPU-kärnor.\n\n### 3. Skicka meddelanden via begränsade kanaler (`new bounded channel`)\nPrecis som i Go eller Erlang kan du utöver agenter även skapa uttryckliga rör för att koppla ihop steg:\n\n- `new bounded channel kapacitet`: skapar en kanal med plats för `kapacitet` meddelanden.\n- `send through varde kanal` (eller `chan send varde kanal`): lägger in ett meddelande i röret.\n- `receive from kanal` (eller `chan recv kanal`): hämtar nästa meddelande ur röret.\n- `try receive from kanal`: tittar efter om det finns ett meddelande utan att bli stående och vänta; returnerar `Some varde` eller `None`.\n- `receive from timeout kanal ticks`: väntar upp till en tidsgräns och returnerar `Ok varde` eller `Err Timeout`.\n\n```ridgun\nfn :: main => ()\n main =\n ror = new bounded channel 4\n _ = send through \"Uppgift A slutförd\" ror\n _ = send through \"Uppgift B slutförd\" ror\n forsta = receive from ror\n andra = receive from ror\n echo forsta \"|\" andra\n```\n\n### 4. Sänkagenter (*fire-and-forget* `agent sink`), globala brevlådor (`agent ::`) och deterministiska tester (`with agent`)\nNär du behöver asynkron granskning, mätvärden eller spårning utan att skräpa ner alla funktionssignaturer eller samla olästa svar i en utkö erbjuder Ridgun **sänkagenter (`agent sink`)** och **globala brevlådor på toppnivå (`agent ::`)** (`agent dropped`, `agent flush`, `agent state` och `with agent audit_log = spion do ...`), samt `Channel`- och `Agent`-deskriptorer som kan delas fritt mellan flera arbetare.\n\nOch spänn nu fast säkerhetsbältet inför **Kapitel 08**, den stora finalen: **tensorer med kompileringstidsverifierade dimensioner, räckviddsvariabler (`context`/`shared`), deterministiska minnesregioner, direkt hårdvaruåtkomst via MMIO och UNIX/POSIX-systemprogrammering**.\n"}, {"num":"08","slug":"08-tensorer-rmm-regioner-och-system","file":"08-tensorer-rmm-regioner-och-system.md","title":"Kapitel 08: Tensorer, kompilerat RMM-minne (`RMM1`/`RMM2`), regioner och system","short_title":"Tensorer, kompilerat RMM-minne (`RMM1`/`RMM2`), regioner och system","markdown":"# Kapitel 08: Tensorer, kompilerat RMM-minne (`RMM1`/`RMM2`), regioner och system\n\nHittills har vi sett den mest vänliga, eleganta och matematiska sidan av Ridgun: rena funktioner, algebraiska datatyper, mönstermatchning, beslutsträd med `|` / `|.` och parallella `||`-grafer med `->` som utnyttjar alla kärnor i din processor utan att kräva ett enda ynka `Mutex`.\n\nVid det här laget brukar den erfarna systemprogrammeraren längst bak i salen räcka upp handen med ett snett leende och fråga:\n\n> *\"Allt det här är jättefint för att räkna på fakturor eller kompilera AST-träd, men vad händer när jag behöver multiplicera matriser med miljontals flyttal i svindlande fart? Vad händer med minnet? Ligger det en skräpsamlare (Garbage Collector) gömd under mattan och väntar på sämsta tänkbara ögonblick för att frysa mitt program i 200 millisekunder? Och hur pratar jag med operativsystemet Unix på riktigt?\"*\n\nUtmärkta frågor. Låt oss lyfta på motorhuven till Ridgun och se hur det beter sig när det är dags att kavla upp ärmarna i systemprogrammering, numeriska beräkningar och deterministiskt minne.\n\n---\n\n## 8.1. Minnesdilemmat: varken Garbage Collector eller bråk med Borrow Checker (`RMM1` och `RMM2`)\n\nI de moderna språkens värld brukar det finnas två oförenliga läger:\n\n1. **Garbage Collector-lägret (Java, Go, Python, JS, Haskell, OCaml):** du begär glatt mer minne och då och då stannar en osynlig sopbil all trafik i ditt program för att spåra vilka objekt som fortfarande lever och vilka som är döda. Det är hur bekvämt som helst... ända tills du bygger ett blixtsnabbt systemverktyg eller en server med strikta svarstider och sopbilen bestämmer sig för att dubbelparkera.\n2. **Manuell kontroll / Borrow Checker-lägret (C, C++, Rust):** det finns ingen skräpsamlare, men i gengäld måste du hantera pekare för hand (med risk för `Segmentation fault` eller *use-after-free*) eller ägna en halv eftermiddag åt att förhandla med *borrow checker* om varför `'a` inte lever lika länge som `'b`.\n\nRidgun löser detta dilemma från grunden med **Ridgun Memory Management (`RMM`)**, ett deterministiskt system med två kompletterande policyer (**`RMM1`** och **`RMM2`**) kombinerat med **lexikala regioner (`with region`)**:\n\n### Policy `RMM1` — Kompilerad minneshantering (Linjär och villkorlig CMM)\nNär kompilatorn statiskt känner till flödet av lokala variabler inuti en funktion:\n- **Linjär CMM**: `ridgunc` beräknar vid kompileringstillfället vilken som är den **sista raden** där varje lokal variabel (`a`, `b`, ...) läses och skjuter direkt efter den in dess deterministiska frigörning (`rg_cmm_drop`), eller överför ägarskapet utan kopiering (`rg_cmm_move`) när variabeln returneras som resultat.\n- **Villkorlig CMM (`ptr(a) != ptr(c)`)**: men vad händer om en funktion som `valj cond a b` returnerar `a` eller `b` beroende på ett villkor vid körning? Då bygger `ridgunc` upp härkomsttabellen och genererar en pekaridentitetsvakt på **1 CPU-cykel**: om `b` slutar användas medan `c` fortfarande lever, kontrollerar den `if ptr(b) != ptr(c) { free(b) }`. Den gren som inte valdes frigörs omedelbart och den valda överlever intakt.\n\n### Policy `RMM2` — Tilldelningsräkning och strukturell kaskad\nOch vad händer när du stoppar in strukturer i andra strukturer (`xs = [a, b]`), tilldelar om muterbara variabler (`mut x = ...`) eller kedjar ihop komplexa anrop? Där kliver **`RMM2`** in och styr hela livscykeln med fyra vattentäta matematiska regler:\n\n1. **Inkommande funktionsargument rörs inte (`+0` vid inträde, `-0` vid utträde)**: att skicka en lista eller en post till en funktion ökar eller minskar aldrig några räknare i onödan.\n2. **Varje tilldelning till en intern lokal variabel eller behållarcell lägger till `+1`**:\n - `a = [10, 20]` $\\rightarrow$ blocket `M1` föds med räknaren `1`.\n - `xs = [a, b]` $\\rightarrow$ listan `xs` föds med `1`, och eftersom den sparar referenser till `a` och `b` stiger båda till `2`.\n - Om du tilldelar om en muterbar variabel (`mut x = ...` och sedan `x = ny`), lägger `RMM2` först på **`+1`** på det nya värdet innan den drar av **`-1`** från det gamla.\n3. **När funktionen avslutas får lokala variabler som INTE returneras `-1`**: om en strukturs räknare når `0` frigörs dess minne på fläcken och **sprider `-1` i kaskad, ett i taget, till vart och ett av dess direkta barn**.\n4. **Värdet som returneras av funktionen undantas under transporten**: det får sitt `-1` som lokal variabel men förstörs inte när det passerar `return`, så att när anroparen skriver `c = min funktion ()`, lämnar tilldelningens `+1` räknaren på exakt `1`.\n\n```ridgun\nvalj Bool [Int] [Int] => [Int]\nvalj cond a b =\n | cond = a\n | otherwise = b\n\nexempel rmm2 Bool => Int\nexempel rmm2 cond =\n a = [10, 20, 30] -- M1 (rc = 1)\n b = [40, 50, 60] -- M2 (rc = 1)\n c = valj cond a b -- `c` får +1; den som inte valdes dör precis här (rc -> 0)\n (rakna a) + (rakna c) -- Vid slutet får `a` och `c` -1 och 0 levande block återstår\n```\n\n---\n\n## 8.2. Lexikala regioner med kvot (`with region`): Minnesbrandväggar i $O(1)$\n\nUtöver `RMM1` och `RMM2` kan du, när du bearbetar ett externt nätverkspaket, en enorm fil eller ett parti opålitliga data och vill sätta ett **strikt tak för RAM-minnet**, kapsla in beräkningen i ett **`with region`**-block:\n\n```ridgun\nbearbeta ram String => Result\nbearbeta ram radata =\n with region 64_KB do\n rena = map rensa rad (dela rader radata)\n rakna giltiga rena\n```\n\n1. **Garanterad kvot i hårdvara/körtidsmiljö**: om något inuti blocket försöker reservera ens en enda byte över `64_KB` (`65 536` byte) avbryter körtidsmiljön blocket snyggt, frigör hela den tillfälliga arenan på konstant tid $O(1)$ och returnerar `Err OutOfMemory` utan att krascha processen.\n2. **Omedelbar frigörning vid utträde**: så fort `with region`-blocket avslutas försvinner allt tillfälligt minne i arenan i ett enda slag utan att lämna någon fragmentering.\n\n---\n\n## 8.3. Inbyggda tensorer, Einsteinkontraktion (`@`) och symboliska dimensioner\n\nOm du någonsin har programmerat i Python med NumPy eller PyTorch har du garanterat råkat ut för det klassiska felet efter 41 minuters körning:\n\n```text\nRuntimeError: mat1 and mat2 shapes cannot be multiplied (128x64 and 32x128)\n```\n\nI Ridgun är **`Tensor`** förstklassiga inbyggda medborgare och deras dimensioner är en del av typsignaturen:\n\n```ridgun\n-- Om (N × K) och (K × M) går in, måste det ovillkorligen komma ut (N × M)!\nmultiplicera matriser Tensor[N, K] Tensor[K, M] => Tensor[N, M]\nmultiplicera matriser a b = a_ik @ b_kj\n```\n\nLägg märke till två spektakulära detaljer:\n1. **Statisk dimensionsverifiering (`Tensor[N, K]`)**: den inre axeln `K` i den första matrisen måste stämma överens med den första axeln `K` i den andra. Om du försöker skicka in inkompatibla dimensioner stoppar `ridgunc check` dig innan något ens körs.\n2. **Einsteins indexnotation (`a_ik @ b_kj`) och Hadamard (`a_ij * b_j`)**:\n - Med **`@`** kontraheras (summeras) de index som upprepas i alla operander (`k`), medan de unika (`i`, `j`) överlever i resultattensorn.\n - Med **`+`, `-`, `*`, `/`** justerar indexen dimensionerna och utför automatisk *broadcasting* (`a_ij * b_j` multiplicerar varje rad `i` i `a` med vektorn `b_j` utan att du behöver skriva `unsqueeze` eller `reshape`).\n3. **Högpresterande typade tensorer (`Tensor[U64 * N]`) och mutering *in-place* med `t_(i, j)`**:\n I kryptografiska system, fysiksimuleringar eller linjär algebra kan du deklarera platta tensorer över ett sammanhängande block av teckenlösa 64-bitars heltal (`Tensor[U64 * 4]`, `Tensor[U64 * 8 * 16]`), operera parallellt med `^` (inbyggd block-XOR) och läsa eller skriva element på $O(1)$-tid med den uttryckliga indexsyntaxen `t_(i)` eller `t_(i, j)`:\n ```ridgun\n skapa tillstandsblock => Tensor[U64 * 2 * 2]\n skapa tillstandsblock =\n mut m = tensor fill [2, 2] (u64 0)\n m_(0, 1) = u64 0x6a09e667f3bcc908\n m\n ```\n\n---\n\n## 8.4. Hårdvaruåtkomst (`hardware ::`) och POSIX-systemprimitiver\n\nSjälva kompilatorn `ridgunc`, bygghanteraren `stable` och Unix-systemverktyg är skrivna i Ridgun. För detta innehåller språket minnesmappade registerblock (`hardware ::`) och direkta POSIX-primitiver:\n\n```ridgun\nhardware :: UART0 @ 0x1000_0000\n tx_data : Int @ 0x00\n status : Int @ 0x04\n```\n\nOch för att arbeta med operativsystemet:\n\n| Primitiv | Signatur | Vad den gör |\n|---|---|---|\n| `cli args` | `=> [String]` | Kommandoradsargument (`argv`). |\n| `read file` / `write file` | `String => String` / `String String => ()` | Läsning och skrivning av hela filer på disk. |\n| `read bytes` / `write bytes` | `String => [Int]` / `String [Int] => ()` | Exakt binär läsning och skrivning byte för byte (`0..255`). |\n| `list dir` / `file lstat` | `String => [String]` / `String => ...` | Listning av kataloger och inspektion av POSIX-metadata (`lstat`). |\n| `sha256 file` / `sha256 str` / `sha256 raw` | `String => String` | Inbyggd kryptografisk SHA-256-hash (64 tecken hexadecimalt eller rått 32-bytes binärt sammandrag med `sha256 raw` / `sha256 bytes`). |\n| `sys exec` / `shell exec` | `... => Int` | Körning av operativsystemprocesser. |\n| `sys getcwd` / `sys chdir` | `=> String` / `String => Int` | Fråga efter eller byt aktuell arbetskatalog. |\n| `sys getenv` / `sys setenv` | `String => String` / `String String => Int` | Processens miljövariabler. |\n| `sys getuid` / `sys getgid` | `=> Int` | Processens faktiska UID och GID (`doas`, säkerhetsverktyg). |\n| `sys exit` | `Int => ()` | Avsluta processen med returkod. |\n\n---\n\n## 8.5. Ekosystemet av standardbibliotek (`ridgun-libs`)\n\nUtöver kompilatorns primitiver innehåller Ridguns officiella ekosystem **32 rena bibliotek (`.rglib`)** skrivna helt i Ridgun som du kan importera med `import <namn>` i vilket projekt som helst:\n\n| Kategori | Tillgängliga bibliotek | Vad de tillhandahåller |\n|---|---|---|\n| **Samlingar, text och data** | `collections`, `set`, `string`, `regex`, `utf8`, `fmt`, `csv`, `json`, `toml`, `yaml`, `xml`, `html`, `markdown`, `base64`, `hex`, `compress`, `sql` | Avbildningar, mängder, reguljära uttryck, strukturerade tolkar/serialiserare, kodning och frågemotorer. |\n| **Matematik, tid och slumptal** | `math`, `random`, `datetime`, `uuid`, `log`, `cli`, `bench`, `test` | Matematiska funktioner, deterministisk och systembaserad PRNG, ISO-8601-datum, UUID, testramverk och prestandamätningar med `clock_gettime`. |\n| **System, nätverk och webb** | `fs`, `path`, `process`, `env`, `net`, `http`, `uri` | Högnivåfilsystem, sökvägshantering, underprocesser, TCP/UDP-uttag samt HTTP-klient och -server. |\n| **Kryptografi och säkerhet (`crypto`)** | `crypto` (`sha256`, `hmac`, `hkdf`, `pbkdf2`, `argon2id`, `chacha20`, `aes`, `x25519`, `ed25519`, `csprng`) | Kryptografisk svit verifierad mot officiella RFC/NIST-vektorer, implementerad över `U64`, `Tensor[U64 * ...]` och `sha256 raw` med tupel-inlining utan heap-allokeringar. |\n\n---\n\n## 8.6. Verklig fallstudie: Vi bygger `rg-wc`, ett parallellt Unix-verktyg\n\nLåt oss knyta ihop allt vi har lärt oss från Kapitel 01 fram till hit i ett riktigt systemprogram: en parallell version av Unix-verktyget `wc` (rad- och byteräknare för flera filer) skriven i ren Ridgun:\n\n```ridgun\n-- 1. Vi modellerar mätvärdena för en fil med en ADT-post (Kapitel 06)\ntype Matvarden = fil: String, rader: Int, bytes: Int\n\n-- 2. Vi räknar radbrytningar (ASCII-kod 10) med TCO-svansrekursion (Kapitel 04)\nfn :: rakna radbrytningar String Int Int Int => Int\n rakna radbrytningar text pos slut ack =\n | pos >= slut = ack\n | (str char at text pos) == 10 = rakna radbrytningar text (pos + 1) slut (ack + 1)\n | otherwise = rakna radbrytningar text (pos + 1) slut ack\n\nfn :: antal rader String => Int\n antal rader text = rakna radbrytningar text 0 (str len text) 0\n\n-- 3. Vi analyserar en fil och returnerar dess Matvarden-struktur\nfn :: analysera fil String => Matvarden\n analysera fil sokvag =\n innehall = read file sokvag\n || antal rader innehall -> n_rader\n || str len innehall -> n_bytes ||.\n Matvarden sokvag n_rader n_bytes\n\n-- 4. Vi formaterar varje rad och summerar totaler med `fold` och `||` (Kapitel 07)\nfn :: formatera matvarde Matvarden => String\n formatera matvarde m = \"{rader m}\\t{bytes m}\\t{fil m}\"\n\nfn :: summera rader Int Matvarden => Int\n summera rader acc m = acc + (rader m)\n\nfn :: summera bytes Int Matvarden => Int\n summera bytes acc m = acc + (bytes m)\n\nfn :: generera rapport [String] => String\n generera rapport sokvagar =\n matvarden = ||map analysera fil sokvagar\n || map formatera matvarde matvarden -> rader_ut\n || fold summera rader 0 matvarden -> total_r\n || fold summera bytes 0 matvarden -> total_b ||.\n \"{rader_ut}\\nTotalt: {total_r} rader, {total_b} byte\"\n\nfn :: main => ()\n main =\n echo (generera rapport [\"README.md\", \"AGENTS.md\"])\n```\n\nStanna upp en sekund och titta på dessa ~40 rader kod:\n- Det finns inte ett enda `null`, inget okontrollerat undantag och inget `Mutex`.\n- `rakna radbrytningar` kompileras till en inbyggd `loop` med 0 byte stackminne tack vare automatisk TCO.\n- `||map analysera fil sokvagar` bearbetar filerna parallellt på alla kärnor i din processor, och `||`-blocket beräknar samtidigt de formaterade raderna, totalt antal rader och totalt antal byte.\n- Det tillfälliga minnet frigörs deterministiskt via **`RMM1`/`RMM2`**.\n- Och när du kör `ridgunc build rg_wc.rg -o rg-wc` får du en fristående inbyggd binär på ~350 KB, färdig att kopieras till `/usr/local/bin`.\n\n---\n\n## 8.7. Slutlig färdplan: Ridgun-programmerarens 10 gyllene regler\n\n1. **Skriv alltid kontraktet (`=>`) först och ekvationerna (`=`) sedan:** att tänka på typerna först får kompilatorn att arbeta åt dig.\n2. **Låt `stable format` formge dina tabeller:** skriv med ett mellanslag och låt verktyget rada upp kolumner, `=>`, `=` och `->`.\n3. **Kom ihåg den universella regeln för `=`:** efter vilket `=` som helst kan du öppna ett sekventiellt block, ett vaktträd `|` eller en parallell graf `||`.\n4. **Använd `|.` och `||.` endast när du stänger ett nästlat block för att återvända till en högre nivå:** håll djupa beslutsträd kompakta och entydiga.\n5. **Oföränderligt som standard (`x = ...`), uttryckligt föränderligt (`mut x = ...`):** använd `mut` endast när en lokal ackumulator verkligen kräver det.\n6. **Använd tydliga booleska operatorer i gemener (`and`, `or`, `xor`, `not`) och avsluta alltid dina vakter med `| otherwise =`.**\n7. **Modellera din domän med ADT (`type`):** använd poster med `with falt: varde` och summatyper (`Option`, `Result`) i stället för `null`.\n8. **Parallellisera genom att deklarera beroenden med `|| expr -> var` samt `||map` / `||filter`:** låt kompilatorn verifiera att det inte finns några cykler och fördela arbetet mellan kärnorna.\n9. **Sätt symboliska dimensioner på dina tensorer (`Tensor[N, K]`) och index på dina kontraktioner (`a_ik @ b_kj`).**\n10. **Lita på `RMM` (`RMM1`/`RMM2`), avgränsa extern indata med `with region` och verifiera alltid med `stable check` och `stable test`.**\n\nLycka till på resan med att programmera i Ridgun!\n"}]; |
| 416 | const UI_STRINGS = {"copy_label":"Kopiera","copied_label":"Kopierad!","prev_label":"← Föregående kapitel","next_label":"Nästa kapitel →","search_hits_label":"Resultat för","search_empty_label":"Inga träffar hittades för"}; |
| 417 | let currentIdx = 0; |
| 418 | |
| 419 | function escapeHtml(s) { |
| 420 | return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); |
| 421 | } |
| 422 | |
| 423 | function highlightRidgun(code) { |
| 424 | return code.split("\n").map(line => { |
| 425 | const comIdx = (() => { |
| 426 | let inD = false, inS = false; |
| 427 | for (let i = 0; i < line.length - 1; i++) { |
| 428 | if (line[i] === "\\") { i++; continue; } |
| 429 | if (line[i] === '"' && !inS) inD = !inD; |
| 430 | else if (line[i] === "'" && !inD) inS = !inS; |
| 431 | else if (!inD && !inS && line[i] === "-" && line[i+1] === "-") return i; |
| 432 | } |
| 433 | return -1; |
| 434 | })(); |
| 435 | const codePart = comIdx >= 0 ? line.slice(0, comIdx) : line; |
| 436 | const comPart = comIdx >= 0 ? line.slice(comIdx) : ""; |
| 437 | let html = escapeHtml(codePart); |
| 438 | // Strings |
| 439 | html = html.replace(/("([^"\\]|\\.)*"|'[^']*')/g, '<span class="rg-str">$1</span>'); |
| 440 | // Keywords |
| 441 | html = html.replace(/\b(fn|op|type|import|mut|otherwise|with|region|do|global|context|shared|atomic|hardware|echo|and|or|xor|not)\b/g, '<span class="rg-kw">$1</span>'); |
| 442 | // Types & constructors |
| 443 | html = html.replace(/\b(Int|Real|String|Char|Bool|Tensor|Option|Result|Some|None|Ok|Err|OutOfMemory|Timeout|True|False)\b/g, '<span class="rg-ty">$1</span>'); |
| 444 | // Operators |
| 445 | html = html.replace(/(::|=>|->|<-|\|\|\.|\|\||\|\.)/g, '<span class="rg-op">$1</span>'); |
| 446 | // Numbers & byte units |
| 447 | html = html.replace(/\b(0x[0-9a-fA-F_]+|[0-9][0-9_]*(_KB|_MB|_GB)?(\.[0-9]+)?)\b/g, '<span class="rg-num">$1</span>'); |
| 448 | if (comPart) { |
| 449 | html += '<span class="rg-com">' + escapeHtml(comPart) + '</span>'; |
| 450 | } |
| 451 | return html; |
| 452 | }).join("\n"); |
| 453 | } |
| 454 | |
| 455 | function formatInline(text) { |
| 456 | let out = escapeHtml(text); |
| 457 | out = out.replace(/`([^`]+)`/g, "<code>$1</code>"); |
| 458 | out = out.replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>"); |
| 459 | out = out.replace(/\*([^*]+)\*/g, "<em>$1</em>"); |
| 460 | out = out.replace(/\$O\(([^)]+)\)\$/g, "<code>O($1)</code>"); |
| 461 | out = out.replace(/\$\\rightarrow\$/g, "→"); |
| 462 | out = out.replace(/\$1024\^2\$/g, "1024<sup>2</sup>"); |
| 463 | out = out.replace(/\$1024\^3\$/g, "1024<sup>3</sup>"); |
| 464 | out = out.replace(/\$1024\$/g, "1024"); |
| 465 | return out; |
| 466 | } |
| 467 | |
| 468 | function renderMarkdown(md) { |
| 469 | const lines = md.split("\n"); |
| 470 | let html = ""; |
| 471 | let i = 0; |
| 472 | while (i < lines.length) { |
| 473 | const line = lines[i]; |
| 474 | // Fenced code block |
| 475 | if (line.startsWith("```")) { |
| 476 | const lang = line.slice(3).trim() || "ridgun"; |
| 477 | i++; |
| 478 | const buf = []; |
| 479 | while (i < lines.length && !lines[i].startsWith("```")) { |
| 480 | buf.push(lines[i]); |
| 481 | i++; |
| 482 | } |
| 483 | i++; // skip closing ``` |
| 484 | const rawCode = buf.join("\n"); |
| 485 | const bodyHtml = (lang === "ridgun" || lang === "") ? highlightRidgun(rawCode) : escapeHtml(rawCode); |
| 486 | html += `<div class="code-wrapper"><div class="code-header"><span>${escapeHtml(lang)}</span><button class="copy-btn" onclick="copyCode(this)">${escapeHtml(UI_STRINGS.copy_label)}</button></div><pre data-raw="${ encodeURIComponent(rawCode) }"><code>${bodyHtml}</code></pre></div>`; |
| 487 | continue; |
| 488 | } |
| 489 | // Horizontal rule |
| 490 | if (/^---+$/.test(line.trim())) { |
| 491 | html += "<hr />"; |
| 492 | i++; |
| 493 | continue; |
| 494 | } |
| 495 | // Headings |
| 496 | if (line.startsWith("# ")) { |
| 497 | html += `<h1>${formatInline(line.slice(2).trim())}</h1>`; |
| 498 | i++; |
| 499 | continue; |
| 500 | } |
| 501 | if (line.startsWith("## ")) { |
| 502 | html += `<h2>${formatInline(line.slice(3).trim())}</h2>`; |
| 503 | i++; |
| 504 | continue; |
| 505 | } |
| 506 | if (line.startsWith("### ")) { |
| 507 | html += `<h3>${formatInline(line.slice(4).trim())}</h3>`; |
| 508 | i++; |
| 509 | continue; |
| 510 | } |
| 511 | // Table |
| 512 | if (line.trim().startsWith("|") && i + 1 < lines.length && /^\|[\s:-]+\|/.test(lines[i+1].trim())) { |
| 513 | const headers = line.trim().slice(1, -1).split("|").map(c => formatInline(c.trim())); |
| 514 | i += 2; |
| 515 | const rows = []; |
| 516 | while (i < lines.length && lines[i].trim().startsWith("|")) { |
| 517 | rows.push(lines[i].trim().slice(1, -1).split("|").map(c => formatInline(c.trim()))); |
| 518 | i++; |
| 519 | } |
| 520 | html += '<div class="table-wrap"><table><thead><tr>' + headers.map(h => `<th>${h}</th>`).join("") + '</tr></thead><tbody>' + |
| 521 | rows.map(r => '<tr>' + r.map(c => `<td>${c}</td>`).join("") + '</tr>').join("") + '</tbody></table></div>'; |
| 522 | continue; |
| 523 | } |
| 524 | // Blockquote |
| 525 | if (line.startsWith(">")) { |
| 526 | const qLines = []; |
| 527 | while (i < lines.length && lines[i].startsWith(">")) { |
| 528 | qLines.push(lines[i].replace(/^>\s?/, "")); |
| 529 | i++; |
| 530 | } |
| 531 | html += `<blockquote><p>${qLines.map(formatInline).join("<br/>")}</p></blockquote>`; |
| 532 | continue; |
| 533 | } |
| 534 | // Unordered list |
| 535 | if (/^\s*-\s+/.test(line)) { |
| 536 | const items = []; |
| 537 | while (i < lines.length && /^\s*-\s+/.test(lines[i])) { |
| 538 | items.push(formatInline(lines[i].replace(/^\s*-\s+/, ""))); |
| 539 | i++; |
| 540 | } |
| 541 | html += "<ul>" + items.map(it => `<li>${it}</li>`).join("") + "</ul>"; |
| 542 | continue; |
| 543 | } |
| 544 | // Ordered list |
| 545 | if (/^\s*\d+\.\s+/.test(line)) { |
| 546 | const items = []; |
| 547 | while (i < lines.length && /^\s*\d+\.\s+/.test(lines[i])) { |
| 548 | items.push(formatInline(lines[i].replace(/^\s*\d+\.\s+/, ""))); |
| 549 | i++; |
| 550 | } |
| 551 | html += "<ol>" + items.map(it => `<li>${it}</li>`).join("") + "</ol>"; |
| 552 | continue; |
| 553 | } |
| 554 | // Empty line |
| 555 | if (!line.trim()) { |
| 556 | i++; |
| 557 | continue; |
| 558 | } |
| 559 | // Paragraph |
| 560 | const pLines = []; |
| 561 | while (i < lines.length && lines[i].trim() && !lines[i].startsWith("#") && !lines[i].startsWith("```") && !lines[i].startsWith(">") && !lines[i].trim().startsWith("|") && !/^---+$/.test(lines[i].trim()) && !/^\s*(-\s+|\d+\.\s+)/.test(lines[i])) { |
| 562 | pLines.push(formatInline(lines[i])); |
| 563 | i++; |
| 564 | } |
| 565 | html += `<p>${pLines.join(" ")}</p>`; |
| 566 | } |
| 567 | return html; |
| 568 | } |
| 569 | |
| 570 | window.copyCode = function(btn) { |
| 571 | const pre = btn.closest(".code-wrapper").querySelector("pre"); |
| 572 | const raw = decodeURIComponent(pre.getAttribute("data-raw")); |
| 573 | navigator.clipboard.writeText(raw); |
| 574 | const old = btn.textContent; |
| 575 | btn.textContent = UI_STRINGS.copied_label; |
| 576 | setTimeout(() => { btn.textContent = old; }, 1400); |
| 577 | }; |
| 578 | |
| 579 | function renderSidebar() { |
| 580 | const nav = document.getElementById("navList"); |
| 581 | nav.innerHTML = CHAPTERS.map((ch, idx) => ` |
| 582 | <li class="nav-item"> |
| 583 | <button class="nav-btn ${idx === currentIdx ? 'active' : ''}" onclick="selectChapter(${idx})"> |
| 584 | <span class="nav-num">${ch.num}</span> |
| 585 | <span>${escapeHtml(ch.short_title)}</span> |
| 586 | </button> |
| 587 | </li> |
| 588 | `).join(""); |
| 589 | } |
| 590 | |
| 591 | window.selectChapter = function(idx) { |
| 592 | currentIdx = idx; |
| 593 | const ch = CHAPTERS[idx]; |
| 594 | location.hash = ch.slug; |
| 595 | renderSidebar(); |
| 596 | let pagerHtml = '<div class="pager">'; |
| 597 | if (idx > 0) { |
| 598 | pagerHtml += `<button class="pager-btn prev" onclick="selectChapter(${idx - 1})"><span class="pager-label">${UI_STRINGS.prev_label}</span><span class="pager-title">${escapeHtml(CHAPTERS[idx - 1].title)}</span></button>`; |
| 599 | } else { |
| 600 | pagerHtml += '<div></div>'; |
| 601 | } |
| 602 | if (idx + 1 < CHAPTERS.length) { |
| 603 | pagerHtml += `<button class="pager-btn next" onclick="selectChapter(${idx + 1})"><span class="pager-label">${UI_STRINGS.next_label}</span><span class="pager-title">${escapeHtml(CHAPTERS[idx + 1].title)}</span></button>`; |
| 604 | } |
| 605 | pagerHtml += '</div>'; |
| 606 | document.getElementById("chapterContent").innerHTML = renderMarkdown(ch.markdown) + pagerHtml; |
| 607 | window.scrollTo({ top: 0, behavior: "smooth" }); |
| 608 | }; |
| 609 | |
| 610 | document.getElementById("searchInput").addEventListener("input", (e) => { |
| 611 | const q = e.target.value.trim().toLowerCase(); |
| 612 | if (q.length < 2) { |
| 613 | selectChapter(currentIdx); |
| 614 | return; |
| 615 | } |
| 616 | const hits = []; |
| 617 | CHAPTERS.forEach((ch, idx) => { |
| 618 | const lines = ch.markdown.split("\n"); |
| 619 | for (const l of lines) { |
| 620 | if (l.toLowerCase().includes(q)) { |
| 621 | hits.push({ idx, title: ch.title, snippet: l.replace(/^[#>*-]+\s*/, "").slice(0, 140) }); |
| 622 | break; |
| 623 | } |
| 624 | } |
| 625 | }); |
| 626 | const box = hits.length |
| 627 | ? `<div class="search-results"><strong>${escapeHtml(UI_STRINGS.search_hits_label)} "${escapeHtml(q)}" (${hits.length}):</strong>` + |
| 628 | hits.map(h => `<div class="search-hit" onclick="document.getElementById('searchInput').value=''; selectChapter(${h.idx})"><div class="search-hit-title">${escapeHtml(h.title)}</div><div class="search-hit-snippet">${escapeHtml(h.snippet)}</div></div>`).join("") + |
| 629 | `</div>` |
| 630 | : `<div class="search-results">${escapeHtml(UI_STRINGS.search_empty_label)} "${escapeHtml(q)}".</div>`; |
| 631 | document.getElementById("chapterContent").innerHTML = box + renderMarkdown(CHAPTERS[currentIdx].markdown); |
| 632 | }); |
| 633 | |
| 634 | document.getElementById("themeBtn").addEventListener("click", () => { |
| 635 | const root = document.documentElement; |
| 636 | root.setAttribute("data-theme", root.getAttribute("data-theme") === "dark" ? "light" : "dark"); |
| 637 | }); |
| 638 | |
| 639 | // Initial load from URL hash if present |
| 640 | const initialSlug = location.hash.replace(/^#/, ""); |
| 641 | const foundIdx = CHAPTERS.findIndex(c => c.slug === initialSlug); |
| 642 | selectChapter(foundIdx >= 0 ? foundIdx : 0); |
| 643 | </script> |
| 644 | </body> |
| 645 | </html> |