status | flip | authors | sponsor | updated |
---|---|---|---|---|
accepted |
13 |
Bastian Müller ([email protected]) |
Bastian Müller ([email protected]) |
2022-12-06 |
This FLIP proposes a change of the semantics of for-loops: Iteration variables should be defined for each loop iteration, instead of once for all iterations.
Currently, Cadence introduces one variable for the value, and one variable for the index (if given), for the whole loop.
Capturing these variables has surprising behaviour.
For example, this program repeatedly logs 3
, instead of the items of the array, as 3
is the last value assigned to the value variable:
let fs: [((): Int)] = []
for x in [1, 2, 3] {
fs.append(fun (): Int {
return x
})
}
for f in fs {
log(f())
}
This has been a problem in many other languages. Some languages and users mostly agree changing the semantics is a good idea:
- Go is planning to change their for-loop semantics
- C# already changed their for-loop semantics which caused little problems
Likely only few developers experience this surprising behaviour, which is usually discovered as a bug. It is very unlikely that existing code relies on the current semantics.
Changing the semantics will affect few users and will avoid further potential bugs in developers' programs.
Developers will benefit from this change by not getting surprised, and the change will likely reduce a source of potential bugs from the language.
The value and index variables of for-loops should be introduced fresh for each iteration, instead of once for all iterations.
Changing the semantics is a breaking change. However, few developers should be affected by it.
None
Performance will likely decrease and memory usage will increase. However, the effects should be minimal.
None
This change is trivial in the implementation.
This change has no impact on compatibility between systems (e.g. SDKs).
Existing contracts' and new transactions' behaviour will change. Given that capturing variables is uncommon, this change should only affect few users' programs.
None
- Go is planning to change their for-loop semantics
- C# already changed their for-loop semantics which caused little problems
- In JavaScript, for loops with
var
variables are function-scoped. When block scope variables (let
) were introduced, their behaviour in for-loops was defined as per-iteration.
None
An implementation is available in onflow/cadence#2024