The two models get named, and the gap handler-case fills gets written down
The dynamic paths follow Clojure and Common Lisp, the static paths follow Odin, and the ML share is what neither supplies. Where the two Lisps disagree the question is which one the rest of Flan already agrees with: conditions say Common Lisp, maps and keywords say Clojure. The missing unwinding handler is recorded alongside it, since a caller that wanted a default had nothing to write once read-file stopped returning an Option.
This commit is contained in:
parent
b77b4f3a1f
commit
624b595869
50
FIX.org
50
FIX.org
@ -437,6 +437,56 @@ rename. typed-flan branch freezes the static language pre-dyn.
|
|||||||
All of it dispatches after the x86-dyn lane lands. The struct dyn-field
|
All of it dispatches after the x86-dyn lane lands. The struct dyn-field
|
||||||
refusal (01e60fa) is the stopgap 2 lifts.
|
refusal (01e60fa) is the stopgap 2 lifts.
|
||||||
|
|
||||||
|
** The two models, named 2026-09-19
|
||||||
|
With a collector in the runtime, the direction has a shorter statement than
|
||||||
|
it used to. The dynamic paths mimic Clojure. The static paths mimic Odin.
|
||||||
|
Both carry a little more ML than either of them does.
|
||||||
|
|
||||||
|
That is a tiebreaker, not a slogan. A question on the dyn side that Clojure
|
||||||
|
has already answered takes Clojure's answer unless there is a reason to
|
||||||
|
depart, and the same holds for Odin on the static side. Keywords, maps and
|
||||||
|
nil landed under that reasoning without it being written down yet.
|
||||||
|
|
||||||
|
Common Lisp is consulted alongside Clojure on the dynamic side, and on some
|
||||||
|
questions it is the better authority of the two. The condition system is the
|
||||||
|
standing proof: handler-bind, the restarts and invoke-restart are Common
|
||||||
|
Lisp, and Clojure has nothing resembling them. handler-case is the same
|
||||||
|
lineage — Clojure's try/catch is the shape most reached for, but the form
|
||||||
|
being added is Common Lisp's, and it is named for the Lisp rather than the
|
||||||
|
Clojure because it is the unwinding half of a pair whose other half is
|
||||||
|
already CL's.
|
||||||
|
|
||||||
|
Where the two disagree, the question is which one the rest of Flan already
|
||||||
|
agrees with. Conditions say Common Lisp. Maps, keywords and nil say Clojure.
|
||||||
|
Neither answer generalises to the other's territory.
|
||||||
|
|
||||||
|
The ML share is the part neither model supplies — the type system, the
|
||||||
|
options, the exhaustive matching, and whatever a second ML surface would
|
||||||
|
eventually add if the deferred syntax question ever reopens.
|
||||||
|
|
||||||
|
** handler-case, decided 2026-09-19
|
||||||
|
Flan has handler-bind, which is the resuming handler: it runs where the
|
||||||
|
condition was signalled, with the stack still standing, and carries on by
|
||||||
|
invoking a restart. What it has no spelling for is the other half — unwind,
|
||||||
|
and answer the whole form with a value. Clojure spells that try/catch and
|
||||||
|
reaches for it constantly; the closest thing here is a handler-bind plus a
|
||||||
|
use-value dance that is far heavier than the intent, or a pre-check that
|
||||||
|
races the read it guards.
|
||||||
|
|
||||||
|
The gap showed itself when edn/read-file stopped returning an Option. The
|
||||||
|
caller that used to write or-else against a None had nothing left to write,
|
||||||
|
because the missing file now arrives as a FileError condition and the only
|
||||||
|
concise way to answer a condition with a default did not exist. The shape
|
||||||
|
wanted is:
|
||||||
|
|
||||||
|
(handler-case (edn/read-file "game-data.edn")
|
||||||
|
[(FileError [c] nil)])
|
||||||
|
|
||||||
|
which keeps read-file's decision intact — the caller still says what a
|
||||||
|
missing file means — while costing one form instead of a machine. Until it
|
||||||
|
lands, sand.flan guards the read with file-exists?, which is a stopgap and
|
||||||
|
racy, and should be rewritten the moment this exists.
|
||||||
|
|
||||||
** The JS backend answers string equality wrongly, parked 2026-09-19
|
** The JS backend answers string equality wrongly, parked 2026-09-19
|
||||||
Typed = and != grew strings in daed039, and the JS dialect was not taught the
|
Typed = and != grew strings in daed039, and the JS dialect was not taught the
|
||||||
case. A string there is a view object and the arm at lib/js.ml:856 compares
|
case. A string there is a view object and the arm at lib/js.ml:856 compares
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user