SuperColliderで用意されているDictionaryクラスに初挑戦してみた。
連想配列と一口に言っても言語によって実装はまちまち。PHPでは配列と連想配列に区別はなくどちらもArrayだし、Javascriptでは連想配列はオブジェクトとして扱われ配列とは別だ。ま、詳しくはないんだけど、とにかく各言語によって違うのは確か。
ちなみに、スパコと同じくSmalltalkの系譜を引くObjective-Cにはその名もズバリNSDictionaryクラスが存在する。ので、手持ちのCocoaプログラミングの本で辞書のページを引いてみたがやはりひと言で説明するのは難しい。まぁ、平たく言うとキーと値をセットにして複数保存しておける仕組みのことだ。
使いかたは、newメッセージで辞書を作りaddメッセージで辞書に項目を足していく。
d = Dictionary.new; d.add('monkey' -> 0).postln; d.add('robot' -> 1).postln;
このコードで↓のような辞書ができる。
Dictionary[ (monkey -> 0), (robot -> 1) ]
辞書ができたら引かなければならない。参照するには配列と同じatメッセージを使う。
d.at('robot');
この結果はrobotをキーとする値だから、「1」になる。削除は同様にremoveAtメッセージを使う。
SuperColliderで面白いのは、キーと値の両方がどんなオブジェクトでもOKというところ。2つのオブジェクトをキーと値のセットとして辞書に追加するにはputメッセージを使う。
d.put("abc", 10);
そして、matchAtメッセージを使えば、キーが単一のオブジェクト(数値や文字列)の場合はatメッセージと同様キーと渡した値が一致した場合、キーが配列の場合は配列内に渡した値が存在するかどうか、さらにはキーが関数の場合、返り値がtrueだった場合に値を返す。詳細はヘルプ参照のこと。つまり、内部が完全にブラックボックスでとりあえず渡した値に対応する結果を返す辞書が作れるということ。
しかし、だからといって使い道はあんまり思い浮かばないが…。MIDIノートナンバーの配列を渡して、メジャーかマイナーか返してくれる辞書が作れたりするのかな。トライアドなら展開形を含めても3パターンなので、結構すぐ作れそうだ。
追記:
メジャーかマイナーかを返すDictionaryを作ってみた。
d = Dictionary[ {arg x; x.sort; if( ( ( ( x.at(1) - x.at(0) ) == 4 ) && ( ( x.at(2) - x.at(1) ) == 3 ) ) || ( ( ( x.at(1) - x.at(0) ) == 3 ) && ( ( x.at(2) - x.at(1) ) == 5 ) ) || ( ( ( x.at(1) - x.at(0) ) == 5 ) && ( ( x.at(2) - x.at(1) ) == 4 ) ), { true }, { false } ); } -> 'M', {arg x; x.sort; if( ( ( ( x.at(1) - x.at(0) ) == 3 ) && ( ( x.at(2) - x.at(1) ) == 4 ) ) || ( ( ( x.at(1) - x.at(0) ) == 4 ) && ( ( x.at(2) - x.at(1) ) == 5 ) ) || ( ( ( x.at(1) - x.at(0) ) == 5 ) && ( ( x.at(2) - x.at(1) ) == 3 ) ), { true }, { false } ); } -> 'm' ]; d.matchAt([60,64,67]); // C d.matchAt([60,63,67]); // Cm d.matchAt([55,60,64]); // C/G
Dictionaryでやる意味があるのかいまいち分かんなくなってきた…。