Skip to main content
Version: 2.4.0

Conditional Logic

In provable code, we can't use the JavaScript if statement. For a constraint system to be valid, it must follow the exact same path every time it's executed. In traditional programming, what an if statement does is evaluate an expression, then jump to one of two different code paths. This behavior can't be copied, but what is possible within provable codes is setting a variable based on the outcome of an expression. The trick is that both sides of the expression will always be evaluated.

Invalid Example

For a simple example of the kind of conditional logic that won't work, see:

// INVALID - DO NOT COPY
let n_heads = Field(0);
for (let i = 0; i < 5; i++) {
const x = Field.random();
Provable.if(
x.isEven(),
(n_heads = n_heads.add(1)),
(n_heads = n_heads.add(0))
);
}
// n_heads is ALWAYS 5

The reason this code is invalid is that every iteration, we evaluate the true side, then the false side. So we always add 1, then 0 to the number of heads flipped. The result will always evaluate to the number of flips.

Valid Example

Instead, write conditional logic like this:

let n_heads = Field(0);
for (let i = 0; i < 5; i++) {
const x = Field.random();
const flip = Provable.if(x.isEven(), Field(1), Field(0));
n_heads = n_heads.add(flip);
}

This code will work correctly because we assign the result of the expression to a variable, and there are no other side effects caused by evaluating both sides.

Valid Example Using a Function

It is valid to execute code in both sides of the condition, as long as you understand the implications! In general, a function that returns a value and has no side effects is good to use in this case.

function oneMoreThan(x: Field) {
return x.add(1);
}

let n_heads = Field(0);
for (let i = 0; i < 5; i++) {
const x = Field.random();
const new_n_heads = Provable.if(x.isEven(), oneMoreThan(n_heads), n_heads);
n_heads = new_n_heads;
}