Infer closure captures for quotations passed to list combinators #395
Labels
No labels
bug
dependencies
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
refactor
rust
technical-debt
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
navicore/patch-seq#395
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
When a quotation is passed directly to
list.fold,list.map, orlist.filter, and its body needs more inputs than the combinator provides, the compiler should auto-capture the excess from the stack — promoting the quotation to a closure without requiring an explicitClosure[T -- U]type annotation.Motivation
Currently, closure capture only triggers when the programmer explicitly declares a
Closure[...]return type on a word. Quotations passed inline to combinators are always treated as stateless, so any extra context must be threaded through packed accumulators or manual recursion.Example — evaluating a polynomial with Horner's method during
list.fold. The fold quotation needsx(the evaluation point) at every step, but fold only provides(acc, coeff):The packed-accumulator approach works but it obscures the algorithm and is error-prone (pick-depth bugs caused an infinite loop during development).
Proposed Change
Typechecker
When type-checking a quotation argument to a combinator whose expected quotation type is fully known:
( Int Int Int -- Int ))( Int Int -- Int )for fold)calculate_captures(which already exists incapture_analysis.rs) to determine what to captureType::QuotationtoType::Closurewith the inferred capturesCodegen
No changes needed — the closure codegen path already handles captures, environment creation, and
invoke_callabledispatch.list.foldand friends already accept bothValue::QuotationandValue::Closureviainvoke_callable.Scope
A conservative first version could limit auto-capture to the built-in list combinators (
list.fold,list.map,list.filter,list.each) where the expected quotation signature is statically known. This avoids ambiguity in the general case.Supported Capture Types
Per the existing closure codegen (
codegen/words.rslines 340-379), these types can already be captured:Int,Bool,Float,String,Quotation.Variantand nestedClosurecaptures are not yet supported and would remain an error.Risk
Medium. The type inference machinery is the most delicate part of the compiler. The key constraint: capture analysis must only trigger when the expected quotation type is unambiguous (i.e., the combinator's signature fully determines the expected effect). Starting with only the built-in list combinators keeps the scope narrow and testable.
Example: What This Enables
Context: discovered while implementing Shamir's Secret Sharing in Seq. The Lagrange interpolation and polynomial evaluation algorithms are natural fits for
list.fold, but the lack of auto-capture forced fallback to manual recursion with deeppick/rollstack juggling.accepted as an enhancement. see https://github.com/navicore/patch-seq/blob/main/docs/design/AUTO_CAPTURE_COMBINATORS.md for implementation plan
https://github.com/navicore/patch-seq/pull/400