// 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` 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 { 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 { 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" }