Source guide/welcome.simd
1 2# Welcome to Silo 3 4Silo is Forth blended with Rust, with a :gloss[dependently typed](./A1-glossary.simd#dependent-type) 5core quietly keeping you honest. The surface is 6:gloss[concatenative](./A1-glossary.simd#concatenative) — you push values 7onto a :gloss[stack](./A1-glossary.simd#stack) and chain small 8**:gloss[words](./A1-glossary.simd#word)** (the Forth term for a function) 9into pipelines — but the type system, 10:gloss[trait](./A1-glossary.simd#trait) system, pattern matcher, and 11:gloss[algebraic effects](./A1-glossary.simd#algebraic-effect) will feel 12familiar to anyone who's written Rust. 13 14The dependent types are there to catch the sort of mistake that's 15annoying to find at runtime: off-by-one on an array, mixing seconds and 16metres, a time zone attached to the wrong calendar. You don't have to 17reach for them, but they're there, and the standard library uses them 18whenever it buys you a real guarantee. 19 20If "dependently typed" makes you nervous, don't let it. You will not be 21writing proofs. You write ordinary code, and sometimes a function 22signature says `(Vec a n)` instead of `(Vec a)` to record that the 23length is known. That's most of it. 24 25## What's distinctive 26 27A few guarantees Silo's type system gives you that are worth 28knowing up front, because they shape the shape of the standard 29library: 30 31- **Nothing can panic without declaring `+Panic`.** If a word's 32 signature doesn't list `+Panic`, it cannot call `panic`, 33 cannot trigger an unwrap-on-`None`, cannot divide by zero 34 without handling it. The effect is as visible as I/O. 35- **Nothing can loop forever without declaring `+Div`.** Silo 36 is total by default. Non-termination is opt-in and 37 signature-visible. 38- **Nothing can touch the outside world without a specific 39 effect.** `+Console`, `+FileSystem`, `+Net`, `+Temporal`, 40 etc. A pure word cannot surprise you by quietly reading a 41 file. 42- **Async and threads are effects, not a parallel dialect.** 43 The `+Concurrent` and `+Executor` effects compose with every 44 other effect. A pure word can be called freely from a task, 45 a thread, or synchronous code — there are no "function 46 colors" forcing an `async` split. 47- **Locality modes let the type system enforce resource 48 discipline.** The default mode is an ordinary shareable 49 value; `local`, `unique`, and `linear` modes opt into 50 can't-escape, no-aliasing, and must-be-consumed semantics 51 when a resource calls for them. 52- **No lifetime system.** The work that Rust does with 53 lifetime parameters is handled here by the modes above — 54 simpler at the surface, with most of the same soundness 55 guarantees on the resource side. 56- **Dependent types track real invariants.** Lengths, index 57 ranges, unit tags — the things that normally become runtime 58 bugs. 59- **Everything you can do at compile time, you can do at the 60 REPL.** Define traits, implement them, declare types, run 61 macros, inspect `:type-info` — the REPL runs the same 62 frontend the batch compiler does. No separate "runtime" 63 dialect with a smaller feature set. 64 65Each of these is elaborated in its own chapter; they're listed 66together here because taken as a set they're what the language 67actually feels like to work with. 68 69## The layers underneath 70 71Silo runs on a :gloss[host](./A1-glossary.simd#host). The language is 72deliberately **:gloss[sans-IO](./A1-glossary.simd#sans-io)**: the compiler 73and the abstract machine never touch the disk or the network on their 74own. Every side effect goes through a typed 75**:gloss[effect handler](./A1-glossary.simd#effect-handler)** supplied by 76whatever is embedding Silo — usually a Rust host. 77 78A command-line host publishes `+Console`, `+FileSystem`, `+Env`. A 79browser host might publish `+Http`, `+DOM`, `+Storage`. An embedded 80host on a microcontroller might publish `+GPIO` and `+SPI` and nothing 81else. The same Silo code can run under any of them, as long as the 82effects it declares are ones the host knows how to handle. 83 84## Reading this handbook 85 86Chapters are cumulative: each assumes the ones before it. The order is 87roughly "syntax you meet in the first ten minutes" first, then the type 88system, then the standard library, then the features you reach for once 89you're building something real. 90 91If you already know Forth, skim [chapter 2](./02-stack-and-words.simd) 92and go straight to [the type system](./06-types.simd) and 93[traits](./09-traits.simd). If you know Rust but have never pushed a 94value onto a stack, the reverse — chapter 2 is where to slow down. 95 96## A first taste 97 98Here is a complete, typechecked Silo function. It sums the squares of 99the integers from 1 up to `n`: 100 101```silo 102:fn sum-of-squares ( Int -> Int ) 103 pop-> n 104 0..n 0 [ pop-> acc pop-> i 105 i 1 + pop-> k 106 acc k k * + 107 ] .fold 108:end 109``` 110 111A few things worth noticing even before any explanation: 112 113- `( Int -> Int )` is the **:gloss[stack effect](./A1-glossary.simd#stack-effect)**. 114 It plays the role of a type signature: this word pops one `Int` and 115 pushes one `Int`. 116- `pop->` binds the top of the stack to a name. Silo is stack-based, 117 but you rarely juggle values — you name whatever you want to reuse. 118 There is also `peek->`, which copies instead of popping. 119- There is no `return` keyword. Whatever is on the stack when the word 120 finishes *is* the return value — that's the normal case. If you need 121 to bail out from a nested block, `:ret` exits the enclosing word 122 immediately with whatever's on the stack at that point. 123- `[ ... ]` is a **:gloss[quotation](./A1-glossary.simd#quotation)** — a 124 first-class block of code with captured bindings. If you know Rust, 125 think of it as a :gloss[closure](./A1-glossary.simd#closure); if you know 126 ML or Haskell, a lambda. `.fold` is an ordinary method that takes 127 one of these. 128 129## Traits are how you abstract 130 131Most of Silo's machinery for polymorphism goes through **traits**, just 132like Rust. Arithmetic operators are trait methods (`+` calls `.add`, 133`=` calls `.eq`, and so on). Iteration, formatting, comparison, 134hashing, conversion — all traits. There is no orphan rule: any package 135can implement any trait on any type, with imports controlling which 136impls are in scope. 137 138You will see traits introduced in [chapter 9](./09-traits.simd) and 139reappearing in almost every chapter after it. 140 141## What Silo is for 142 143Silo is designed for the kind of code where cutting a class of bugs 144early saves a great deal of work later: long-running services, 145simulations, anything that touches a calendar or a locale, anything 146with non-trivial concurrency. The dependent types give you index-safe 147collections and unit-safe arithmetic. The effect system makes it easy 148to be precise about what code actually needs the filesystem or the 149network or the current time. 150 151Silo is not a scripting language and it is not a toy. It is a serious 152attempt to let types and effects carry real structural weight without 153making the everyday code ceremonial. 154 155## Before you continue 156 157You do not need to have installed anything to read this handbook. 158Every chapter has complete, typechecked examples you can read as you 159go. When you're ready to run code, the project `README.md` at the repo 160root describes how to build the CLI and the REPL. 161 162The rest of the book assumes you've met the stack and the word. 163[Chapter 2](./02-stack-and-words.simd) makes that introduction.