# c has no closure syntax One `Ishikawa → scientific method → Six Sigma` loop. The record below is the commit message as written at the time, before the outcome was known to anyone reading this file. ## Record — `2bed848` ``` EXPERIMENT: hand the construct the body as a real closure ROOT CAUSE of the weaker design: "C has no closures" was taken as a fact about what is possible. It is a fact about one grammar. Every C++ lambda, every Go closure, every Rust closure compiles to a struct of captured values plus a function pointer -- which is what is emitted here. Codegen emits C; it is not written in C's syntax, and the distinction is the whole difference between a construct that can only decide whether to repeat and one that controls invocation. It would also have crippled the JS backend, which has closures natively, for a limit that applies only to the C one. PREDICTIONS AND RESULTS 1 env struct + thunk taking void* TRUE 2 fails to compile: struct redefinition FALSE -- C allows the inner declaration to shadow. Prediction wrong; C is more permissive than assumed. A different real defect surfaced instead: a wrap with no exit construct emitted `(EL_STR("f"), EL_STR(""), __r);` -- a call to an empty target -- because has_exit was reused as "needs a wrapper" and the exit line was emitted unconditionally. Fixed. 3 compiles when the target is declared in El FALSE -- and this is the root cause worth keeping: El has ONE type, el_val_t = int64_t. El's type system cannot describe a callable, so `extern fn` and the real signature cannot be made to agree in El's own vocabulary. The fix is not a cast: codegen DEFINES the wrap calling convention, so codegen emits the extern declaration. The convention is not El-expressible; it is emitted. 4 target controls invocation, 0..N times TRUE 5 existing @manager output byte-identical TRUE 6 compiler fixpoint holds TRUE 7 emitting the convention makes it compile TRUE MEASURED base(5) wrapped by a target that invokes the body twice and sums -> 10 never_runs(5) wrapped by a target that never invokes it -> 999 Neither is expressible by "decide whether to repeat". This supersedes the repeats_body experiment on experiment/repeats-body, which was built around the mistaken limit. ``` ## Record — `7d01608` ``` land wraps_body: a construct controls invocation Proven on experiment/wraps-body (2bed848): base(5) wrapped by a target that invokes the body twice returns 10; a target that never invokes it returns 999. Neither is expressible by deciding whether to repeat. Root cause it corrected: 'C has no closures' is a fact about one grammar, not about what can be emitted. And El's single type (el_val_t = int64_t) cannot describe a callable, so codegen emits the calling convention rather than asking El's type system for something it structurally cannot say. ```