7fe08139fb
Tested McCarthy's head[a; b] notation (user request). Explicit structure (brackets + semicolons) in the function-call shape LLMs know cold. Result 4-5/8 (model variance over two runs): below plain parens, above bracket-free. Two watch-out catches kept it honest: (1) a trailing ';' before ']' — a normal trailing separator Qwen wrote — was rejected by my too-strict parser; fixed to tolerate it, round-trip preserved (without this M-expr looked unfairly bad). (2) L4 then failed with 43 '[' vs 42 ']', a genuine Qwen bracket imbalance (not truncation), the same depth-tracking failure as plain parens. Why worse than plain parens despite being explicit: swapping () for [] does nothing for the balance burden, and the semicolons ADD a second consistency requirement Qwen does not reliably meet. This sharpens the overall finding across five formats (annotated-parens 7/8 > plain parens 6/8 > M-expr 4-5/8 > indent 3/8 > YAML 2/8): the discriminator is not "explicit vs implicit" but REDUNDANT CUE vs EXTRA BURDEN. Depth-annotated parens carry nesting redundantly so the model can't lose its place (best); indentation moves tracking to an implicit channel (worst); M-expr semicolons add bookkeeping on top of bracket balance (middle). Lever for an LLM-authored language: redundant self-checking structure, not a lighter or more familiar surface that carries extra bookkeeping. Synthesis in format-findings.md.
8.2 KiB
8.2 KiB
Qwen format probe — M-expressions head[a; b]
Model: Qwen/Qwen3-Coder-Next; single-shot; own literal parser (atoms verbatim).
L0_const — ✅ green
tokens: prompt=616 completion=56
model output:
module[
m;
fn[
answer;
type[
fn-type[
params[];
ret[
own[
con[Int]
]
]
]
];
params[];
body[
42
]
]
]
converted Form-A:
(module m (fn answer (type (fn-type (params) (ret (own (con Int))))) (params) (body 42)))
L1_arith — ✅ green
tokens: prompt=618 completion=72
model output:
module[
m;
fn[
triple;
type[
fn-type[
params[
own[
con[Int]
]
];
ret[
own[
con[Int]
]
]
]
];
params[x];
body[
app[*; x; 3]
]
]
]
converted Form-A:
(module m (fn triple (type (fn-type (params (own (con Int))) (ret (own (con Int))))) (params x) (body (app * x 3))))
L2_print — ✅ green
tokens: prompt=613 completion=79
model output:
module[
m;
fn[
main;
type[
fn-type[
params[];
ret[
own[
con[Unit]
]
];
effects[IO]
]
];
params[];
body[
seq[
app[print; 7];
do[io/print_str; "\n"]
]
]
]
]
converted Form-A:
(module m (fn main (type (fn-type (params) (ret (own (con Unit))) (effects IO))) (params) (body (seq (app print 7) (do io/print_str "\n")))))
L3_adt — ✅ green
tokens: prompt=632 completion=122
model output:
module[
m;
data[
Light;
ctor[Red];
ctor[Green]
];
fn[
code;
type[
fn-type[
params[
own[
con[Light]
]
];
ret[
own[
con[Int]
]
]
]
];
params[x];
body[
match[
x;
case[
pat-ctor[Red];
0
];
case[
pat-ctor[Green];
1
]
]
]
]
]
converted Form-A:
(module m (data Light (ctor Red) (ctor Green)) (fn code (type (fn-type (params (own (con Light))) (ret (own (con Int))))) (params x) (body (match x (case (pat-ctor Red) 0) (case (pat-ctor Green) 1)))))
L4_rec — ❌ convert
tokens: prompt=644 completion=301
model output:
module[
m;
data[
IntList;
ctor[Nil];
ctor[
Cons;
con[Int];
con[IntList]
]
];
fn[
length;
type[
fn-type[
params[
own[
con[IntList]
]
];
ret[
own[
con[Int]
]
]
]
];
params[xs];
body[
match[
xs;
case[
pat-ctor[Nil];
0
];
case[
pat-ctor[Cons; h; t];
app[
+;
1;
app[length; t]
]
]
]
]
];
fn[
main;
type[
fn-type[
params[];
ret[
own[
con[Unit]
]
];
effects[IO]
]
];
params[];
body[
let[
xs;
term-ctor[
IntList;
Cons;
1;
term-ctor[
IntList;
Cons;
2;
term-ctor[
IntList;
Cons;
3;
term-ctor[IntList; Nil]
]
];
seq[
app[
print;
app[length; xs]
];
do[io/print_str; "\n"]
]
]
]
]
]
convert:
own parser rejected output: unterminated [
L5_series_len — ❌ check
tokens: prompt=875 completion=182
model output:
module[
demo_m;
fn[
main;
type[
fn-type[
params[];
ret[
own[
con[Unit]
]
];
effects[IO]
]
];
params[];
body[
let[
s;
new[
Series;
con[Float];
3
];
];
let[
s1;
app[Series.push; s; 1.0];
];
let[
s2;
app[Series.push; s1; 2.0];
];
let[
s3;
app[Series.push; s2; 3.0];
];
seq[
app[
print;
app[Series.len; s3]
];
do[io/print_str; "\n"]
]
]
]
]
converted Form-A:
(module demo_m (fn main (type (fn-type (params) (ret (own (con Unit))) (effects IO))) (params) (body (let s (new Series (con Float) 3)) (let s1 (app Series.push s 1.0)) (let s2 (app Series.push s1 2.0)) (let s3 (app Series.push s2 3.0)) (seq (app print (app Series.len s3)) (do io/print_str "\n")))))
check:
error: [surface-parse-error] parse error: expected term, got `)` at byte 134
L6_series_at — ❌ check
tokens: prompt=883 completion=190
model output:
module[
demo_m;
fn[
main;
type[
fn-type[
params[];
ret[
own[
con[Unit]
]
];
effects[IO]
]
];
params[];
body[
let[
s;
new[
Series;
con[Float];
3
];
];
let[
s1;
app[Series.push; s; 1.0];
];
let[
s2;
app[Series.push; s1; 2.0];
];
let[
s3;
app[Series.push; s2; 3.0];
];
seq[
app[
print;
app[
Series.at;
s3;
0
]
];
do[io/print_str; "\n"]
]
]
]
]
converted Form-A:
(module demo_m (fn main (type (fn-type (params) (ret (own (con Unit))) (effects IO))) (params) (body (let s (new Series (con Float) 3)) (let s1 (app Series.push s 1.0)) (let s2 (app Series.push s1 2.0)) (let s3 (app Series.push s2 3.0)) (seq (app print (app Series.at s3 0)) (do io/print_str "\n")))))
check:
error: [surface-parse-error] parse error: expected term, got `)` at byte 134
L7_sma — ❌ check
tokens: prompt=966 completion=327
model output:
module[
demo_m;
fn[
main;
type[
fn-type[
params[];
ret[
own[
con[Unit]
]
];
effects[IO]
]
];
params[];
body[
let[
s;
new[
Series;
con[Float];
3
];
let[
s1;
app[Series.push; s; 1.0];
];
let[
s2;
app[Series.push; s1; 5.0];
];
let[
s3;
app[Series.push; s2; 3.0];
];
seq[
app[
print;
app[
/;
app[Series.sum; s3];
3.0
]
];
let[
s4;
app[Series.push; s3; 8.0];
seq[
app[
print;
app[
/;
app[Series.sum; s4];
3.0
]
];
let[
s5;
app[Series.push; s4; 6.0];
seq[
app[
print;
app[
/;
app[Series.sum; s5];
3.0
]
];
let[
s6;
app[Series.push; s5; 2.0];
]
converted Form-A:
(module demo_m (fn main (type (fn-type (params) (ret (own (con Unit))) (effects IO))) (params) (body (let s (new Series (con Float) 3) (let s1 (app Series.push s 1.0)) (let s2 (app Series.push s1 5.0)) (let s3 (app Series.push s2 3.0)) (seq (app print (app / (app Series.sum s3) 3.0)) (let s4 (app Series.push s3 8.0) (seq (app print (app / (app Series.sum s4) 3.0)) (let s5 (app Series.push s4 6.0) (seq (app print (app / (app Series.sum s5) 3.0)) (let s6 (app Series.push s5 2.0)))))))))))
check:
error: [surface-parse-error] parse error: expected term, got `)` at byte 166
Ladder
- L0_const: ✅ green
- L1_arith: ✅ green
- L2_print: ✅ green
- L3_adt: ✅ green
- L4_rec: ❌ convert
- L5_series_len: ❌ check
- L6_series_at: ❌ check
- L7_sma: ❌ check