For Loops

The previous section introduced a while loop implementation of triangle:

fn loop_triangle(n: u32) -> (sum: u32) requires triangle(n as nat) < 0x1_0000_0000, ensures sum == triangle(n as nat), { let mut sum: u32 = 0; let mut idx: u32 = 0; while idx < n invariant idx <= n, sum == triangle(idx as nat), triangle(n as nat) < 0x1_0000_0000, { idx = idx + 1; assert(sum + idx < 0x1_0000_0000) by { triangle_is_monotonic(idx as nat, n as nat); } sum = sum + idx; } sum }

We can rewrite this as a for loop as follows:

fn for_loop_triangle(n: u32) -> (sum: u32) requires triangle(n as nat) < 0x1_0000_0000, ensures sum == triangle(n as nat), { let mut sum: u32 = 0; for idx in iter: 0..n invariant sum == triangle(idx as nat), triangle(n as nat) < 0x1_0000_0000, { assert(sum + idx + 1 < 0x1_0000_0000) by { triangle_is_monotonic((idx + 1) as nat, n as nat); } sum = sum + idx + 1; } sum }

The only difference between this for loop and the while loop is that idx is automatically incremented by 1 at the end of the each iteration.

In addition, iter.start, iter.cur, iter.end reveal the start, current, and end for the iterator of range 0..n. iter@ records all the elements that the iterator has iterated so far. In the above example, if idx=3, iter@ =~= seq![0,1,2]