Kotlin has a nice feature that allows to return
/break
/continue
across function boundaries, if these functions are inlined. For example:
public inline fun repeat(times: Int, action: (Int) -> Unit) {
for (index in 0 until times) {
action(index)
}
}
action
is a closure that accepts an integer. The function can be used like this:
repeat(100) { i ->
println(i)
}
Because it's an inline
function, return
/continue
/break
keywords within the closure ignore the function boundary; this is called non-local control flow:
fun foo(): Int {
repeat(100) {
return 4 // returns from foo()
}
}
I think that this would be useful in Rust as well. However, we would need labels to indicate that we want to leave the enclosing function:
'f: fn product(s: &[i32]) -> i32 {
// multiply all values, but return early if the slice contains 0
s.iter().fold(0, |acc, &x| {
if x == 0 {
return 'f 0;
}
acc * x
})
}
To mark a function argument that allows non-local control flow, we could use an annotation, for example
#[inline]
pub fn repeat(times: i32, #[non_local] action: impl Fn(i32)) {
for index in 0..times {
action(index);
}
}
The compiler must inline all closures that contain non-local control flow.
What do you think about this idea?