CEP-0057: Reassignable Loop Bindings¶
Draft
Draft proposal for future reassignable loop item and optional payload bindings. V1 loop-introduced bindings are const, and while var is rejected.
Summary¶
Catalyst should eventually decide whether loop-introduced bindings can be reassignable, and if so which syntax expresses that without confusing local rebinding with collection mutation.
V1 accepts const loop bindings only:
while const item = iter.next() {
}
for item in items {
}
for var item in items {
}
In V1, for var requests mutable collection iteration through MutableIterable(Item). It does not make the loop item binding reassignable.
Motivation¶
Reassignable loop bindings are useful when an iteration body wants to normalize, transform, or replace a local working value before using it. The naive spelling collides with accepted V1 source forms:
while var item = iter.next() {
item = transform(item)
}
This looks consistent with if var, but it breaks the V1 rule that loop-introduced bindings are const.
The same problem is sharper for for:
for var item in slice {
item.* = value
}
Here var selects mutable iteration and item is usually a mutable pointer. If item were also reassignable, item = other would rebind the local pointer, not replace the collection element. V1 keeps element replacement explicit through the yielded item, such as item.* = value.
Proposed Direction¶
The proposal should decide:
- whether
whileoptional payload bindings should support a reassignable form; - whether
foritem bindings should support a reassignable form; - whether one syntax should cover both
whileandfor; - how reassignable binding syntax composes with destructuring binding patterns;
- how diagnostics distinguish local rebinding from collection element replacement;
- whether
for varremains permanently reserved for mutable iteration selection.
Any accepted design should preserve the V1 meaning of for var as mutable iteration selection. A future feature should not make for var item in xs silently mean both "call iter_mut" and "make item reassignable" unless diagnostics can make the two effects clear.
Example¶
Possible future shapes include a dedicated loop-binding modifier:
while mutable item = iter.next() {
item = transform(item)
}
or a body-local declaration, which is already valid V1 and may remain the preferred spelling:
while const item = iter.next() {
var current = item
current = transform(current)
}
These examples are illustrative only. The proposal does not reserve mutable or accept a new source form.
V1 Compatibility¶
V1 rejects while var:
while var item = iter.next() {
}
V1 accepts while const for optional payload loops, plain for for readonly or existing-iterator iteration, and for var for mutable iterable selection. All loop-introduced bindings are const in V1. Code that needs a mutable working value declares a local var inside the loop body.