Files
Brummel 7fe08139fb experiment(cma): M-expressions tested — middle of the pack; sharpens the finding (refs #68)
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.
2026-06-02 19:11:18 +02:00

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