💎

【Crystalと○○】Crystalとローカル変数

2021/04/19に公開

📖【Crystalと○○】コンテンツ一覧

Crytalでは値を保持する枠組みとして、ローカル変数、インスタンス変数、クラス変数と定数を利用できます、今回はこの中からローカル変数の使い方や特徴を説明することにしましょう。

ローカル変数の命名規則

Crystalのローカル変数は一般的に小文字のスネークケース(単語の間をアンダースコア _ で繋ぐ方式)が使用されます。

local_var = 1

厳密には、英小文字もしくはアンダースコア(_)で始まり、その後ろに大小の英文字と数字、アンダースコアを使用することができます。さらに、マルチバイトのUTF-8文字(絵文字含む)も英小文字扱いになりますので、次のようなローカル変数名が実は有効です。

# アンダースコア始まり
_local_var = 1

# 大文字を含む
localVar   = 1

# 連続したアンダースコア
__IVAR__   = 1

# マルチバイト文字
日本語      = 1

# 絵文字
🍺         = 1

とはいえ、あまり奇抜な変数名をつけると可読性が下がりますので、余程の事情があるかジョークで使うのでもなければ原則として小文字のスネークケースを使用することをお勧めします。

ローカル変数の型と初期化

ローカル変数は予め宣言しておく必要はなく、いきなり値を代入して使用することができますが、一度も使用していないローカル変数を参照しようとするとコンパイルエラーが発生します。

local_var = 1

p undefined_var
# Error: undefined local variable or method 'undefined_var' for top-level

また、ローカル変数の型は代入される値からコンパイラが自動的に推論してくれるため、型を指定する必要もありません。

一度値を代入したローカル変数に、異なる型の値を再代入することも可能で、その場合、コンパイラはそのローカル変数の型をそれ以降は新しく代入された値の型として扱ってくれます。

local_var = 1
typeof(local_var) #=> Int32

local_var = "a"
typeof(local_var) #=> String

なお、ローカル変数の型を明示的に宣言することも一応可能です。その場合、宣言した型以外の値を再代入しようとすると、型チェックによりコンパイルエラーが発生します。

string_var : String
string_var = 1
# Error: type must be String, not Int32

ローカル変数のスコープ

ローカル変数のスコープは、メソッド中で初期化された場合はそのメソッド内、そうでない場合はそのファイル内になります。

例えば、次の例ではメソッド定義内の変数 var とトップレベルの変数 var は別の変数になります。

var = 1

def foo(new_var)
  var = new_var
end

puts var
#=> 1

一方、次の例ではクラス定義内の変数 var とトップレベルの変数 var は同じものです。

var = 1

class Foo
  var = 2
end

puts var
#=> 2

今回のまとめ

  • Crystalのローカル変数の挙動は、以下の点で動的型システムにおける変数の挙動によく似ている。
    • ローカル変数は事前の宣言が不要で、いきなり値を代入して使用できる
    • 型の指定も不要で、その時点で代入されている型をコンパイラが適宜推論して適切に扱ってくれる
  • 定義場所によるスコープの変化に注意が必要

Discussion