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.