Structural typing is a front-end question, except for field order, which is layout
This commit is contained in:
parent
a8a032e340
commit
95b4f1173b
40
DISCUSS.md
40
DISCUSS.md
@ -106,14 +106,40 @@ conditional re-initialisation. Neither is worth building alone; together they ar
|
||||
|
||||
## 4. Structural typing, row polymorphism, anonymous structs
|
||||
|
||||
Worth noting before this is scoped: `types.ml` already does **structural equality** on resolved types, and a Flan struct
|
||||
is exactly its C layout with no header or tag word. So the representation is already structural; what is nominal is the
|
||||
*checking*, not the data.
|
||||
The goal as stated: make this feel Clojure-like while still being typed.
|
||||
|
||||
The questions this opens: whether a function can take "any struct with an `x` and a `y`"; whether anonymous structs get a
|
||||
spelling; how this interacts with the FFI, where the shim generates a C typedef per named struct; and how it interacts
|
||||
with the planned managed classes, which are explicitly the *opposite* direction — identity and metadata rather than plain
|
||||
layout.
|
||||
**The representation is already structural.** `types.ml` does structural equality on resolved types, and a Flan struct is
|
||||
exactly its C layout with no header and no tag word. What is nominal is the *checking*, not the data — so this is a
|
||||
front-end question, not a data-model change.
|
||||
|
||||
**What it buys, in rough order of value here:**
|
||||
|
||||
1. **Your destructuring already looks like this, and that is the strongest argument.** Clojure's `{:keys [x y]}` works in
|
||||
binding position today. Structural typing makes the same notation work in *parameter* position — the pattern you write
|
||||
to pull fields out becomes the signature saying what you accept. One notation, two places, no separate declaration.
|
||||
That is precisely the "Clojure-like but typed" feel being asked for, and it needs no new syntax, only a new meaning
|
||||
for syntax that exists.
|
||||
2. **Functions over "anything with these fields".** Magnitude over anything with an `x` and a `y` — a position, a
|
||||
velocity, an enemy, a bullet. In a game this recurs constantly because everything has a position.
|
||||
3. **Ad-hoc returns.** Returning a hit flag and a point without declaring a type for the pair. The Clojure habit of
|
||||
returning a map, typed and free.
|
||||
4. **The FFI stops needing conversions.** raylib's `Vector2` and a locally-defined vector are byte-identical and are
|
||||
today two nominal types. Structurally they are one.
|
||||
|
||||
**Two costs, and the second is the real work:**
|
||||
|
||||
- **It cuts against the project's standing instinct.** This language has repeatedly chosen explicit over convenient: no
|
||||
implicit numeric conversions, a bare integer cannot become an enum, `:spcae` must fail at the call site. Structural
|
||||
typing says things are compatible when they happen to line up, which is the opposite reflex. Worth deciding
|
||||
deliberately rather than drifting into — and worth asking whether structural compatibility should be *written* at the
|
||||
site that relies on it, the way `(GamepadAxis n)` made an enum conversion explicit without making it implicit.
|
||||
- **Field order is layout, and that is the hard part.** `{x f32, y f32}` and `{y f32, x f32}` have the same fields and
|
||||
different memory. So either field order becomes significant — surprising, since nothing else about a structural type
|
||||
should be — or matching a differently-ordered type requires a copy, which breaks the zero-cost property the whole data
|
||||
model rests on. This is the question to settle first; the type checking is comparatively easy.
|
||||
|
||||
Also unresolved: the shim generates a C typedef per *named* struct, and an anonymous struct has no name to generate one
|
||||
from. Either anonymous structs cannot cross the FFI, or the generator learns to name them.
|
||||
|
||||
## 5. A performant JS transpiler
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user