带标签的控制流

Move支持带标签的控制流,允许您在函数中定义特定标签并将控制权转移到这些标签。例如,我们可以嵌套两个循环,并使用带有这些标签的breakcontinue来精确指定控制流。您可以在任何loopwhile形式前加上'label:形式,以允许直接在那里中断或继续。

为了演示这种行为,我们来考虑一个函数,它接受嵌套的数字向量(即vector<vector<u64>>)并根据某个阈值进行求和,其行为如下:

  • 如果所有数字的总和低于阈值,返回该总和。
  • 如果将一个数字加到当前总和会超过阈值,则返回当前总和。

我们可以通过将向量的向量作为嵌套循环进行迭代,并标记外部循环来编写这个函数。如果内部循环中的任何加法会使我们超过阈值,我们可以使用带有外部标签的break来一次性跳出两个循环:

fun sum_until_threshold(input: &vector<vector<u64>>, threshold: u64): u64 {
    let mut sum = 0;
    let mut i = 0;
    let input_size = vector::length(vec);

    'outer: loop {
        // 跳出到outer,因为它是最近的外围循环
        if (i >= input_size) break sum;

        let vec = vector::borrow(input, i);
        let size = vector::length(vec);
        let mut j = 0;

        while (j < size) {
            let v_entry = *vector::borrow(vec, j);
            if (sum + v_entry < threshold) {
                sum = sum + v_entry;
            } else {
                // 我们看到的下一个元素会突破阈值,
                // 所以我们返回当前的总和
                break 'outer sum
            };
            j = j + 1;
        };
        i = i + 1;
    }
}

这些标签也可以用于嵌套的循环形式,在更大的代码块中提供精确的控制。例如,如果我们正在处理一个大表,其中每个条目都需要迭代,可能会看到我们继续内部或外部循环,我们可以使用标签来表达该代码:

'outer: loop {
    ...
    'inner: while (cond) {
        ...
        if (cond0) { break 'outer value };
        ...
        if (cond1) { continue 'inner }
        else if (cond2) { continue 'outer };
        ...
    }
    ...
}