Chapter 5 複数の戻り値があるプロシージャ
チャプタ5では、プロシージャについて説明し、一つの戻り値があるプロシージャの使い方を示しました。しかし、多くのシナリオでは、この章で説明する様な複数の戻り値があるプロシージャを使う必要があります。
チャプタ5では、一つの戻り値があるプロシージャを次の様に定義しました。
public procedure name( parameter name 1,parameter name 2,...) : reture type {...}
同様に、次の様に定義される二つの戻り値を持つプロシージャを例にしてみましょう。
public procedure name( parameter name 1,parameter name 2,...) : reture type * reture type {...}
このメソッドのコールは…
variable 1, variable 2, ... = module name.procedure name( parameter name 1,parameter name 2,... )
複数の戻り値があるプロシージャを使うとき、次の点に注意する必要があります。
複数戻り値のプロシージャが、ひとつの戻り値を持つプロシージャと一緒に計算される場合には、最初のプロシージャの最後の戻り値のみが含まれています。
次のコードがその例です。2行目が18行目で複数戻り値のプロシージャとして呼ばれる時、最後のひとつはbar()
プロシージャの操作が終わってから導かれるため、最初のふたつの戻り値がこのプロシージャの実行結果となります。
module M {
public foo(u: u64): u64 * u64 * u64 {
let twice: u64;
let quadruple: u64;
twice = 2 * copy(u);
quadruple = 4 * copy(u);
return move(u), move(twice), move(quadruple);
}
public bar(): u64 {
return 2;
}
}
import Transaction.M;
main() {
let x: u64;
let y: u64;
let z: u64;
x, y, z = M.foo(5) + M.bar();
return;
}
複数の戻り値をもつプロシージャは、他の複数戻り値があるプロシージャのパラメータとして機能することができます。
例えば、次のコードブロックで、2行目にある複数戻り値のプロシージャは、25行目の3つのパラメータを持つプロシージャの最初の2つのパラメータとして使われています。
module Test {
public foo(v: u64): u64 * u64 {
let one_less: u64;
let one_more: u64;
one_less = copy(v) - 1;
one_more = move(v) + 1;
return move(one_less), move(one_more);
}
public baz(k: u64, l: u64, m: u64) : u64 {
let z: u64;
z = move(k) + move(l) + move(m);
return move(z);
}
}
import Transaction.Test;
main() {
let x: u64;
let y: u64;
let x0: u64;
let x1 : u64;
x = 7;
x0, x1 = Test.foo(copy(x));
y = Test.baz(Test.foo(move(x)), 0);
return;
}
もし、複数戻り値を持つプロシージャのreturn
ステートメントが、switch
構文なら、全ての分岐における型と戻り値の数が揃っているかどうかをチェックする必要があります。
例えばbar()
プロシージャの戻り値は6行目から10行目にあり、両方の戻り値はu64
型ですが、これはプロシージャの定義と一致しています。
module A {
public foo(t: u64): u64 * u64 {
return (copy(t), 2 * move(t));
}
public bar(k: u64): u64 * u64 {
if (copy(k) != 1) {
return Self.foo(copy(k));
} else {
return 3 * Self.foo(move(k));
}
}
}
import Transaction.A;
main() {
let x: u64;
let y: u64;
let u: u64;
let v: u64;
x, y = A.bar(10);
u, v = A.bar(1);
return;
}
実習
racial_judgement()
プロシージャをBuildCastle
モジュールに追加し、そして「シリアルナンバーに基づく種族を決定し、それに対応する経済力と軍事力を返す」という機能を実行してください。
シリアルナンバーから種族桁(Race digit)を取り出します。ここでは、シリアルナンバーの7番目のデジットを、割り算と剰余演算によって取り出します。
Switchステートメントによって、種族に対応する経済力と戦力を決定します。種族と二つのパワー値の関係は次の様になります。
Race digit | 0, 5 | 1, 6 | 2, 7 | 3, 8 | 4, 9 |
---|---|---|---|---|---|
経済力 | 6 | 8 | 3 | 7 | 4 |
軍事力 | 6 | 3 | 8 | 4 | 7 |
このプロシージャはひとつが経済力用、もう一つが軍事力用に二つのu64型の戻り値を持ちます。
Tips:どうやってn桁の数から、m番目の桁を切り出すの?
- n桁の数で、最初のx個の桁を取り出したいなら、Num / 10n-1 の丸め込み割り算が使えます。この計算の結果は最初のn桁に基づく値になります。例えば「54321 / 105-2 = 54」
- n桁の数で、後ろのx個の桁を取り出したいなら、Num % 10xの剰余演算が使えます。例えば「54312 % 10^2 = 12」
- n桁の数で、真ん中のx桁が欲しい場合、上の二つの問題を一つに変換すると良いでしょう。そして、さらに最終的な値を計算します。