はじめに#
MoonBit プログラムは、次のようなトップレベル定義から構成されます:
型定義
関数定義
定数定義と変数束縛
init関数、main関数、testブロック
式と文#
MoonBit では文と式を区別します。関数本体では最後の句だけが式であり、それが戻り値になります。例えば:
fn foo() -> Int {
let x = 1
x + 1
}
fn bar() -> Int {
let x = 1
//! x + 1
x + 2
}
式には次のものが含まれます:
値リテラル(例:真偽値、数値、文字、文字列、配列、タプル、構造体)
算術演算、論理演算、比較演算
配列要素(例:
a[0])、構造体フィールド(例:r.x)、タプル要素(例:t.0)などへのアクセス変数と(先頭が大文字の)enum コンストラクタ
無名ローカル関数定義
match、if、loop式など
文には次のものが含まれます:
名前付きローカル関数定義
ローカル変数束縛
代入
return文戻り値の型が
Unitの式(例:ignore)
コードブロックには複数の文と 1 つの式を含められ、その式の値がコードブロックの値になります。
変数束縛#
変数は let mut または let を使って、それぞれ可変または不変として宣言できます。可変変数には新しい値を再代入できますが、不変変数にはできません。
定数はトップレベルでのみ宣言でき、変更できません。
let zero = 0
const ZERO = 0
fn main {
//! const ZERO = 0
let mut i = 10
i = 20
println(i + zero + ZERO)
}
注釈
トップレベルの変数束縛は、
明示的な型注釈が必要です(文字列、バイト、数値などのリテラルで定義する場合を除く)
可変にはできません(代わりに
Refを使ってください)
命名規則#
変数名と関数名は小文字の a-z で始める必要があり、文字、数字、アンダースコア、その他の非 ASCII Unicode 文字を含められます。snake_case を使うことを推奨します。
定数名と型名は大文字の A-Z で始める必要があり、文字、数字、アンダースコア、その他の非 ASCII Unicode 文字を含められます。PascalCase または SCREAMING_SNAKE_CASE を使うことを推奨します。
キーワード#
以下はキーワードであり、識別子として使用できません:
[
"as", "else", "extern", "fn", "fnalias", "if", "let", "const", "match", "using",
"mut", "type", "typealias", "struct", "enum", "extenum", "trait",
"traitalias", "derive", "while", "break", "continue", "import", "return",
"throw", "raise", "try", "catch", "pub", "priv", "proof_assert", "proof_let",
"readonly", "true", "false", "_", "test", "loop", "for", "in", "impl", "with",
"guard", "async", "is", "suberror", "and", "letrec", "enumview", "noraise",
"defer", "lexmatch", "where", "declare", "nobreak",
]
予約語#
以下は予約語です。使用すると警告が出ます。将来的にキーワードになる可能性があります。
[
"module", "move", "ref", "static", "super", "unsafe", "use", "await",
"dyn", "abstract", "do", "final", "macro", "override", "typeof", "virtual", "yield",
"local", "method", "alias", "assert", "package", "recur", "using", "enumview",
"isnot", "define", "downcast", "inherit", "member", "namespace", "static", "upcast",
"use", "void", "lazy", "include", "mixin", "protected", "sealed", "constructor",
"atomic", "volatile", "anyframe", "anytype", "asm", "await", "comptime", "errdefer",
"export", "opaque", "orelse", "resume", "threadlocal", "unreachable", "dynclass",
"dynobj", "dynrec", "var", "finally", "noasync", "assume",
]
プログラムのエントリ#
init と main#
init 関数という特別な関数があります。init 関数には次の特徴があります:
引数リストも戻り値型も持ちません。
同じパッケージ内に複数の
init関数を定義できます。init関数は、他の関数から明示的に呼び出したり参照したりできません。代わりに、パッケージ初期化時にすべてのinit関数が暗黙的に呼び出されます。したがって、init関数は文のみで構成する必要があります。
fn init {
let x = 1
println(x)
}
main 関数という別の特別な関数もあります。main 関数はプログラムの主エントリであり、初期化段階の後に実行されます。
init 関数と同様に、引数リストも戻り値型も持ちません。
fn main {
let x = 2
println(x)
}
前の 2 つのコード例は、実行時に次を出力します:
1
2
このような main 関数を定義できるのは main パッケージだけです。詳しくは ビルドシステムチュートリアル を参照してください。現在のプロジェクトでは、これは moon.pkg で次のように設定します:
options(
"is-main": true,
)
test#
test ブロックというトップレベル構造もあります。test ブロックでは次のようにインラインテストを定義できます:
test "test_name" {
assert_eq(1 + 1, 2)
assert_eq(2 + 2, 4)
debug_inspect([1, 2, 3], content="[1, 2, 3]")
}
以降では test ブロックと main 関数を使って実行結果を示します。特に断りがない限り、すべての test ブロックは成功すると仮定します。