Perl 6を語る(第2回)変数の宣言と型制約
第2回はPerl 6の変数宣言と型制約について説明していきます。
新規のローカル変数を宣言するにはmy 変数名
という構文を使います。これはPerl 5と同じです。
さらにPerl 6はスクリプト言語ですが、TypeScriptやDartのように変数の型を指定することができます。型を宣言する方法はC言語などと一緒で、変数の宣言時に型名を付けます。
変数の型を指定しない場合は「Any」型になる
最初は型を指定せずに変数を宣言する場合を見てみます。変数の型と内容を表示したい場合はWHICH
メソッドを使うと簡単です。
my $hoge; say $hoge.WHICH; # Anyと表示される my Any $hoge; # 丁寧に書くとこうなるが、通常は省略する
Any
はその名の通り「何でも」という意味で、最も制約の緩い型です。JavaScriptなどの言語におけるObject型に相当します。
変数の宣言時に初期値を設定すると、それに応じてデータ型も変わります。
my $hoge_int = 1234; # 整数 say $hoge_int.WHICH; # Int|1234と表示される my $hoge_str = "1234"; # 文字列 say $hoge_str.WHICH; # Str|1234と表示される
プロトタイプオブジェクト(型オブジェクト)とは
上記の例でmy $hoge;
と変数を宣言しただけの場合に$hoge
の中身はどうなるのかというと、「プロトタイプオブジェクト」と呼ばれる特殊なオブジェクトになります。略して「型オブジェクト」です。
型オブジェクト自体を評価すると未定義となり、値としては意味を持ちません。
my $hoge; # 未定義のAnyプロトタイプオブジェクトになる # .definedメソッドで値が定義済みか調べる say $hoge.defined; # False
型オブジェクトは裸の型名を書くことでも得られます。上記のコードを厳密に書くと次のようになります。
my $hoge = Any; # 未定義のAnyプロトタイプオブジェクトになる say $hoge.defined; # False
型宣言の例(Int型)
具体的に型宣言の例を説明していきます。基本中の基本ということで整数オブジェクトである「Int型」を使ってみます。
my Int $int; # 未定義のIntプロトタイプオブジェクトになる say $int.WHICH; # Int say $int.defined; # False my Int $int2 = Int; # 上と同じ
Any型の場合と同様に、単に変数を宣言しただけなので$int
の中身はIntのプロトタイプオブジェクトになります。
この変数に整数以外の値を入れようとするとエラーになり、型制約が機能していることが確認できます。
my Int $int; # 有理数(Rational Number)なのでエラー $int = 1234.5; # Type check failed in assignment to '$int'; expected 'Int' but got 'Rat' # 文字列なのでエラー $int = "1234"; # Type check failed in assignment to '$int'; expected 'Int' but got 'Str'
型オブジェクトの使用用途
型オブジェクト自体は値として意味を持ちませんが、以下のような用途に使用することができます。
コンストラクターメソッドを呼び出す
型オブジェクトからクラスのコンストラクターメソッド(通常はnew
)を呼び出すことができます。
他のプログラミング言語から見ると$int = $int.new;
のように変数からコンストラクターを呼び出すのは変に思うかもしれませんが、型名を何度もハードコーディング(直接書く)しなくて済むというメリットがあります。
my Int $int; # 未定義のIntプロトタイプオブジェクトになる say $int.defined; # False $int = $int.new; # 0に初期化される say $int.WHICH; # Int|0 say $int.defined; # True $int = Int.new; # これでも同じ(ハードコーディング) my Int $int .= new; # 省略形
型変換関数として使う
型オブジェクトを関数として使うことで型変換を行うことができます。
my Int $int; $int = $int(1234.5); # 有理数をInt型に変換。小数部は切り捨てられる say $int; # 1234 $int = $int("1234"); # 文字列をInt型に変換 $int = Int(1234.5); # これでも同じ(ハードコーディング) my Int $int = $int("1234"); # これもOK
値が初期化された後で型変換関数として使うことはできません。
my Int $int = 0; # 初期化しているので型オブジェクトではない # エラー $int = $int("1234"); # Cannot find method 'postcircumfix:<( )>'