Showcase
These are curated, idiomatic E# programs — the "this is what good E# looks like" tier, written to be read top to bottom with extensive inline commentary. Unlike the rest of the corpus (lifted and re-verified from the test suite), each of these is a standalone program verified through the compiler. Read them in order; they build from the memory model up to a complete recursive-descent calculator.
Value vs. shared — the heart of E#'s memory model, and what `new` is for.
// E# — a verified example from the E# language corpus (CLR language; .es, not ECMAScript).
// provenance: pointers_and_sharing.es topic: pointers status: verified
// hand-authored, idiomatic E# — verified through the E# compiler
namespace Demo
// ═════════════════════════════════════════════════════════════════════════════
// Value vs. shared — the heart of E#'s memory model, and what `new` is for.
//
// A `data` type is a VALUE, like an int. Assigning it COPIES; two variables holding a
// `data` never affect each other. That is the default, and it is usually what you
// want — no spooky action at a distance.
//
// Sometimes you need the opposite: several places that read and write ONE shared
// piece of state (a counter threaded through a computation, a node in a linked
// structure). For that you put the `data` on the heap with `new`, which yields a
// POINTER, written `*T`. Everyone holding the `*T` sees the same mutations.
//
// `new Counter { ... }` → allocate on the heap, hand back a `*Counter`
// `c: *Counter` → a pointer; `c.total` reads/writes the shared cell
// `let alias = c` → copies the POINTER, not the counter — same object
//
// `new` is exactly "put this value on the heap and give me a pointer to it". It is
// the one allocation expression in the language and the only way to mint a fresh `*T`.
// ═════════════════════════════════════════════════════════════════════════════
// A plain value `data`: a running tally. No `init` block — value types are built with
// a composite literal that names each field (`Counter { total: 0, steps: 0 }`).
data Counter {
var total: int
var steps: int
}
// `bump` takes a POINTER (`*Counter`), so it mutates the caller's counter in place.
// A pointer parameter stays a free function (only a direct-value receiver like
// `func f(c: Counter)` would become the method `c.f()`).
func bump(c: *Counter, amount: int) {
c.total += amount
c.steps += 1
}
// Had this taken a value `Counter` instead of `*Counter`, `add` would receive its own
// COPY and the caller would never see the change. The pointer is what makes the
// sharing real.
// Optional: You can annotate return type as void if you prefer visibility.
func addAll(c: *Counter, xs: List<int>) -> void {
for x in xs {
bump(c, x)
}
}
func main() -> int {
// `new` allocates the counter on the heap and returns a *Counter. `tally` and
// `alias` are then two NAMES for the SAME heap counter.
var tally: *Counter = new Counter { total: 0, steps: 0 }
let alias = tally
let xs = List<int>()
xs.Add(5)
xs.Add(7)
xs.Add(3)
addAll(tally, xs) // through the pointer: total = 15, steps = 3
bump(alias, 100) // through the OTHER name — same object: total = 115, steps = 4
// The writes via `alias` are visible through `tally` — both point at one heap cell.
// Read the shared fields back through the pointer (auto-deref): total = 115, steps = 4.
return tally.total + tally.steps // 119
}
raw source ↓ /raw/authored/pointers_and_sharing.es
E#'s defining move: behavior lives in FREE FUNCTIONS, but a free function whose
// E# — a verified example from the E# language corpus (CLR language; .es, not ECMAScript).
// provenance: promotion_and_match.es topic: choice status: verified
// hand-authored, idiomatic E# — verified through the E# compiler
namespace Demo
// ═════════════════════════════════════════════════════════════════════════════
// E#'s defining move: behavior lives in FREE FUNCTIONS, but a free function whose
// first parameter is a value `data` is PROMOTED to a method on that type. You write
// plain procedural code; you get to call it object-style — including chaining.
//
// func add(v: Vec, o: Vec) -> Vec is the method Vec.add → v.add(o)
//
// The free-call spelling `add(v, o)` is then a hard error (the compiler points you at
// `v.add(o)`). The method travels with its receiver type, so it is reachable wherever
// `Vec` is, regardless of which file declared the function.
//
// This file pairs that with the other half of E#'s type story — a `choice` (a closed
// set of shapes) consumed by `match` (exhaustive pattern dispatch). A `choice` is NOT
// a `data`, so functions over it are ordinary free functions, never promoted.
// ═════════════════════════════════════════════════════════════════════════════
// A 2-D vector. A `data` is value-semantic: copying it copies the fields, and a
// function that returns a new `Vec` never disturbs its input.
data Vec {
x: int
y: int
}
// Each of these has `Vec` as its first parameter, so each is promoted onto `Vec`.
// Call them `a.add(b)`, `a.scaled(2)`, `a.dot(b)` — never `add(a, b)`.
func add(v: Vec, o: Vec) -> Vec {
return Vec { x: v.x + o.x, y: v.y + o.y }
}
func scaled(v: Vec, k: int) -> Vec {
return Vec { x: v.x * k, y: v.y * k }
}
func dot(v: Vec, o: Vec) -> int {
return v.x * o.x + v.y * o.y
}
// Because `add` and `scaled` return a `Vec`, promoted calls CHAIN: each result is a
// fresh value you can call the next method on. No mutation, no aliasing — just values
// flowing through transformations.
func combine(a: Vec, b: Vec) -> Vec {
return a.add(b).scaled(2)
}
// The other half of the type story: a sum type. Each variant may carry payload fields.
choice Shape {
point // no payload
segment(length: int) // one payload
box(w: int, h: int) // two payloads
}
// `Shape` is a `choice`, not a `data`, so this is a plain free function — call it
// `area(s)`. `match` must cover every variant (the compiler warns otherwise); each
// arm binds that variant's payloads positionally.
func area(s: Shape) -> int {
match s {
.point { return 0 }
.segment(len) { return 0 } // a 1-D segment has no area
.box(w, h) { return w * h }
}
return 0
}
func main() -> int {
let a = Vec { x: 1, y: 2 }
let b = Vec { x: 3, y: 4 }
let c = a.combine(b) // (a + b) then *2 → Vec { x: 8, y: 12 } — promoted, so `a.combine(b)`
let d = a.dot(b) // 1*3 + 2*4 = 11
// Construct a choice value with its factory, then fold it with `match`.
let boxArea = area(Shape.box(3, 5)) // 15
return c.x + c.y + d + boxArea // 8 + 12 + 11 + 15 = 46
}
raw source ↓ /raw/authored/promotion_and_match.es
Money done right: a fixed-point amount in integer cents, never a float.
// E# — a verified example from the E# language corpus (CLR language; .es, not ECMAScript).
// provenance: money.es topic: result status: verified
// hand-authored, idiomatic E# — verified through the E# compiler
namespace Demo
// ═════════════════════════════════════════════════════════════════════════════
// Money done right: a fixed-point amount in integer cents, never a float.
//
// Money is the textbook case for value semantics. An amount has no identity — two
// $5.00 bills are interchangeable — and you never want one assignment to mutate
// another ledger entry by surprise. So `Money` is a `data`: copied on assignment,
// equal by its field, no shared mutation. And it's stored as `cents: int`, because
// binary floating point cannot represent 0.10 exactly and money math must be exact.
//
// Every operation is a free function whose first parameter is `Money`, so by
// promotion it reads as a method on the value — `a.plus(b)`, `price.times(3)`,
// `total.format()` — and because each returns a fresh `Money` (or a `Result`), the
// calls chain without ever mutating the input. Division can fail (zero divisor), so
// it returns `Result<Money, string>` and the `?` operator threads the failure.
// ═════════════════════════════════════════════════════════════════════════════
// A value amount. One field, integer cents. No constructor — value `data` is built
// with a composite literal; a factory gives a readable surface.
data Money {
cents: int
}
// Factories. `dollars(5)` → $5.00; `of(12, 34)` → $12.34.
func dollars(d: int) -> Money = Money { cents: d * 100 }
func of(d: int, c: int) -> Money = Money { cents: d * 100 + c }
// --- promoted arithmetic (first param `Money` ⇒ method on `Money`) ----------------
// Each returns a new value; the receiver is never touched.
func plus(a: Money, b: Money) -> Money = Money { cents: a.cents + b.cents }
func minus(a: Money, b: Money) -> Money = Money { cents: a.cents - b.cents }
func times(a: Money, factor: int) -> Money = Money { cents: a.cents * factor }
func isNegative(a: Money) -> bool = a.cents < 0
// Splitting a bill N ways can fail (N <= 0), so it speaks `Result`. Integer division
// floors, so the remainder cents are handed back too — no money is silently lost.
func splitEvenly(a: Money, ways: int) -> Result<Money, string> {
if ways <= 0 {
return error("cannot split into {ways} shares")
}
return ok(Money { cents: a.cents / ways })
}
// Render as "$D.CC", padding the cents and handling a negative amount cleanly.
func format(a: Money) -> string {
let neg = a.cents < 0
let abs = neg ? 0 - a.cents : a.cents
let d = abs / 100
let c = abs % 100
let cc = c < 10 ? "0{c}" : "{c}"
let sign = neg ? "-" : ""
return "{sign}${d}.{cc}"
}
// A small end-to-end calculation: three items, a discount, split two ways.
// The `?` after splitEvenly unwraps the ok value or returns the error from here.
func checkout() -> Result<string, string> {
let apple = of(0, 99) // $0.99
let bread = of(2, 49) // $2.49
let coffee = dollars(8) // $8.00
let subtotal = apple.plus(bread).plus(coffee) // chained, no mutation: $11.48
let discount = of(1, 48) // $1.48 off
let total = subtotal.minus(discount) // $10.00
let perPerson = total.splitEvenly(2)? // $5.00, or propagate the error
return ok("total {total.format()}, each {perPerson.format()}")
}
func main() -> string {
let r = checkout()
return r.IsOk ? r.Value : "error: {r.Error}" // "total $10.00, each $5.00"
}
raw source ↓ /raw/authored/money.es
E#'s object side: interfaces, the two kinds of type that satisfy them, methods that
// E# — a verified example from the E# language corpus (CLR language; .es, not ECMAScript).
// provenance: interfaces_and_static.es topic: static-func status: verified
// hand-authored, idiomatic E# — verified through the E# compiler
namespace Demo
// ═════════════════════════════════════════════════════════════════════════════
// E#'s object side: interfaces, the two kinds of type that satisfy them, methods that
// live inside a `ref data` body, and a `static func` static class.
//
// An `interface` is nominal: a type satisfies it only by NAMING it after `:` — there is
// no structural auto-matching. Both kinds of user type can conform:
//
// • a value `data` conforms by PROMOTION — a free `func` whose first parameter is the
// data type becomes the interface method. (Storing a value type behind an interface
// boxes it; the compiler warns. Use `ref data` when you'll pass it as the interface a
// lot.)
// • a `ref data` conforms with methods written INSIDE its body (they get an implicit
// `self`), and constructs via an `init` block.
//
// A `static func Name { ... }` is a static class: a bag of constants and stateless
// functions, called `Name.member(...)`.
// ═════════════════════════════════════════════════════════════════════════════
// The contract. By .NET convention interface names start with `I`.
interface IArea {
func area() -> int
}
// A value `data` conforming via promotion. `func area(r: Rect)` has `Rect` as its first
// parameter, so it IS `Rect.area()` — and that satisfies `IArea`. (Passing a `Rect` where
// an `IArea` is expected boxes the struct; fine here, the compiler just notes it.)
data Rect : IArea {
w: int
h: int
}
func area(r: Rect) -> int {
return r.w * r.h
}
// A `ref data` conforming with an in-body method. It has identity, an `init` constructor,
// and `self` inside its methods.
ref data Disk : IArea {
radius: int
init(r: int) {
self.radius = r
}
// Methods inside a `ref data` body read/write fields through `self`. This one
// satisfies `IArea.area()`. (Rough integer area, π ≈ 3.)
func area() -> int {
return 3 * self.radius * self.radius
}
}
// Dispatch through the interface: `describe` neither knows nor cares whether it holds a
// `Rect` or a `Disk` — it calls `area()` virtually. This is the one place E# reaches for
// the object world on purpose.
func describe(s: IArea) -> int {
return s.area()
}
// A `static func` static class: constants + stateless helpers, reached as `Geo.member`.
static func Geo {
const UNIT = 1
func unitSquare() -> Rect {
return Rect { w: UNIT, h: UNIT }
}
func biggest(a: int, b: int) -> int {
return a > b ? a : b
}
}
func main() -> int {
let r = Rect { w: 3, h: 4 } // value type
let d = Disk(5) // ref data via init
let viaInterface = describe(r) + describe(d) // 12 + 75 = 87 (both as IArea)
let unit = Geo.unitSquare().area() // 1 (static class → promoted method)
let pick = Geo.biggest(viaInterface, 100) // 100
return viaInterface + unit + pick // 87 + 1 + 100 = 188
}
raw source ↓ /raw/authored/interfaces_and_static.es
Passing behavior as a value: E# has three callable forms, chosen by intent.
// E# — a verified example from the E# language corpus (CLR language; .es, not ECMAScript).
// provenance: delegates_and_pointers.es topic: delegates-events status: verified
// hand-authored, idiomatic E# — verified through the E# compiler
namespace Demo
// ═════════════════════════════════════════════════════════════════════════════
// Passing behavior as a value: E# has three callable forms, chosen by intent.
//
// 1. Function pointer — `&func`, type `&(int, int -> int)`. Zero allocation, no GC:
// `ldftn` + `calli`. The systems tier — hot paths, dispatch tables. (C# needs
// `unsafe` + `delegate*` for this; E# makes it safe by construction.)
// 2. Nominal delegate — `delegate func Name(...)`. A named `MulticastDelegate` type,
// distinct from any structurally-identical delegate. Intent-named, interop-friendly.
// 3. BCL delegate — `Func<...>` / `Action<...>`. Structural, heap, multicast. The
// framework-callback tier.
//
// A bare function name converts to whichever delegate type is expected (method-group
// conversion), and a lambda's parameter types are inferred from the target.
// ═════════════════════════════════════════════════════════════════════════════
// (2) A NOMINAL delegate type. `BinOp` is its own type — a `Func<int,int,int>` is NOT a
// `BinOp`, even though both wrap (int, int) -> int.
delegate func BinOp(a: int, b: int) -> int
func add(a: int, b: int) -> int = a + b
func mul(a: int, b: int) -> int = a * b
// Parameter typed as the nominal delegate. A bare `add` passed here converts (method group).
func apply(op: BinOp, a: int, b: int) -> int = op(a, b)
// Parameter typed as a BCL `Func`. A lambda converts, its `x` inferred as int.
func applyFunc(f: Func<int, int>, x: int) -> int = f(x)
// Parameter typed as a function POINTER. `&name` takes the address; the call is a `calli`,
// with no delegate object allocated.
func applyPtr(f: &(int, int -> int), a: int, b: int) -> int = f(a, b)
func main() -> int {
let viaDelegate = apply(add, 3, 4) // 7 — method group → nominal delegate
let viaLambda = applyFunc((x) => x * 2, 10) // 20 — lambda → Func<int,int>
let viaPointer = applyPtr(&mul, 5, 6) // 30 — &mul → ldftn + calli, zero alloc
return viaDelegate + viaLambda + viaPointer // 57
}
raw source ↓ /raw/authored/delegates_and_pointers.es
Events — a controlled subscription point over a delegate. The delegate is the payload;
// E# — a verified example from the E# language corpus (CLR language; .es, not ECMAScript).
// provenance: events.es topic: delegates-events status: verified
// hand-authored, idiomatic E# — verified through the E# compiler
namespace Demo
// ═════════════════════════════════════════════════════════════════════════════
// Events — a controlled subscription point over a delegate. The delegate is the payload;
// the event only governs who may subscribe (`+=`) and unsubscribe (`-=`). Outside code
// can't invoke or replace it. Events are declared on `ref data` (they imply identity),
// fired with the null-safe `raise` statement, and emit exactly what C# emits for
// `public event Action<int> OnChanged;` — so a C# consumer subscribes with `+=` unchanged.
// ═════════════════════════════════════════════════════════════════════════════
// A counter that announces every change. `event OnChanged: Action<int>` declares the
// subscription point, typed by the `Action<int>` delegate.
ref data Counter {
var total: int
event OnChanged: Action<int>
init() {
self.total = 0
}
func add(n: int) {
self.total = self.total + n
// `raise` captures the handler list then invokes it — a no-op when there are no
// subscribers, and safe against a handler unsubscribing mid-raise.
raise OnChanged(self.total)
}
}
func main() -> int {
var lastSeen = 0 // mutable local, captured by the handler below
let c = Counter()
// Subscribe a lambda whose shape matches the event's Action<int>. Closures capture
// outer `var`s mutably, so each raise writes the new total back into `lastSeen`.
c.OnChanged += func(v: int) -> void {
lastSeen = v
}
c.add(5) // total 5 → OnChanged(5) → lastSeen = 5
c.add(3) // total 8 → OnChanged(8) → lastSeen = 8
return lastSeen // 8 — proof the event fired and the handler ran
}
raw source ↓ /raw/authored/events.es
A turtle you drive with a CHAIN of commands — the fluent-builder pattern, and the
// E# — a verified example from the E# language corpus (CLR language; .es, not ECMAScript).
// provenance: turtle.es topic: choice status: verified
// hand-authored, idiomatic E# — verified through the E# compiler
namespace Demo
// ═════════════════════════════════════════════════════════════════════════════
// A turtle you drive with a CHAIN of commands — the fluent-builder pattern, and the
// reason it works.
//
// The turtle is a `ref data`: it has identity and evolving state (position + heading).
// Each command is applied by `apply`, which mutates the turtle and then **returns the
// turtle itself**. Because a `ref data` is a reference, returning it hands back the SAME
// object — so `apply` can be chained, and you never re-name the receiver:
//
// Turtle().apply(...).apply(...).apply(...)
//
// That return-`self` move is the whole trick behind fluent APIs (`StringBuilder`,
// LINQ, query builders). Contrast it with a method that returns a `Result` or a fresh
// value: those don't chain, because the next call would land on the wrong type.
//
// The commands themselves show the other half of the language: a `choice` whose
// `forward` case carries a step count and whose `turn` case carries an `enum`
// direction, dispatched with `match`. One `apply`, two payload shapes, no `if`-ladder.
// ═════════════════════════════════════════════════════════════════════════════
// Which way to pivot. A plain `enum` — a closed set of named constants.
enum Turn {
left
right
}
// What the turtle can be told to do. A `choice`: `forward` carries how far, `turn`
// carries which way (the `Turn` enum). `match` in `apply` handles both.
choice Command {
forward(steps: int)
turn(direction: Turn)
}
// The turtle. `ref data` = identity + mutable state; heading is 0=N, 1=E, 2=S, 3=W,
// so a right turn is +1 (mod 4) and a left turn is +3 (mod 4).
ref data Turtle {
var x: int
var y: int
var facing: int
init() {
self.x = 0
self.y = 0
self.facing = 0 // start facing North
}
}
// Apply one command and RETURN THE TURTLE — that return-self is what makes `apply`
// chainable. `match` dispatches the command; `forward` walks in the current heading,
// `turn` rotates. The nested `match (direction: Turn)` folds the enum to a delta.
func apply(t: Turtle, cmd: Command) -> Turtle {
match cmd {
.forward(steps) {
if t.facing == 0 { t.y += steps } // North
else if t.facing == 1 { t.x += steps } // East
else if t.facing == 2 { t.y -= steps } // South
else { t.x -= steps } // West
}
.turn(direction) {
match (direction: Turn) {
.left { t.facing = (t.facing + 3) % 4 }
.right { t.facing = (t.facing + 1) % 4 }
}
}
}
return t // the SAME turtle — the chain continues on it
}
// Drive the turtle with a single fluent chain — no intermediate `t` rebinding, just
// commands flowing through the one object:
//
// start (0,0) facing N
// forward 5 → (0,5) turn right → facing E
// forward 3 → (3,5) turn right → facing S
// forward 2 → (3,3)
//
// Final position (3, 3) → encoded as x*100 + y = 303.
func main() -> int {
let t = Turtle()
.apply(Command.forward(5))
.apply(Command.turn(Turn.right()))
.apply(Command.forward(3))
.apply(Command.turn(Turn.right()))
.apply(Command.forward(2))
return t.x * 100 + t.y // 303
}
raw source ↓ /raw/authored/turtle.es
A vending machine — a small stateful protocol, and the one place E# reaches for
// E# — a verified example from the E# language corpus (CLR language; .es, not ECMAScript).
// provenance: vending.es topic: choice status: verified
// hand-authored, idiomatic E# — verified through the E# compiler
namespace Demo
// ═════════════════════════════════════════════════════════════════════════════
// A vending machine — a small stateful protocol, and the one place E# reaches for
// the object world on purpose.
//
// The machine HAS IDENTITY: there is one of it, money accumulates in it, stock
// depletes from it, and every command acts on that same evolving thing. That is the
// definition of `ref data` — a class with reference semantics — as opposed to the
// value `data` used elsewhere in this corpus. Commands arrive as a `choice` (insert a
// coin, buy, cancel) and are dispatched with `match`. Coins are an `enum` with
// explicit denominations, decoded by a second `match`. Anything the user can get
// wrong (too little credit, sold out) is a `Result`, so the caller always gets a
// clear outcome instead of a silent failure.
// ═════════════════════════════════════════════════════════════════════════════
// Coin denominations, in cents. An `enum` emits as a real CLR enum; the explicit
// values are the actual coin worth.
enum Coin {
nickel = 5
dime = 10
quarter = 25
}
// Decode a coin to its cent value. `match` over an enum needs the type named so the
// `.nickel` shorthand resolves to `Coin`.
func cents(c: Coin) -> int {
match (c: Coin) {
.nickel { return 5 }
.dime { return 10 }
.quarter { return 25 }
}
return 0
}
// The three things a customer can do. A `choice`: `insert` carries which coin; the
// others carry nothing.
choice Command {
insert(coin: Coin)
buy
cancel
}
// The machine itself — a `ref data`, because it has identity and evolving state.
// `var` fields mutate in place; `price` is fixed at construction.
ref data Machine {
var credit: int
var stock: int
let price: int
init(stock: int, price: int) {
self.credit = 0
self.stock = stock
self.price = price
}
}
// Apply one command to the machine, mutating it and reporting the outcome. Promoted
// onto `Machine` (first parameter), so the caller writes `machine.apply(cmd)`. Each
// arm reads/writes the shared state through the reference — the changes persist
// across calls because a `ref data` is one object, not a copy.
func apply(m: Machine, cmd: Command) -> Result<string, string> {
match cmd {
.insert(coin) {
m.credit += cents(coin) // coin IS the Coin (transparent view)
return ok("credit: {m.credit}c")
}
.buy {
if m.stock == 0 {
return error("sold out")
}
if m.credit < m.price {
return error("need {m.price - m.credit}c more")
}
let change = m.credit - m.price
m.credit = 0 // bank the price, return the rest
m.stock -= 1
return ok("dispensed — change {change}c, {m.stock} left")
}
.cancel {
let refund = m.credit
m.credit = 0
return ok("refunded {refund}c")
}
}
}
// A short session against ONE machine: the mutations accumulate because `m` is a
// single identity-bearing object, not re-copied each call. Two quarters + a dime is
// 60c against a 50c price → dispensed with 10c change.
// The application is itself a `ref data` — `Program` OWNS the machine and drives the
// session in `main`. A `main` method on a `ref data Program` IS the program's entry
// point (the class-style alternative to a bare top-level `func main`); the compiler
// constructs the program (`Program()`) and calls `.main()`, so no launcher is needed.
ref data Program {
func main() -> string {
let m = Machine(3, 50) // 3 items, 50c each
m.apply(Command.insert(Coin.quarter())) // credit 25
m.apply(Command.insert(Coin.quarter())) // credit 50
m.apply(Command.insert(Coin.dime())) // credit 60
let result = m.apply(Command.buy()) // dispense, 10c change, 2 left
return result.IsOk ? result.Value : "error: {result.Error}"
}
}
raw source ↓ /raw/authored/vending.es
Counting word frequencies — a tour of BCL interop, which is the soul of E#.
// E# — a verified example from the E# language corpus (CLR language; .es, not ECMAScript).
// provenance: wordcount.es topic: interop status: verified
// hand-authored, idiomatic E# — verified through the E# compiler
namespace Demo
using "System.Collections.Generic" // Dictionary<K, V>
// ═════════════════════════════════════════════════════════════════════════════
// Counting word frequencies — a tour of BCL interop, which is the soul of E#.
//
// There is no bespoke E# hash map: you reach straight for `Dictionary<string, int>`
// from the .NET base class library and call it directly — `ContainsKey`, the `[key]`
// indexer for get and set, `Count`, `TryGetValue` with an `out` parameter. E# adds no
// wrapper; a `Dictionary` here is the same `Dictionary` a C# caller would hand you.
// `string.Split`, `.ToLower()`, and `.Length` are likewise just the BCL string API.
//
// The program reads a sentence, tallies each word, then finds the most frequent one
// — a single pass to count, a single pass to pick the winner. `out` is the idiomatic
// BCL "return a bool and a value" shape, and E# speaks it natively (`out var n`).
// ═════════════════════════════════════════════════════════════════════════════
// Tally how many times each (lower-cased) word appears. Returns the populated map.
func tally(text: string) -> Dictionary<string, int> {
let counts = Dictionary<string, int>()
let words = text.ToLower().Split(' ')
var i = 0
while i < words.Length {
let w = words[i]
if w.Length > 0 {
// get-or-zero then store back: the indexer reads and writes the same cell.
if counts.ContainsKey(w) {
counts[w] = counts[w] + 1
} else {
counts[w] = 1
}
}
i += 1
}
return counts
}
// How many times one word occurs, using the BCL `TryGetValue(key, out value)` pattern.
// `out n` binds a fresh local the call fills; reading `n` afterward is the count (or 0
// when the word is absent and the call returned false).
func frequency(counts: Dictionary<string, int>, word: string) -> int {
if counts.TryGetValue(word, out var n) {
return n
}
return 0
}
// Walk the entries to find the highest count. `for (k, v) in dict` destructures each
// KeyValuePair into its key and value — tuple-style iteration over a BCL collection.
func mostFrequentCount(counts: Dictionary<string, int>) -> int {
var best = 0
for (word, n) in counts {
if n > best {
best = n
}
}
return best
}
// "the cat sat on the mat the cat ran" — "the" appears 3×, "cat" 2×, rest once.
// frequency("the") is 3; the single most-frequent count is also 3. 3 + 3 = 6.
//
// The driver is a `main` method on a `ref data Program` — the class-style program. That
// method IS the entry point; the compiler constructs the program (`Program()`) and calls
// `.main()`, so no separate launcher function is needed.
ref data Program {
func main() -> int {
let counts = tally("the cat sat on the mat the cat ran")
return frequency(counts, "the") + mostFrequentCount(counts)
}
}
raw source ↓ /raw/authored/wordcount.es
Two flavors of recursion, and a thing E# does that C# can't.
// E# — a verified example from the E# language corpus (CLR language; .es, not ECMAScript).
// provenance: linked_list_and_tail.es topic: pointers status: verified
// hand-authored, idiomatic E# — verified through the E# compiler
namespace Demo
// ═════════════════════════════════════════════════════════════════════════════
// Two flavors of recursion, and a thing E# does that C# can't.
//
// 1. Structural recursion over a heap-linked list. A value `data` can't contain itself
// by value (that would be infinitely large — a hard error), so the `next` link is a
// pointer, `*Node`. `new Node { ... }` allocates a node on the heap and yields a
// `*Node`; `nil` ends the list.
//
// 2. Tail recursion. When a recursive call is the LAST thing a function does
// (`return f(...)`), E# emits the CLR `tail.` prefix — the frame is REUSED, not
// stacked — and GUARANTEES it, so an accumulator loop written as recursion runs in
// constant stack however deep. (Roslyn emits `tail.` only opportunistically and gives
// C# no language-level control or guarantee, so you can't rely on TCO there; E#, like
// F#, makes it a guarantee.)
// ═════════════════════════════════════════════════════════════════════════════
// The self-reference is a pointer — `next: Node` would be ES2002 (infinite-size value).
data Node {
value: int
next: *Node
}
// Structural recursion: this node's value plus the sum of the rest. NOT a tail call (the
// addition happens after the recursive call returns) — and that's fine for a short list.
func sumList(n: *Node) -> int {
if n == nil {
return 0
}
return n.value + sumList(n.next)
}
// Tail recursion: the recursive call is in tail position, so it compiles to a guaranteed
// CLR tail call. At large `n` a non-TCO'd version risks a StackOverflow; here it's flat.
func sumTo(n: int, acc: int) -> int {
if n <= 0 {
return acc
}
return sumTo(n - 1, acc + n)
}
func main() -> int {
// Build 1 -> 2 -> 3 on the heap, tail first so each node can point at the next.
let third = new Node { value: 3, next: nil }
let second = new Node { value: 2, next: third }
let first = new Node { value: 1, next: second }
return sumList(first) + sumTo(100, 0) // 6 + 5050 = 5056
}
raw source ↓ /raw/authored/linked_list_and_tail.es
A JSON value, modeled and serialized. The shape of JSON is a recursive sum type —
// E# — a verified example from the E# language corpus (CLR language; .es, not ECMAScript).
// provenance: json.es topic: choice status: verified
// hand-authored, idiomatic E# — verified through the E# compiler
namespace Demo
using "System.Text" // StringBuilder
// ═════════════════════════════════════════════════════════════════════════════
// A JSON value, modeled and serialized. The shape of JSON is a recursive sum type —
// a value is null, a bool, a number, a string, an array OF values, or an object whose
// fields hold values — so it is a `ref choice`: an identity-carrying tagged union whose
// cases can recurse through each other (an array holds a `List<Json>`, and so on).
//
// `stringify` is the whole point: one `match` over the six cases, each arm building its
// own text, the array/object arms recursing back into `stringify`. This is the canonical
// "interpreter over an AST" shape — `match` for dispatch, recursion for structure, a
// `StringBuilder` for the O(n) join, string interpolation for the leaves.
// ═════════════════════════════════════════════════════════════════════════════
// One key/value entry of an object. A plain value `data` — copied by value, no identity.
data Field {
key: string
value: Json
}
// The recursive value type. `ref choice` = abstract base + one sealed subclass per case;
// the cases reference `Json` (and `List<Json>`) freely because each case is a real class.
ref choice Json {
jnull
jbool(value: bool)
jnum(value: double)
jstr(value: string)
jarr(items: List<Json>)
jobj(fields: List<Field>)
}
// Serialize any value to its JSON text. Exhaustive `match` — every case is handled, so
// the compiler needs no trailing fallback. Each single-payload case binds its payload
// *transparently*: in `.jbool(b)` the name `b` IS the bool, in `.jarr(items)` `items` IS
// the `List<Json>` — the case view unwraps to the payload value (and `b.value` /
// `items.Count` still work). The array/object arms walk their collection and recurse.
//
// The transparent binding is pure SUGAR. A single-payload arm `.jbool(b) { … b … }` is
// exactly the case view `.jbool(c) { … c.value … }` with the projection elided — both
// lower to the identical IL (cast to the variant subclass, then load the one payload
// field). So `.jbool(b)` and `.jbool(c)` + `c.value` are interchangeable; the bare name
// is just the common case spelled shorter. (A multi-payload case has no single value to
// unwrap to, so it keeps the explicit view: `.jobj(c)` then `c.fields`.)
func stringify(j: Json) -> string {
match j {
.jnull { return "null" }
.jbool(b) { return b ? "true" : "false" }
.jnum(n) { return "{n}" }
.jstr(s) { return "\"{s}\"" }
.jarr(items) {
let sb = StringBuilder()
sb.Append("[")
var i = 0
while i < items.Count {
if i > 0 { sb.Append(",") }
sb.Append(stringify(items[i])) // recurse into each element
i += 1
}
sb.Append("]")
return sb.ToString()
}
.jobj(fields) {
let sb = StringBuilder()
sb.Append("{")
var i = 0
while i < fields.Count {
let f = fields[i]
if i > 0 { sb.Append(",") }
sb.Append("\"{f.key}\":")
sb.Append(stringify(f.value)) // recurse into each value
i += 1
}
sb.Append("}")
return sb.ToString()
}
}
}
// Build a small document and render it: {"name":"ada","tags":["math","engine"],"active":true}
func main() -> string {
let tags = List<Json>()
tags.Add(Json.jstr("math"))
tags.Add(Json.jstr("engine"))
let fields = List<Field>()
fields.Add(Field { key: "name", value: Json.jstr("ada") })
fields.Add(Field { key: "tags", value: Json.jarr(tags) })
fields.Add(Field { key: "active", value: Json.jbool(true) })
return stringify(Json.jobj(fields))
}
raw source ↓ /raw/authored/json.es
A tiny stack machine — the smallest thing that is honestly a "virtual machine".
// E# — a verified example from the E# language corpus (CLR language; .es, not ECMAScript).
// provenance: vm.es topic: choice status: verified
// hand-authored, idiomatic E# — verified through the E# compiler
namespace Demo
// ═════════════════════════════════════════════════════════════════════════════
// A tiny stack machine — the smallest thing that is honestly a "virtual machine".
//
// A program is a list of instructions; execution is a loop that walks them, each
// one pushing to or popping from an operand stack. This is how real bytecode VMs
// (the CLR's own, the JVM, CPython, Lua) work underneath — just with more opcodes.
//
// The instruction set is a `choice` (a value tagged union): some variants carry a
// payload (`push` carries the integer to push), most carry none (`add`, `dup`, …).
// Executing one instruction is a `match` over the variant — the canonical use of a
// sum type. The operand stack is a `List<int>` used as a LIFO: `Add` is push,
// `xs[xs.Count - 1]` is peek, `RemoveAt(xs.Count - 1)` is pop — a `List<T>` from the
// BCL, called directly. Anything that can fail (popping an empty stack, dividing by
// zero, leaving the wrong number of results) is a `Result`, threaded with `?`.
// ═════════════════════════════════════════════════════════════════════════════
// The instruction set. `push` is the only variant with a payload.
choice Op {
push(value: int)
add
sub
mul
div
dup // duplicate the top of the stack
swap // exchange the top two
}
// Pop the top of the stack, or fail on underflow. Takes `*List<int>`... actually a
// `List<int>` is already a reference type, so it is passed and mutated directly — no
// pointer needed. Returns the popped value (or an error), leaving the list shorter.
func pop(stack: List<int>) -> Result<int, string> {
if stack.Count == 0 {
return error("stack underflow")
}
let top = stack[stack.Count - 1]
stack.RemoveAt(stack.Count - 1)
return ok(top)
}
// Execute one instruction against the stack. `match` covers every variant, so the
// dispatch is exhaustive; each arm either pushes, or pops its operands (with `?`
// propagating an underflow) and pushes the result. Single-payload `push` binds its
// value transparently — `n` IS the int.
func step(stack: List<int>, op: Op) -> Result<int, string> {
match op {
.push(n) { stack.Add(n) }
.add {
let b = pop(stack)?
let a = pop(stack)?
stack.Add(a + b)
}
.sub {
let b = pop(stack)?
let a = pop(stack)?
stack.Add(a - b)
}
.mul {
let b = pop(stack)?
let a = pop(stack)?
stack.Add(a * b)
}
.div {
let b = pop(stack)?
let a = pop(stack)?
if b == 0 {
return error("division by zero")
}
stack.Add(a / b)
}
.dup {
let top = pop(stack)?
stack.Add(top)
stack.Add(top)
}
.swap {
let b = pop(stack)?
let a = pop(stack)?
stack.Add(b)
stack.Add(a)
}
}
return ok(0) // step's value is unused; it reports success or the error
}
// Run a whole program: step through every instruction, then require exactly one value
// left on the stack — that's the result. Too many or too few is a program error, not a
// silent answer.
func run(program: List<Op>) -> Result<int, string> {
let stack = List<int>()
var i = 0
while i < program.Count {
step(stack, program[i])? // propagate the first runtime error
i += 1
}
if stack.Count != 1 {
return error("program left {stack.Count} values on the stack, expected 1")
}
return ok(stack[0])
}
// Build and run: (2 + 3) * (10 - 6) == 5 * 4 == 20
// push 2, push 3, add → stack [5]
// push 10, push 6, sub → stack [5, 4]
// mul → stack [20]
// The entry point lives on a `ref data Program` — the OO "an object IS the application"
// shape, the class-style alternative to a bare top-level `func main`. A `main` method on
// a `ref data Program` IS the program's entry point; the compiler constructs the program
// (`Program()`) and calls `.main()`, so no separate launcher function is needed.
ref data Program {
func main() -> int {
let program = List<Op>()
program.Add(Op.push(2))
program.Add(Op.push(3))
program.Add(Op.add())
program.Add(Op.push(10))
program.Add(Op.push(6))
program.Add(Op.sub())
program.Add(Op.mul())
let r = run(program)
return r.IsOk ? r.Value : -1 // 20
}
}
raw source ↓ /raw/authored/vm.es
A tiny arithmetic calculator, end to end.
// E# — a verified example from the E# language corpus (CLR language; .es, not ECMAScript).
// provenance: calculator.es topic: choice status: verified
// hand-authored, idiomatic E# — verified through the E# compiler
namespace Demo
// ═════════════════════════════════════════════════════════════════════════════
// A tiny arithmetic calculator, end to end.
//
// It turns a string like "1 + 2 * 3" into a number — and gets 7, not 9, because it
// respects operator precedence (multiplication binds tighter than addition). It is
// written the way a real E# program is: a recursive-descent parser that builds an
// abstract syntax tree (AST), then a recursive evaluator that walks it.
//
// If this is the first E# you have ever read, here is the whole tour in one file:
//
// • `ref choice` — a tagged union (a "sum type"). The AST is one of three shapes:
// a number, an addition, or a multiplication. Because it is a
// *ref* choice it is a reference type, so a variant may hold
// another `Expr` and the tree can nest to any depth.
// • `data` + `*P` — a small mutable parser-state struct. `data` is a value type
// (copying it copies the bits), so to let every parse step share
// and advance ONE cursor we put it on the heap with `new`, which
// hands back a pointer, written `*P`.
// • `new` — the heap-allocation operator: `new P { ... }` allocates a value
// `data` on the heap and yields a `*P`. It is the only way to mint
// a fresh pointer.
// • `Result<T,E>` — error handling without exceptions. A parse step returns either
// `ok(tree)` or `error("message")`. The `?` after a call means
// "if that was an error, stop and return the same error from here",
// so the happy path stays flat and readable.
// • `match` — exhaustive, binding pattern dispatch over a choice's variants.
// ═════════════════════════════════════════════════════════════════════════════
// The AST. Each variant carries its own payload. `add` and `mul` hold two more
// `Expr`s — legal because `ref choice` is a reference type, so the tree nests freely.
ref choice Expr {
num(value: int) // a literal integer, e.g. 42
add(left: Expr, right: Expr) // left + right
mul(left: Expr, right: Expr) // left * right
}
// The parser's mutable state: the input text plus a cursor into it. It is a value
// type (`data`), but we will hand around a *pointer* (`*P`) so every parse step
// advances the same shared `pos` instead of mutating a private copy.
data P {
var src: string
var pos: int
}
// --- small cursor helpers -----------------------------------------------------
// Each takes `*P` (a pointer). A pointer parameter is NOT promoted to a method, so
// these stay plain free functions you call as `atEnd(p)` — only a direct `data`
// receiver (e.g. `func f(v: Vec)`) would become `v.f()`.
// True once the cursor has consumed the whole string.
func atEnd(p: *P) -> bool {
return p.pos >= p.src.Length
}
// Advance past spaces so the grammar can ignore whitespace.
func skipWs(p: *P) {
while !atEnd(p) {
if p.src[p.pos] == ' ' {
p.pos += 1
} else {
return
}
}
}
// --- the grammar, highest-precedence first ------------------------------------
//
// expr = term ('+' term)* (addition — lowest precedence)
// term = factor ('*' factor)* (multiplication — binds tighter)
// factor = number (a run of digits)
//
// Each rule returns `Result<Expr, string>`: the parsed subtree, or an error message.
// factor = number
func parseFactor(p: *P) -> Result<Expr, string> {
skipWs(p)
if atEnd(p) { return error("expected a number") }
if !char.IsDigit(p.src[p.pos]) { return error("expected a digit") }
let start = p.pos
while !atEnd(p) && char.IsDigit(p.src[p.pos]) {
p.pos += 1
}
let text = p.src.Substring(start, p.pos - start)
return ok(Expr.num(int.Parse(text)))
}
// term = factor ('*' factor)* — left-associative: fold each '*' into the tree.
func parseTerm(p: *P) -> Result<Expr, string> {
var left = parseFactor(p)? // `?` unwraps ok, or returns the error from here
while true {
skipWs(p)
if atEnd(p) || p.src[p.pos] != '*' {
return ok(left)
}
p.pos += 1
let right = parseFactor(p)?
left = Expr.mul(left, right)
}
return ok(left)
}
// expr = term ('+' term)* — same shape, one precedence level down.
func parseExpr(p: *P) -> Result<Expr, string> {
var left = parseTerm(p)?
while true {
skipWs(p)
if atEnd(p) || p.src[p.pos] != '+' {
return ok(left)
}
p.pos += 1
let right = parseTerm(p)?
left = Expr.add(left, right)
}
return ok(left)
}
// Entry point: put the cursor on the heap with `new`, parse a whole expression, and
// confirm nothing is left over.
func parse(src: string) -> Result<Expr, string> {
var p: *P = new P { src: src, pos: 0 } // `new` → heap value `data`, yields *P
let tree = parseExpr(p)?
skipWs(p)
if !atEnd(p) {
return error("trailing characters")
}
return ok(tree)
}
// --- evaluation ---------------------------------------------------------------
// Walk the tree to an int. `match` dispatches on the variant and binds a "case view"
// — `.add(n)` gives an `n` whose members are that variant's payloads, reached by their
// declared names (`n.left`, `n.right`, `n.value`). Recursion follows the tree's shape.
func eval(e: Expr) -> int { // `Expr` is a choice → not promoted → a free function
match e {
.num(n) { return n.value }
.add(n) { return eval(n.left) + eval(n.right) }
.mul(n) { return eval(n.left) * eval(n.right) }
}
return 0
}
// Parse, then evaluate. Returns the answer, or -1 if the input did not parse — so the
// precedence is visible in the result: 1 + 2 * 3 == 7, never 9.
func calc(src: string) -> int {
let r = parse(src)
if r.IsError {
return -1
}
return eval(r.Value)
}
// The entry point is a `main` method on a `ref data Program` (the OO application shape,
// the class-style alternative to a bare top-level `func main`). That method IS the entry
// point; the compiler constructs the program (`Program()`) and calls `.main()`.
ref data Program {
func main() -> int {
return calc("1 + 2 * 3") // 7
}
}