Skip to content

変数宣言 ​

本章ではYaoXiangにおける変数宣言の核となる構文を紹介する。他のプログラミング言語の経験があれば、YaoXiangの変数システムは非常に簡潔であることがわかるだろう。すべての宣言が同じ構文モデルを共有している。

統一構文モデル ​

YaoXiangの設計哲学は「万物は統一されている」である。整数の宣言であれ、関数の定義であれ、型の作成であれ、すべて同じ構文を用いる。

name: type = value

これはYaoXiangの最も重要な設計理念である。いくつかの例を見れば、この一貫性が伝わるだろう。

yaoxiang
// 変数宣言
x: Int = 42
name: String = "YaoXiang"

// 関数定義
add: (a: Int, b: Int) -> Int = a + b

// 型定義
Point: Type = { x: Float, y: Float }

言語仕様における変数宣言の形式的な定義は次のとおりである。

('mut')? Identifier (':' TypeExpr)? '=' Expr

平易に言えば次のようになる。任意のmutキーワード、続いて変数名、その後に任意の: 型、最後に= 値である。この構造は言語全体に通じており、一度学べば十分である。

不変変数(デフォルトの挙動) ​

YaoXiangでは、すべての変数はデフォルトで不変である。一度代入したら、もう変更できない。これは言語の安全設計である。

yaoxiang
x = 10
// x = 20   // コンパイルエラー!x は不変である

=で宣言された変数について、コンパイラはスコープチェーンに沿って外側に向かって同名の変数を探索する。見つかれば代入を試み、見つからなければ現在のスコープ内に新しい不変変数を作成する。

yaoxiang
x = 1       // 外側のスコープに x がないため、新しく変数として宣言
x = 2       // 外側の x が見つかるため、代入を試みる → コンパイルエラー!x は不変である

これは少し直感に反するように思えるかもしれない。他の言語を学んだことがあれば、「見つかっているならなぜ代入できないのか」と思うだろう。これはYaoXiangが安全性を最優先しているためである。デフォルトが不変であることは、コードのどこかの角落で変数が意図せず変更される心配がないことを意味する。

mut 可変変数 ​

変数を変更する必要がある場合は、mutキーワードで明示的に宣言する。

yaoxiang
mut counter = 0
counter = counter + 1   // 変更可能
counter = 100           // これも可能

mutにはいくつかの重要なルールがある。

ルール1:mutは明示的な新規宣言であり、コンパイラは外側スコープで同名の変数を探索しない。

yaoxiang
mut x = 10      // 現在のスコープに新しい可変変数 x を作成
mut x = 20      // コンパイルエラー!同じスコープ内に x はすでに宣言されている

ルール2:mutで宣言した変数は、外側スコープの変数と同名にできない(シャドーイングを禁止)。

yaoxiang
x = 10
{
    mut x = 20   // コンパイルエラー!x は外側で宣言済みであり、シャドーイングは許可されない
}

ルール3:同じスコープ内で、各名前は1回しか宣言できない。=でもmutでも同様である。

yaoxiang
x = 10
mut x = 20   // コンパイルエラー!x はすでに宣言済みである

これらのルールにより、各スコープ内で変数名が一意であることが保証され、同名変数が一体どの変数を指しているのかという混乱が生じない。

型推論と明示的な型注釈 ​

YaoXiangはHindley-Milner(HM)型推論アルゴリズムを採用している。コンパイラは記述された値から自動的に型を推論できるため、ほとんどの場合手動で型を書く必要はない。

yaoxiang
x = 42              // コンパイラが Int と推論
name = "YaoXiang"   // String と推論
pi = 3.14159        // Float と推論
is_valid = true     // Bool と推論

型を明示的に指定したい場合(コードの可読性向上や、コンパイラが推論できない場合など)は、: Type構文を使用する。

yaoxiang
count: Int = 100
greeting: String = "Hello"
ratio: Float = 0.618

2つの書き方は完全に等価である。型を省略して書き始め、必要になった時点で型注釈を補える。これによりプロトタイピングが非常に高速になり、最終的なコードの型安全性を損なうこともない。

基本型一覧 ​

YaoXiangには、日常プログラミングのほとんどのシナリオをカバーする基本型が組み込まれている。

Int(整数) ​

yaoxiang
a = 42              // 十進数
b = 0o52            // 八進数(0o プレフィックス)
c = 0x2A            // 十六進数(0x プレフィックス)
d = 0b101010        // 二進数(0b プレフィックス)
e = 1_000_000       // 数字をアンダースコアで区切って読みやすくできる

Float(浮動小数点数) ​

yaoxiang
pi = 3.14159
speed = 2.998e8         // 科学的記数法:2.998 × 10^8
tiny = 1.6e-19

String(文字列) ​

yaoxiang
name = "YaoXiang"
empty = ""              // 空文字列
escape = "Hello\nWorld" // エスケープ対応:\n 改行、\t タブ、\\ バックスラッシュ、\" ダブルクォート
unicode = "\u{4F60}\u{597D}"  // Unicodeエスケープ

Bool(ブール) ​

yaoxiang
is_ready = true
is_done = false

ブール値は通常条件判定に使用される。

yaoxiang
if is_ready {
    print("処理を開始")
}

変数のスコープ ​

スコープは変数の可視範囲を決定する。YaoXiangのスコープルールは非常にシンプルである。各{}ブロックが新しいスコープを作成する。

基本ルール ​

yaoxiang
{
    x = 10
    print(x)   // アクセス可能:x は現在のスコープ内に存在する
}
// print(x)    // エラー:x はスコープ外では不可視

内側のスコープから外側の変数にアクセスできる。

yaoxiang
outer = "外側にいる"
{
    print(outer)   // 外側の outer にアクセス可能
    inner = "内側にいる"
}
// print(inner)    // エラー:inner はスコープ外では不可視

関数パラメータのスコープ ​

yaoxiang
greet: (name: String) -> Void = {
    print("こんにちは, " + name)
    // name はこの関数本体内でのみ可視
}
// name は関数外では不可視

ブロック式 ​

YaoXiangの{}ブロックは式でもあり、値を返すことができる。

yaoxiang
result = {
    x = 10
    y = 20
    return x + y   // 30 を外側のスコープに返す
}
// result の値は 30
// x と y はブロック外では不可視

ブロックの戻り値の詳細については、続く関数の章を参照してほしい。ここで覚えておくべきは波括弧はスコープを作成し、内側から外側は見えるが、外側から内側は見えないということだけである。

まとめ ​

これでYaoXiangの変数システムの核心となるコンセプトを習得した。

コンセプト要点
統一構文モデルname: type = value、変数・関数・型すべてに同じ構文を使用
デフォルトで不変x = 10の後、xは変更不可
可変変数mutで明示的に宣言 mut x = 10
シャドーイング禁止同じスコープ内で同じ名前は1回しか宣言できない
型推論HMアルゴリズムによる自動推論、: Typeでの明示注釈も可能
スコープ各{}がスコープを作成、内から外は見えるが、外から内は不可視

続いて基本型の詳細を学ぶか、直接制御フローの章に進むことができる。