ChucK : Language Specification > Type
ChucK: 言語仕様 > 型
version: 1.2.x.x (dracula)
型、値、および変数
ChucK は強い型付けを持った言語であり、コンパイル時に全ての型がチェックされます。しかし、このことは ChucK が静的型の言語であることを意味しません。なぜなら、コンパイラおよび型システムは ChucK 仮想マシンの一部であり、そしてそれらは ChucK の動作環境でもあるためです。型システムはコードが正確さと明瞭さを保つことを助け、また、複雑なプログラムの構造化を行ないやすくさせます。また、ChucK は動的な型にも対応しています。マナーに反さない範囲では実行時に型システムへの変更を行なうこともできます。このような動的プログラミングは、on-the-fly programming を行なう際の基本になっています。
この節では、型、値、代入、および変数の扱いかたについて論じます。型とそれらに関連づけられたデータの扱われかたについては、他の強い型付けを持ったプログラミング言語での場合とほぼ同様に考えることができます。(例: 'int' は整数 (integer) の型であり、2 つの整数の加算を行なった場合には、計算結果である第 3 の整数を返すよう定義されています) クラスとオブジェクトを用いることで、既存の型を独自に定義した型によって拡張することができます。この節では、主にプリミティブ型についてのみを扱うこととし、複雑な型の説明については class and objects にて扱います。
型、値、変数についてはサンプルコードもご覧ください。
プリミティブ型
プリミティブ型は単純なデータ型です。これらの型の値は特殊な属性値を持っていません。オブジェクトはプリミティブ型ではありません。プリミティブ型は値によって渡されます。プリミティブ型を拡張することはできません。ChucK におけるプリミティブ型は以下の通りです:
値 (もしくはリテラル)
リテラル値とはコード中で明示的に記述される値のことであり、コンパイラによって型が割り当てられます。以下はリテラル値の記述例です。
整数:
42
整数 (16進記法):
0xaf30
1.323
期間:
5.5::second
上記のコードでは、second が期間を表している既存の変数です。期間についての表現の詳細は manipulating time の節を参照してください。
変数
変数とは、メモリ上でデータが保持されている場所を示すために使われるものです。ChucK では変数は使われる前に宣言されている必要があります。例えば、foo という整数型の変数を宣言するには以下のようにします:
// 'foo' という名前の 'int' 型の変数を宣言します int foo;
宣言された変数に対しては、ChucK 演算子を使うことによって値を代入することができます。この演算子は ChucK で何かをする場合には最もよく使われるもののひとつです。
// 'foo' に 2 を代入 2 => foo;
変数の宣言と代入を同時に行なうこともできます:
// 新しい 'int' 型の変数 'foo' に 2 を代入 2 => int foo;
変数を使うには、変数名を指定します:
// foo の値をデバッグ表示させる <<< foo >>>;
foo の値を更新したい場合には以下のようにします:
// 'foo' の値に 10 を掛け、再び 'foo' に代入します foo * 10 => foo;
以下は期間の表現に関する例です:
// 新しい変数 bar に '5 秒' の値を代入します 5::second => dur bar;
既に bar を定義している場合、既存の定義を使って新たな期間を定義することもできます:
// bar の 4 倍でひと区切り? 4::bar => dur measure;
ChucK のプログラミングでは時間が主要な存在となるため、時間 (time) や期間 (dur) の関連性とそれらの扱いかたについて理解しておくことはとても重要です。それらについての詳細は manipulating time 節で述べます。
参照型
参照型とは Object クラスを継承しているもののことです。いくつかのデフォルトの参照型が定義されています:
- Object : 全てのクラスが直接的/間接的に継承している最も基本的な型です
- array : N 次元の整列された (同じ型の) データの集合です
- Event : 基本的な、拡張可能な、同期メカニズム
- UGen : 拡張可能な unit generator 基底クラス
- string : 文字の連なり
複素数型 *1
FFT の出力に見られるような複素数の値を表すため、2 つの特別なプリミティブ型が用意されています。直行形式と極形式 (polar form) です。a + bi の形式で表現される複素数は以下のように代入できます:
#(2,3) => complex cmp; //cmp は 2 + 3i
#(...) という構文は、それが直行形式による複素数の表現であることを示します。複素数同士では直接的に演算を行なうこともできます:
#(5, -1.5) => complex cmp; // cmp は 5 - 1.5i #(2,3) + #(5,6) + cmp => complex sum; // sum は 12 + 7.5i
複素数の実部 (real parts) と虚部 (imaginary parts) は、それぞれ .re と .im を用いて得ることができます
#(2.0,3.5) => complex cmp; cmp.re => float x; // x は 2.0 cmp.im => float y; // y は 3.5
極形式もまた複素数の等価な表現形式であり、magnitude と phase value とを用いて表されます。極形式で表現した複素数の代入は以下の様にして行ないます。*2
%(2, .5*pi) => polar pol; // pol は 2∠.5π
magnitude と phase value は .mag と .phase を用いて得ることができます。
%(2, .5*pi) => polar pol; pol.mag => float m; // m は 2 pol.phase => float p; //p は .5π
極形式と複素数との間では互いに型変換を行なうことができ、乗算/加算/代入などが行なえます:
%(2, .5*pi) => polar pol; #(3, 4) => complex cmp; pol $ complex + #(10, 3) + cmp => complex cmp2; cmp $ polar + %(10, .25*pi) - pol => polar pol2;