Blink structs are intentionally immutable — no field mutation. To "update" a struct, you must reconstruct all fields manually:
let updated = Account { id: acct.id, owner: acct.owner, balance: acct.balance + amount }
This scales poorly. The self-hosting compiler's Node struct has 51 fields — updating one field requires spelling out all 51. This blocks the parser parallel-array migration (0jbhdq) and makes struct-heavy code fragile: adding a field to a type breaks every construction site.
- Rust:
Struct { field: val, ..other }— spread suffix, same type required, last position - OCaml:
{ record with field = val }—withkeyword (taken in Blink for resource blocks) - Elm:
{ record | field = val }— pipe separator inside braces - JavaScript:
{ ...obj, field: val }— spread operator, any position, no type checking - Kotlin:
data class+.copy(field = val)— method-based, compiler-generated
Five panelists (systems, web/scripting, PLT, DevOps/tooling, AI/ML) independently proposed options, then voted.
Q1: Struct copy-update syntax (4-1 for Option A)
Option A: ..source suffix in struct literal
let updated = Account { balance: acct.balance + amount, ..acct }
Option B: copy keyword expression
let updated = copy acct { balance: acct.balance + amount }
Option C: update...with keyword expression
let updated = update acct with { balance: acct.balance + amount }
| Expert | Vote | Reasoning |
|---|---|---|
| Systems | A | Zero-cost desugaring to flat field list in C. No new keywords — keywords have grammar-wide blast radius (copy and update are common identifiers). .. dual of pattern rest is structural symmetry, not coincidence. |
| Web/Scripting | A | Recognizable from Rust/JS. Symmetric with existing pattern .. — same sigil, opposite direction. Zero new vocabulary. Teachable in one sentence. |
| PLT | A | Pattern/construction duality is principled: .. means "fields I didn't name" in both directions. Sound typing rule — source must be same nominal type. Desugars before type inference. |
| DevOps | A | Single sigil means one formatter/LSP code path. Zero keyword-colorization edge cases. Error attribution is precise. Originally proposed Option C but switched — with reuse as contextual keyword creates diagnostic ambiguity. |
| AI/ML | B (dissent) | copy names the operation at first token — no sigil overloading. LLMs trained on Rust may place ..source in wrong position or confuse with range ... Counter: ..source in struct literal is a field expression LLMs handle reliably from Rust precedent. |
Result: A — 4-1 (AI/ML dissented)
sourcemust be the same nominal type as the struct being constructed..sourcemust appear last in the field list (hard parse rule, not style)- At most one
..sourceper literal - Explicit fields shadow source fields
- Desugars to field-by-field copy at typecheck — zero codegen impact
- Source values win over field defaults for non-explicit fields
| Criterion | Pass/Fail | Notes |
|---|---|---|
| Learnability | Pass | ..source is dual of pattern ... One concept, two directions |
| Consistency | Pass | Reuses existing .. sigil. No new keywords or grammar categories |
| Generability | Pass | Rust precedent in training data. Position error caught by parser |
| Debuggability | Pass | Type mismatch and position errors are clear and actionable |
| Token efficiency | Pass | 51-field Node update: ~15 tokens vs ~300 |
0 criteria fail — no reconsideration needed.