forked from verus-lang/verus
verus source docs guide src lex_mutual.md
2.0 kB · 51 lines
Markdown

Lexicographic decreases clauses #

For some recursive functions, it's difficult to specify a single value that decreases in each recursive call. For example, the Ackermann function has two parameters m and n, and neither m nor n decreases in all 3 of the recursive calls:

{{#include ../../../../examples/guide/recursion.rs:ackermann}}

For this situation, Verus allows the decreases clause to contain multiple expressions, and it treats these expressions as lexicographically ordered. For example, decreases m, n means that one of the following must be true:

  • m stays the same, and n decreases, which happens in the call ackermann(m, (n - 1) as nat)
  • m decreases and n may increase or decrease arbitrarily, which happens in the two calls of the form ackermann((m - 1) as nat, ...)

Mutual recursion #

Functions may be mutually recursive, as in the following example where is_even calls is_odd recursively and is_odd calls is_even recursively:

{{#include ../../../../examples/guide/recursion.rs:even}}

The recursion here works for both positive and negative i; in both cases, the recursion decreases abs(i), the absolute value of i.

An alternate way to write this mutual recursion is:

{{#include ../../../../examples/guide/recursion.rs:even2}}

In this alternate version, the recursive call !is_even(i) doesn't decrease abs(i), so we can't just use abs(i) as the decreases clause by itself. However, we can employ a trick with lexicographic ordering. If we write decreases abs(i), 1, then the call to !is_even(i) keeps the first expression abs(i) the same, but decreases the second expression from 1 to 0, which satisfies the lexicographic requirements for decreasing. The call is_odd(i - 1) also obeys lexicographic ordering, since it decreases the first expression abs(i), which allows the second expression to increase from 0 to 1.