ローカル変数とスコープ
Moveのローカル変数は、語彙的に(静的)スコープ(観測)されています。新しい変数はキーワードlet
で導入され、同じ名前の以前のローカル変数をシャドウします。ローカル変数は可変であり、直接更新する事も、可変参照を介して更新する事も出来ます。
ローカル変数の宣言
let
バインディング
Moveプログラムはlet
を使用して変数名を値へバインドします。
script {
fun example() {
let x = 1;
let y = x + x:
}
}
ローカルへ値をバインドせずlet
を使用する事も出来ます。
script {
fun example() {
let x;
}
}
ローカルは後で値を割り当てる事が出来ます。
script {
fun example() {
let x;
if (cond) {
x = 1
} else {
x = 0
}
}
}
これは、デフォルト値が提供出来ない場合ループから値を抽出しようとする時役立ちます。
script {
fun example() {
let x;
let cond = true;
let i = 0;
loop {
(x, cond) = foo(i);
if (!cond) break;
i = i + 1;
}
}
}
使用前、変数を割り当てる必要が有ります
Moveの型システムは、ローカル変数が割り当てられる前に使用される事を防ぎます。
script {
fun example() {
let x;
x + x // エラ^!
}
}
script {
fun example() {
let x;
if (cond) x = 0;
x + x // エラー!
}
}
script {
fun example() {
let x;
while (cond) x = 0;
x + x // エラー!
}
}
有効な変数名
変数名は、アンダースコア_
、a
からz
までの_文字、A
からZ
までの文字、0
から9
までの数字を含む事が出来ます。変数名は、アンダースコア_
または a
からz
までの文字で始まる必要が有ります。大文字で始める事は 出来ません。
script {
fun example() {
// 全て有効
let x = e;
let _x = e;
let _A = e;
let x0 = e;
let xA = e;
let foobar_123 = e;
// 全て無効
let X = e; // エラー!
let Foo = e; // エラー!
}
}
型注釈
ローカル変数 の型は、Moveの型システムによってほぼ常時推測出来ます。Moveは、読みやすさ、明確さ、デバッグしやすさで役立つ明示的な型注釈を使用出来ます。型注釈を追加するための構文は:
script {
fun example() {
let x: T = e; // "型Tの変数xは式eへ初期化されます"
}
}
型注釈の例:
module 0x42::example {
struct S { f: u64, g: u64 }
fun annotated() {
let u: u8 = 0;
let b: vector<u8> = b"hello";
let a: address = @0x0;
let (x, y): (&u64, &mut u64) = (&0, &mut 1);
let S { f, g: f2 }: S = S { f: 0, g: 1 };
}
}
注意: 型注釈は常時パターンの右側である必要が有ります
script {
fun example() {
let (x: &u64, y: &mut u64) = (&0, &mut 1); // エラー! (x, y): ... = とする必要が有ります
}
}
注釈が必要な場合
型システムが型を推測できない場合、ローカル型注釈が必要となります。これは通常、ジェネリック型の型引数を推論できない場合発生します。例:
script {
fun example() {
let _v1 = vector::empty(); // エラー!
// ^^^^^^^^^^^^^^^ この型を推測出きませんでした。注釈の追加を試して下さい。
let v2: vector<u64> = vector::empty(); // エラーは有りません
}
}
型システムが分岐コ ード(後続のコードが全て到達不能)の型を推論出来ない場合が有ります。return
とabort
はどちらも式であり、任意の型を持つ事がで出来ます。break
がある場合、loop
は()
型を持ちますが、loop
から抜け出す事が出来ない場合は、任意の型を持つ事が出来ます。これらの型が推論出来ない場合は、型注釈が必要です。例えば、このコード:
script {
fun example() {
let a: u8 = return ();
let b: bool = abort 0;
let c: signer = loop ();
let x = return (); // エラー!
// ^ この型を推測出きませんでした。注釈の追加を試して下さい。
let y = abort 0; // エラー!
// ^ この型を推測出きませんでした。注釈の追加を試して下さい。
let z = loop (); // エラー!
// ^ この型を推測出きませんでした。注釈の追加を試して下さい。
}
}