控制流

通过控制流表达式,我们可以选择运行某个代码块,或者跳过某段代码而运行另一个代码块。

Move 支持 if 表达式和循环表达式。

if 表达式

if 表达式允许我们在条件为真时运行代码块,在条件为假时运行另一个代码块。

module book::c_if {
    use std::debug;

    fun main() {
        let a = true;

        if (a) {
            debug::print<u8>(&0);
        } else {
            debug::print<u8>(&99);
        };
    }

}

这个例子中,当a == true时打印0,当a是false时打印99,语法非常简单:

if (<布尔表达式>) <表达式> else <表达式>;

if是一个表达式,我们可以在 let 声明中使用它。但是像所有其他表达式一样,它必须以分号结尾。

module book::c_if {
    use std::debug;

    fun main() {

        // try switching to false
        let a = true;
        let b = if (a) { // 1st branch
            10
        } else { // 2nd branch
            20
        };

        debug::print<u8>(&b);
    }
}

现在,b 将根据 a 表达式为变量分配不同的值。但是 if 的两个分支必须返回相同的类型!否则,变量 b 将会具有不同类型,这在静态类型的语言中是不允许的。在编译器术语中,这称为分支兼容性 —— 两个分支必须返回兼容(相同)类型。

if 不一定非要和 else 一起使用,也可以单独使用。

module book::c_if {
    use std::debug;

    fun main() {

        let a = true;

        // only one optional branch
        // if a = false, debug won't be called
        if (a) {
            debug::print<u8>(&10);
        };
    }
}

但是请记住,不能在 let 赋值语句中使用不带分支的表达式!因为如果 if 不满足条件,就会导致变量未被定义,这同样是不允许的。

循环表达式

在 Move 中定义循环有两种方法:

  1. while 条件循环
  2. loop 无限循环

while 条件循环

while 是定义循环的一种方法:在条件为真时执行表达式。只要条件为 true,代码将一遍又一遍的执行。条件通常使用外部变量或计数器实现。

module book::c_if {
    fun main() {

        let i = 0; // define counter

        // iterate while i < 5
        // on every iteration increase i
        // when i is 5, condition fails and loop exits
        while (i < 5) {
            i = i + 1;
        };
    }
}

需要指出的是,while 表达式就像 if 表达式一样,也需要使用分号结束。while 循环的通用语法是:

while (<布尔表达式>) <表达式>;

if 表达式不同的是,while 表达式没有返回值,因而也就不能像 if 那样把自己赋值给某变量。

无法访问的代码

安全是 Move 最显著的特性。出于安全考虑,Move 规定所有变量必须被使用。并且出于同样的原因,Move 禁止使用无法访问的代码。由于数字资产是可编程的,因此可以在代码中使用它们(我们将在 Resource 一章中对其进行介绍)。而将资产放置在无法访问的代码中可能会带来问题,并造成损失。

这就是为什么无法访问的代码如此重要的原因。

无限循环

Move 提供了一种定义无限循环的方法,它没有条件判断,会一直执行。一旦执行该代码将消耗所有给定资源(交易费),大多数情况下,编译器也无法判断循环是否是无限的,也就无法阻止无限循环代码的发布。因此,使用无限循环时一定要注意安全,通常情况下建议使用 while 条件循环。

无限循环用关键字 loop 定义。

module book::c_if {
    fun main() {
        let i = 0;

        loop {
            i = i + 1;
        };

        // UNREACHABLE CODE
        let _ = i;
    }
}

下面的代码也是可以编译通过的:

module book::c_if {
    fun main() {
        let i = 0;

        loop {
            if (i == 1) { // i never changed
                break // this statement breaks loop
            }
        };

        // actually unreachable
        std::debug::print<u8>(&i);
    }
}

对于编译器而言,要了解循环是否真的是无限的,这是一项艰巨的任务,因此,就目前而言,只有开发者自己可以帮助自己发现循环错误,避免资产损失。

通过 continuebreak 控制循环

continuebreak 关键字,分别允许程序跳过一轮循环或中断循环,可以在两种类型的循环中同时使用它们。

例如,让我们在 loop 中添加两个条件,如果i是偶数,我们通过 continue 跳转到下一个迭代,而无需执行循环中 continue 之后的代码。当 i 等于 5 时,我们通过 break 停止迭代并退出循环。

module book::c_if {
    fun main() {
        let i = 0;

        loop {
            i = i + 1;

            if (i / 2 == 0) continue;
            if (i == 5) break;

            // assume we do something here
         };

        std::debug::print<u8>(&i);
    }
}

注意,如果 break 和 continue 是代码块中的最后一个关键字,则不能在其后加分号,因为后面的任何代码都不会被执行。请看这个例子:

module book::c_if {
    fun main() {
        let i = 0;

        loop {
            i = i + 1;

            if (i == 5) {
                break; // will result in compiler error. correct is `break` without semi
                       // Error: Unreachable code
            };

            // same with continue here: no semi, never;
            if (true) {
                continue
            };

            // however you can put semi like this, because continue and break here
            // are single expressions, hence they "end their own scope"
            if (true) continue;
            if (i == 5) break;
        }
    }
}

有条件退出 abort

有时,当某些条件失败时,您需要中止程序的执行。对于这种情况,Move 提供了有键字 abort。

module book::c_if {
    fun main(a: u8) {

        if (a != 10) {
            abort 0;
        }

        // code here won't be executed if a != 10
        // transaction aborted
    }
}

关键字 abort 允许程序中止执行的同时报告错误代码。

使用 assert 内置方法

内置方法 assert(<condition>, <code>)abort和条件进行了封装,你可以在代码中任何地方使用它。

module book::c_if {

    fun main(a: u8) {
        assert(a == 10, 0);

        // code here will be executed if (a == 10)
    }
}

assert() 在不满足条件时将中止执行,在满足条件时将不执行任何操作。