While, For, ループ
Moveは while
、for
、loop
の3つのループ構造を提供します。
while
ループ
このwhile
構文は、条件(bool
の型の式)がfalse
と評価されるまで、本体(unitの型の式)を繰り返します。
以下は1
からn
までの数値の合計を計算する単純なwhile
ループの例です。
script {
fun sum(n: u64): u64 {
let sum = 0;
let i = 1;
while (i <= n) {
sum = sum + i;
i = i + 1
};
sum
}
}
無限ループが許可されます:
script {
fun foo() {
while (true) { }
}
}
break
break
式は、条件がfalse
と評価する前にループを終了するために使用出来ます。例えば、以下のループはbreak
を使用し、1より大きいn
の最小の因数を見つけます。
script {
fun smallest_factor(n: u64): u64 {
//入力が0もしくは1ではないと仮定します
let i = 2;
while (i <= n) {
if (n % i == 0) break;
i = i + 1
};
i
}
}
break
式はループの外部では使用できません。
continue
continue
式はループの残りをスキップし、次の反復処理へ進みます。
このループは、数値が10で割り切れる場合を除き、continue
を使用して1, 2, ..., n
の合計を計算します。
script {
fun sum_intermediate(n: u64): u64 {
let sum = 0;
let i = 0;
while (i < n) {
i = i + 1;
if (i % 10 == 0) continue;
sum = sum + i;
};
sum
}
}
continue
式はループの外部では使用出来ません。
break
とcontinue
の型
break
とcontinue
はreturn
やabort
と同様、任意の型を持つ事が出来ます。以下の例で、この柔軟な型付けが役立つ所を示します。
script {
fun pop_smallest_while_not_equal(
v1: vector<u64>,
v2: vector<u64>,
): vector<u64> {
let result = vector::empty();
while (!vector::is_empty(&v1) && !vector::is_empty(&v2)) {
let u1 = *vector::borrow(&v1, vector::length(&v1) - 1);
let u2 = *vector::borrow(&v2, vector::length(&v2) - 1);
let popped =
if (u1 < u2) vector::pop_back(&mut v1)
else if (u2 < u1) vector::pop_back(&mut v2)
else break; // ここで、`break`の型は`u64`です
vector::push_back(&mut result, popped);
};
result
}
}
script {
fun pick(
indexes: vector<u64>,
v1: &vector<address>,
v2: &vector<address>
): vector<address> {
let len1 = vector::length(v1);
let len2 = vector::length(v2);
let result = vector::empty();
while (!vector::is_empty(&indexes)) {
let index = vector::pop_back(&mut indexes);
let chosen_vector =
if (index < len1) v1
else if (index < len2) v2
else continue; // ここで、 `continue`の型は`&vector<address>`です
vector::push_back(&mut result, *vector::borrow(chosen_vector, index))
};
result
}
}
for
式
このfor
式は、整数型のlower_bound
(包括的)式とupper_bound
(非包括的)式を使用して定義された範囲を反復処理し、範囲の各要素に対してループ本体を実行します。for
はループの反復回数が特定の範囲によって決定されるシナリオ向けで設計されています。
以下はfor
ループの例で、0
からn-1
までの範囲の要素の合計を計算します。
script {
fun sum(n: u64): u64 {
let sum = 0;
for (i in 0..n) {
sum = sum + i;
};
sum
}
}
ループ反復子変数 (上記の例ではi
)は現在数値型(境界から推論)である必要があり、境界0
とn
ここでは任意の数値式へ置き換える事が出来ます。それぞれはル ープの開始時に1回だけ評価されます。反復子変数i
はlower_bound
(この場合は0
)を割り当て、各ループ反復後に増分します。反復子i
がupper_bound
(この場合はn
)へ達するか超えるとループが終了します。
for
ループの中断
と続行
while
ループと同様、break
式をfor
ループ内で使用して途中で終了する事が出来ます。continue
式を使用して、現在の反復をスキップし、次の反復へ進む事が出来ます。以下はbreak
とcontinue
の両方の使用例です。ループは0
からn-1
までの数値を反復処理し、それらを合計します。
3
で割り切れる数値はスキップし(continue
を使用)、10
より大きい数値と遭遇すると停止します(break
を使用)。
script{
fun sum_conditional(n: u64): u64 {
let sum = 0;
for (iter in 0..n) {
if (iter > 10) {
break; // 数値が10より大きい場合はループを終了します
}
if (iter % 3 == 0) {
continue; // 数値が3で割り切れる場合は現在の反復をスキップします
}
sum = sum + iter;
};
sum
}
}
loop
式
loop
式はbreak
とヒットするまでループ本体(型()
の式)をリピートします。
break
がなければ、ループは永遠に続きます。
script {
fun foo() {
let i = 0;
loop { i = i + 1 }
}
}