Skip to content

Document the four working WS-mode let binding variants #21

Description

@hierophantos

Summary

Four let binding variants currently work in WS-mode .prologos files, but only some are tested and none are documented in prologos-syntax.md. This issue tracks a small docs+tests pass to make the supported surface explicit, without changing parser/macro behavior.

Surfaced during review of PR #11 (pitfall #5: multi-line let body) — the expand-let family supports more variants than expected, all functional, none surfaced to users.

The four working variants

Verified empirically (each evaluates [int+ x y] correctly in a let-bound context):

Form Example Macro path
Flat-pair, untyped let [x 5 y 6] body expand-let-bracket-bindings flat-pair branch (macros.rkt:4358)
:=-marked, untyped let [x := 5 y := 6] body expand-let-bracket-bindings := branch via parse-assign-bindings
:=-marked, typed let [x : Int := 5 y : Int := 6] body Same path; : consumed before :=
Sequential per-line (block-style) let x := 5\nlet y := 6\nbody Each line is one expand-let invocation; scopes stack

What does NOT work:

  • Typed without :=: let [x : Int 5 y : Int 6] body — fails with Unbound variable :. Structural reason: types can span multiple tokens (e.g., x : Map Keyword Int), and without := the parser cannot disambiguate where the type ends and the value begins.

Why pluripotential is the right state for now

Three observations from the review discussion:

  1. The flat-pair / := choice maps to a real ergonomic difference. Quick local bindings (counters, intermediate results) read fine flat-pair. Bindings with explicit types or complex RHS expressions read markedly better with :=. Two forms, two cognitive loads — not redundant.
  2. Cross-language intuitions split here. Clojure → flat-pair. Haskell/ML → let x = 5 in body (:= analog). Lisp → nested. Picking one form prematurely picks a winner against half our potential contributors' intuitions.
  3. Cost of supporting multiple variants is documentation, not code. All four implementations exist and are tested at the macro level. The cost is documenting them; the benefit is gathering usage data before codifying.

Scope

This is docs + tests only — no compiler/parser change.

  • Update prologos-syntax.md § Definitions / let with the four variants, examples, and the typed-without-:= failure mode (with the structural explanation)
  • Update docs/spec/grammar.org and docs/spec/grammar.ebnf if the formal grammar there needs to reflect the variants
  • Add WS-mode test coverage for any variants that aren't currently pinned at the WS level (audit tests/test-eq-let-surface-01.rkt, tests/test-let-arrow-syntax.rkt, tests/test-let-multiline-ws.rkt for gaps)
  • Add at least one stdlib or examples usage of multi-binding bracket-block let so users have a real example to learn from

Out of scope (intentional)

  • Don't yet pick a canonical "one true form". The pluripotential discipline says: track usage over the next few months. If one form dominates in examples and contributor PRs, that's the natural canonical. If usage stays mixed, that's a real signal that pluripotential is a feature.
  • Don't deprecate any variant. All four work; collapsing now would make the scope larger and force a decision we don't yet have data for.
  • Don't refactor the macro layer. expand-let has 5 sexp branches; that's a separate cleanup track if we ever decide IR canonicalization is worth doing.

Source

Priority

Low. Working surface; gap is purely about discoverability. Pick up when next doing a stdlib syntax/style pass.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationenhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions