変数とは、値を一時的に記録するためのメモリ領域に名前を付けたものです。一方、定数とは、変更できない値に対して、名前を与えたものです。変数や定数に値を割り当てる操作を、代入と呼びます。
Zenでは、変数はvar
を使用して、定数はconst
を使用して、それぞれ定義します。変数を定義する構文は次の通りです。
const / var 変数名 :型名 バイトアライメント リンクセクション = 式;
:型名
、バイトアライメント
、リンクセクション
は省略可能です。
var
で定義された変数は、実行時にミュータブル (変更可能) であることを意味します。var
で定義された変数は、次の例のように、再代入による値の更新が可能です。
examples/ch02-primitives/src/values.zen:1:8
const std = @import("std");
const ok = std.testing.ok;
test "var" {
var i: u32 = 42;
i = 52;
ok(i == 52);
}
const
はイミュータブルな (変更できない) 値を定義する際に使用します。一度const
で定義した値は、不変値として利用することができます。
examples/ch02-primitives/src/values.zen:10:13
test "const" {
const very_important_number: u32 = 42;
ok(very_important_number == 42);
}
Zenのconst
には2つの意味があります。
全てのconst
で定義された値は、1.の特性を持ちます。すなわち、一度初期化すると、その値を変更することができません。次のコードはコンパイルエラーになります。
test "assign to constant" {
const i: u32 = 42;
i = 52;
}
error: cannot assign to constant
i = 52;
^
コンパイル時計算可能なconst
は、コンパイル時にその値を利用することができます。
test "const in compile time" {
const added: u32 = 1 + 2;
comptime {
ok(added == 3);
}
}
ノート:
comptime
ブロックは、コンパイル時に実行するブロックです。詳しくは、12章 comptimeで説明します。
var
は本質的に実行時の値であるため、このような使い方はできません。
test "var in compile time" {
var added: u32 = 1 + 2;
comptime {
ok(added == 3);
}
}
上のコードは、次のようなコンパイルエラーになります。
error[E04000]: unable to evaluate constant expression
ok(added == 3);
~
可能な場合は常に、var
よりconst
を使用することがベストプラクティスです。
const
が適切に利用されることにより、まず、プログラムの可読性が向上します。const
で定義された値はイミュータブルであるため、プログラマはその値が書き換わらないことを前提にプログラムを読むことができます。
const
で定義された値が誤って再代入されると、コンパイラはエラーを出力し、コンパイルを中断します。const
で値を定義することは、プログラマの誤りを防ぐシートベルトでもあります。
また、const
で定義された値は、コンパイル時により多くの最適化ができる可能性があります。const
には、コンパイル時に計算可能という意味が含まれる場合があることを説明しました。const
がコンパイル時に計算可能である場合、コンパイラはその計算を可能な限りコンパイル時に完了させ、実行時の計算を減らしてくれるでしょう。
Zen言語では変数を定義する時に初期化を省略することができません。
test "Incorrect Initialization" {
var x: i32;
x = 42;
}
上のコードは次のコンパイルエラーを出します。
$ zen test test.zen
test.zen:2:5: error: variables must be initialized
var x: i32;
変数は任意の式で定義できます。
examples/ch02-primitives/src/values.zen:22:24
test "Correct Initialization" {
var x: i32 = 42;
}
ここで式とは、値、変数、演算、関数の組み合わせであるため、次のように変数を初期化することも可能です。
examples/ch02-primitives/src/values.zen:26:41
test "correct initializations" {
var a: i32 = 1;
var b: i32 = a;
var c: i32 = a + b;
var d: i32 = add(a, c);
var e: i32 = add(a, b) + c;
ok(b == 1);
ok(c == 2);
ok(d == 3);
ok(e == 4);
}
fn add(a: i32, b: i32) i32 {
return a + b;
}
変数を定義する時、初期値が決定していない場合があります。Zen言語では変数の初期化は省略できませんため、そのような場合にはundefined
を利用します。
var a: u32 = undefined;
a = 42;
undefined
は配列の初期化を後回しにしたい時、特に便利です。
var array: [100]u32 = undefined;
// ループを回すなどして`array`を初期化する
注意:
undefined
は値が不定値になることに注意して下さい。ただし、デバッグの利便性のため、デバッグビルド時は、各バイトを0xAA
で初期化します。また、一度undefined
で初期化すると、undefined
で初期化されているかどうかは分かりません。
ここまでのサンプルコードでは、初期化時に全ての変数の型を明示的に記述しました。しかし、Zenには型推論の機能が備わっており、Zenコンパイラが推論可能な場所では、型の記述を省略できます。
次の例では、初期化時にb
の型を明示していません。
examples/ch02-primitives/src/values.zen:43:48
test "type inference" {
var a: i32 = 1;
// `b`の型は`a`の型から`i32`に推論される
var b = a;
ok(@TypeOf(b) == i32);
}
しかし、b
の型は、a
の型から推論可能であるため、b
の型はi32
になります。@TypeOf
は引数として与えた値の型を返す組込み関数です。
☰ 人の生きた証は永遠に残るよう ☰
Copyright © 2018-2020 connectFree Corporation. All rights reserved. | 特定商取引法に基づく表示
Zen, the Zen three-circles logo and The Zen Programming Language are trademarks of connectFree corporation in Japan and other countries.