控制流

控制流是大多数编程语言中的基本构建块,它允许根据条件运行一些代码,并在某个条件为真时重复运行一些代码。让您控制Cairo代码执行的最常见结构是if表达式和循环。

if表达式

if表达式允许根据条件分支代码。您提供一个条件,然后声明:“如果满足此条件,请运行此代码块。如果条件不成立,请不要运行此代码块。”

文件名:main.cairo

use debug::PrintTrait;

fn main() {
    let number = 3;

    if number == 5 {
        'condition was true'.print();
    } else {
        'condition was false'.print();
    }
}

所有if表达式都以关键字if开头,后跟条件。在这种情况下,条件检查变量number是否具有等于5的值。我们将要执行的代码块放在条件后面的花括号内,用于执行条件为true的条件块。

可选地,我们还可以包含else表达式,我们选择在这里使用它,以便程序有替代代码块可执行,如果条件评估为false。如果您不提供else表达式并且条件为false,则程序将跳过if块并继续执行下一段代码。

尝试运行此代码; 您应该会看到以下输出:

$ cairo-run main.cairo
[DEBUG]	condition was false

让我们尝试更改number的值,以使条件为真,看看会发生什么:

let number = 5;
$ cairo-run main.cairo
condition was true

还值得注意的是,此代码中的条件必须是bool类型。如果条件不是bool,则会出现错误。

$ cairo-run main.cairo
thread 'main' panicked at 'Failed to specialize: `enum_match<felt252>`. Error: Could not specialize libfunc `enum_match` with generic_args: [Type(ConcreteTypeId { id: 1, debug_name: None })]. Error: Provided generic argument is unsupported.', crates/cairo-lang-sierra-generator/src/utils.rs:256:9

使用else if处理多个条件

您可以通过将if和else组合在else if表达式中来使用多个条件。例如:

文件名:main.cairo

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();
    }
}

这个程序有四个可能的路径。运行它后,您应该会看到以下输出:

[DEBUG]	number is 3

当此程序执行时,它依次检查每个if表达式,并执行第一个条件为真的主体。请注意,即使number - 2 == 1为真,我们也看不到输出number minus 2 is 1' .print(),也没有从else块中看到not found文本。这是因为Cairo仅执行第一个真条件的块,并且一旦它找到一个条件,它甚至不会检查其余部分。使用太多的else if表达式可能会使您的代码混乱,因此如果有多个,您可能需要重构代码。第5章描述了用于这些情况的强大的Cairo分支结构,称为match。

在let语句中使用if

因为if是一个表达式,我们可以在let语句的右侧使用它,将结果赋给一个变量。

文件名:main.cairo

use debug::PrintTrait;

fn main() {
    let condition = true;
    let number = if condition {
        5
    } else {
        10
    };

    number.print();
}

在这个例子中,我们声明了一个变量condition并将其设置为true。然后我们定义了一个新变量number,并使用if表达式初始化它。如果条件为真,则将5分配给number。否则,将10分配给number。

最终,我们调用print()方法来打印变量的值。尝试运行此程序,您应该会看到输出:

[DEBUG]	5

循环

循环结构允许您多次执行一种或多种操作。Cairo支持while和for循环。

while循环

while循环不断地重复执行代码,直到条件为false为止。例如,以下代码片段计算从1到10的数字的总和:

文件名:main.cairo

use debug::PrintTrait;

fn main() {
    let mut sum = 0;
    let mut i = 1;

    while i <= 10 {
        sum += i;
        i += 1;
    }

    sum.print();
}

在这个例子中,我们定义了两个变量:sum和i。我们使用while循环来重复执行代码块,每次将i添加到sum中,然后递增i的值。当i等于11时,while循环的条件评估为false,并退出循环。

您可以使用类似的方式编写无限循环:只需编写while true或while 1就可以了。

for循环

for循环是一种更常见的循环结构,它按照一定的步骤重复执行代码。例如,以下代码片段打印从1到10的数字:

文件名:main.cairo

use debug::PrintTrait;

fn main() {
    for i in 1..11 {
        i.print();
    }
}

在这个例子中,我们使用for循环将i从1逐步增加到10,并在每次迭代时打印它的值。请注意,1..11是一个范围对象,表示从1到10的整数(包括1,但不包括11)。您可以使用类似的方式声明其他类型的范围:例如,'a'..'z'将为字母a到z创建一个范围。

break和continue语句

Cairo还支持break和continue语句,它们可以在循环内部控制执行流程。

break语句用于立即停止当前循环并退出该循环。例如,以下代码片段计算从1开始的第一个平方和大于100的数字:

文件名:main.cairo

use debug::PrintTrait;

fn main() {
    let mut sum = 0;
    let mut i = 1;

    loop {
        let square = i * i;

        if sum + square > 100 {
            break;
        }

        sum += square;
        i += 1;
    }

    sum.print();
}

在这个例子中,我们使用loop语句来创建一个无限循环。在每次迭代中,我们计算当前数字的平方并检查是否将其添加到sum中将使得sum超过100。如果是这样,我们使用break语句停止循环。否则,我们将数字的平方添加到sum中,并递增i的值。

continue语句用于立即跳过当前迭代并开始下一次迭代。例如,以下代码片段打印从1到10之间的偶数:

文件名:main.cairo

use debug::PrintTrait;

fn main() {
    for i in 1..11 {
        if i % 2 == 1 {
            continue;
        }

        i.print();
    }
}

在这个例子中,我们在for循环内部使用if表达式来检查i是否为奇数。如果是这样,我们使用continue语句跳过该迭代。否则,我们打印数字的值。因此,我们只会看到输出2、4、6、8和10。

总结

控制流是编程中非常重要的概念,它允许您根据条件运行一些代码,并在某些情况下重复运行一些代码。Cairo支持if表达式、while循环和for循环。您还可以使用break和continue语句来控制循环内部的执行流程。熟练掌握这些结构对于编写高效和可读性良好的代码至关重要。