The trio the author decided on 2026-09-20 is now all built: def is CL's defparameter — its initialiser runs on every daemon re-run, unguarded, so an edited initialiser repaints the same storage on C-c C-c plus re-run — defonce (Clojure's name for CL's defvar, per the author) initialises once behind the .init~once. flag, and defconst stays the image. One parse arm reads both forms; the difference is Ast.reinit, carried to Tast.global's grerun. Emit.startup_plan gives a def no guard flag, and Check.check_global lifts every def initialiser — zero and literal included — into global/<n>, so the host's startup reaches it through the function cell and a re-evaluated def swaps it (Session's def_inits; Emit.redefinition declares the cell for a non-sibling target). The old defvar spelling is refused with the rename and both compiling spellings, and every program, test, doc and editor list is swept — except sand.flan, the author's live WIP, whose seven defvar lines are flagged in FIX.org and keep its three dependent tests red on this branch.
54 lines
2.2 KiB
Plaintext
54 lines
2.2 KiB
Plaintext
;;;; nil <-> None at (Option T) boundaries -- M2 queue item 4.
|
|
;;;;
|
|
;;;; nil is dyn's own absence and None is (Option T)'s; this is the boundary
|
|
;;;; where the checker decides they are the same absence. [absent] and
|
|
;;;; [opt-of] take it in at the two annotated sites that are not a function
|
|
;;;; argument -- a global's declared type and a return type; [via-param]
|
|
;;;; takes it in at the third, a parameter. [as-dyn] is the other direction:
|
|
;;;; a written (Option i64) crossing into dyn becomes nil or the boxed
|
|
;;;; payload. [box-it]/[unbox-opt] round-trip a value through both crossings.
|
|
;;;;
|
|
;;;; The last line is the trap: a dyn that is nil only once the program runs,
|
|
;;;; reaching a bare i64. The literal [nil] two lines above it would have been
|
|
;;;; refused at compile time instead -- see test_flan.ml and
|
|
;;;; test_acceptance.ml's "nil at a bare T, compile time" row for that half.
|
|
|
|
(defonce absent (Option i64) nil)
|
|
|
|
(defn opt-of [flag bool] (Option i64)
|
|
(if flag (Some 7) nil))
|
|
|
|
(defn via-param [o (Option i64)] i64
|
|
(match o (Some v) v None -1))
|
|
|
|
(defn as-dyn [o (Option i64)] dyn o)
|
|
|
|
(defn box-it [x i64] dyn x)
|
|
(defn unbox-opt [d dyn] (Option i64) d)
|
|
|
|
(defn maybe-nil [flag bool] dyn (if flag 5 nil))
|
|
(defn take-i64 [n i64] i64 n)
|
|
|
|
(defn show [o (Option i64)] ()
|
|
(print (match o (Some v) v None -1)) (println ""))
|
|
|
|
(defn main [] ()
|
|
;; nil -> None, at a global's declared type, a return type and a parameter.
|
|
(show absent) ; -1
|
|
(show (opt-of true)) ; 7
|
|
(show (opt-of false)) ; -1
|
|
(print (via-param nil)) (println "") ; -1
|
|
(print (via-param (Some 3))) (println "") ; 3
|
|
|
|
;; None -> nil, crossing into dyn; Some x -> the boxed x.
|
|
(print (= (as-dyn None) nil)) (println "") ; true
|
|
(print (as-dyn (Some 9))) (println "") ; 9
|
|
|
|
;; A value round-tripped through both crossings: typed -> dyn -> (Option T).
|
|
(show (unbox-opt (box-it 42))) ; 42
|
|
|
|
;; The trap: a dyn that turns out to be nil only when the program runs,
|
|
;; reaching a bare i64. flan_dyn_need_i64 owns the wording.
|
|
(print (take-i64 (maybe-nil false)))
|
|
(println ""))
|