Control Flow in Cairo#
This article uses the Cairo compiler version: 2.0.0-rc0. Since Cairo is being rapidly updated, the syntax may vary slightly in different versions, and the article content will be updated to the stable version in the future.
if statement#
use debug::PrintTrait;
fn main() {
let number = 3;
if number == 3 {
'condition was true'.print();
}
}
It is easy to use and does not require enclosing the condition in parentheses.
Let's take a look at the case of multiple conditions:
use debug::PrintTrait;
fn main() {
let number = 3;
if number == 12 {
'number is 12'.print();
} else if number == 3 {
'number is 3'.print();
} else if number - 2 == 1 {
'number minus 2 is 1'.print();
} else {
'number not found'.print();
}
}
The execution order of multiple conditions is from top to bottom. Once a condition is satisfied, it will exit and no longer evaluate the remaining conditions. In the example above, the second condition number == 3
is already satisfied, so even if the third condition is true, it will not be executed.
Special if statement, achieving the same effect as the ternary operator#
This statement combines the let
statement and the if
statement together.
use debug::PrintTrait;
fn main() {
let condition = true;
let number = if condition {5} else {6};
if number == 5 {
'condition was true'.print();
}
}
In the above code, if condition
is true, number
will be assigned as 5; if condition
is false, number
will be assigned as 6.
The ternary operator in Solidity is as follows:
bool condition = true;
uint256 a = condition ? 5 : 6;
loop statement#
loop
allows for an infinite loop, and control can be achieved using continue
and break
. Let's first look at an example:
use debug::PrintTrait;
fn main() {
let mut i: usize = 0;
loop {
i += 1;
if i < 10 {
'again'.print();
continue;
}
if i == 10 {
break ();
};
}
}
In the above code, i
is incremented, and when it is less than 10, it will continue to the next iteration using the continue
instruction. The logic after continue
will not be executed. When i
is equal to 10, it will break out of the loop using the break
instruction.
- A return value needs to be added after
break
, and if there is no return value, the unit type()
is used. It cannot be omitted.
Note: When executing Cairo code with loop
, the --available-gas
option needs to be used to specify the gas limit. For example:
cairo-run --available-gas 200000 $CairoFile
Obtaining the return value of loop#
As mentioned earlier, break
must be followed by a return value, and we can obtain this return value:
use debug::PrintTrait;
fn main() {
let mut i: usize = 0;
let t = loop {
i += 1;
if i >= 10 {
break i;
};
};
t.print();
}
The final value of t
in the above code is 10.
Commonality of if and loop: Obtaining the result of an expression#
Both if
and loop
can be combined with let
to obtain the result of an expression, which is the return value of the code block inside the curly braces. For example:
let number = if condition {5} else {6};
and
let t = loop {
i += 1;
if i >= 10 {
break i;
};
};
In Cairo, the common way to obtain the result of an expression is to directly get the return value of the code block inside {}
.
use debug::PrintTrait;
fn main() {
let y = {
let x = 3;
x + 1
};
y.print();
}
The value of y
in the above code is 4.
The combined syntax of if
, loop
, and let
can be understood as syntactic sugar based on the common way of obtaining the result of an expression.