制御文
一般にプログラムというものは、通常上から順に処理するところを、制御文を使って、処理をループさせたり、条件によって処理を変えたりできる。
かつそこに時間が挟まると、制御構造=楽曲構造、みたいな面白げなことができるのではー
と妄想するのだが、いよいよ難儀なことになりつつあるので、ひとまずどんな制御文があるのかを見てみる。
if
条件に当たった場合と外れた場合で処理を分ける。
if( 10.rand < 5, // 条件 {"boo"}, // 真の場合 {"foo"} // 偽の場合 ).postln;
答えが二つ返ってきますが、あくまで処理は一回であるようです。
ううむ。何度も見てますが、どういう意味なのか未だにわからない。
switch
複数の条件のどれに当たったかで処理を分ける。
条件はいくつでも立てられるのと、どれでもない場合も立てられる。
switch( 4.rand, // 条件 0, {"boo"}, // 0の場合 1, {"foo"}, // 1の場合 {"orz"} // どれでもない場合 ).postln;
do
指定した回数繰り返す。
10.do({ // 10回繰り返す |i| // arg i;と同じ ("do "++i).postln });
argを置くとインクリメントします。妙な書き換えを覚えた。
実はinf.doとすると無限に繰り返すのだが、後述する遅延処理がないとハングして強制終了せざるを得なくなり、HDが爆砕とかPCが炎上とかしがちなのでやめとこう。
(3..7).do({ // 3から7まで |i| ("do "++i).postln });
こんな書き方もできるんだって。forの代替みたいな感じ?
while
条件が当たってる時だけ繰り返します。
q = 0; while( {q != 9}, // 条件(9ではない場合) {q = 10.rand; q.postln} // 真の場合 );
上の例だとサイコロ振って9が出た瞬間終了なので、いつ終わるかは毎回違う。
制御文は他にもあるが、詳しくはControl-Structuresヘルプなどを見よ(ぶん投げ)。
Routine
Routineは、要するに処理の間に待ち時間が作れるようです。
ヘルプ読んだけどyieldとか何に使うのかよくわかりませんでしたので、相変わらず皮相的な理解です。
Routine { "boo".postln; 1.0.wait; // 1拍待つ "foo".postln; }.play;
waitというのを間において、続く処理を遅らせておる。
わざわざ遅れを作って何がありがたいのかというと、これで音楽の時間構造が作れるのでは、という。
loop
放って置けば無限に繰り返します。
r = Routine { loop { "boo".postln; 1.0.wait; } }.play;
wait入れないとHDが液状化とかPCが反物質化とかしますので忘れぬよー。
止めたくなったら
r.stop;
1拍待ちがたりーなーと思ったら、数を0.5とかにするとか
Tempo.tempo = 4; // 1秒あたり4拍
などと予め実行しておくがいいらしい。
なお、Tempoはいじると次にいじるまでそのままなので注意。
wait
waitはいくつでも置ける。
r = Routine { a = 0; loop { a.postln; a = a+3; 1.wait; a.postln; a = a-2; 1.wait; } }.play; r.stop;
さっきのifの例文を自動化してみる。
r = Routine { loop { if( 10.rand < 5, {"boo"}, {"foo"} ).postln; 1.wait; } }.play; r.stop;
loopだけじゃなくてdoとかwhileでもwaitできます。
r = Routine { 10.do({|i| i.postln; i.wait; // 意味なくだんだん遅くなる }); "bang".postln; }.play;
r = Routine { q = 0; while({q != 9}, { q = 10.rand; q.postln; 1.wait; }); "bang".postln; }.play;
では次はRoutineを使った怪しい作曲法について考える。