docs(course): replace Scala bridges with general programming in 00–05, README, mentor, spec
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9891bb596d
commit
d8828e1b6a
11 files changed
+109
-54
No files matched your search
@@ -43,7 +43,7 @@ A function is **total** if it returns a result for every possible input. It neve
|
||||
|
||||
What should `turn` do when the game is paused? Throw "cannot turn while paused"? Then every caller must catch, and a key press during pause would crash the game. Instead, our rules follow one simple convention: **when a rule does not apply, it returns the state unchanged.** `turn` while paused returns the same state. `advance` when the game is over returns the same state. This is what the fixtures `turn-ignored-when-paused`, `advance-game-over-unchanged`, `advance-won-unchanged` check.
|
||||
|
||||
> **From Scala:** this is the same reason you prefer `headOption` to `head`, and `Option` to exceptions: totality moves "what if it does not apply?" from a runtime surprise to an ordinary value. In a game, "nothing happens" is the right value surprisingly often.
|
||||
> **From everyday programming:** the usual alternative is a method that throws an `IllegalStateException` when it is called at the wrong time, so that every caller has to check `canTurn()` first or wrap the call in `try`/`catch`. A total rule behaves more like a disabled button in a user interface: pressing it is allowed, and nothing happens. Totality moves "what if it does not apply?" from a runtime surprise to an ordinary value. In a game, "nothing happens" is the right value surprisingly often.
|
||||
|
||||
A typical rule therefore starts with a **guard**:
|
||||
|
||||
@@ -191,7 +191,7 @@ A fixture case is `{ name, args, expected }`. For `advance`, `args` is a one-ele
|
||||
|
||||
When a fixture test fails, find the case by name, draw the board, and compute by hand what each phase (compute, decide, build) should give. Then compare with what your function returns. Usually one field differs, and the field tells you which phase is wrong.
|
||||
|
||||
> **From Scala:** in Scala, the enum values are qualified (`Status.Playing`, `Direction.Up`); add `import Direction.*` and `import Status.*` at the top of `Rules.scala` if you prefer the short names. Comparing a `Status` uses `==` (or `!=`). In F#, union cases are unqualified (`Playing`, `Up`), and record fields are PascalCase (`state.NextDir`).
|
||||
In the Scala track, the enum values are qualified (`Status.Playing`, `Direction.Up`); add `import Direction.*` and `import Status.*` at the top of `Rules.scala` if you prefer the short names. Comparing a `Status` uses `==` (or `!=`). In F#, union cases are unqualified (`Playing`, `Up`), and record fields are PascalCase (`state.NextDir`).
|
||||
|
||||
### Using what you built
|
||||
|
||||
|
||||
Reference in new issue
Block a user