A ChucK operátor
A ChucK operátor (=>
) többszörösen túl van terhelve, jelentése függ a típusoktól, melyeken
használjuk, többfajta hatást fejt ki. Ezek a hatások láncba rendezhetők, kiértékelésük balról jobbra
történik. A ChucK operátor szolgál a ChucK-kal történő munka végzésére (szűrők sorba fűzése).
A ChucK operátor igazából operátorok családja. Az összes ChucK operátor balasszociatív.
Alapvető ChucK operátor
Először essék szó a hagyományos ChucK operátorról (=>
). Mivel balasszociatív, segítségével
bármilyen irányított adat-, taszk- vagy modulfolyam felépíthető (például unit generator-okból), beszélt
nyelvhez hasonló szintaxissal. A (=>
) viselkedése kontextusfüggő. Konkrét
jelentése függ a bal oldalán (chucker) és jobb oldalán (chuckee) szereplő kifejezés típusától, és néha az
entitástól is (változó vagy konstans).
Néhány példa:
// UGen objektumok összekapcsolása - az adatfolyam iránya jól látszik
// (ebben az esetben a => az egyik UGen kimenetét a másik UGen bemenetére köti)
SinOsc b => Gain g => BiQuad f => dac;
// 4-el megnöveli a foo változó értékét és az eredményt egy új 'int' változóba bar-ba helyezi
// (ebben az esetben a => változó értékadást jelöl)
4 + foo => int bar;
// értékek (paraméterek) chuck-olása függvényhez
// (ebben az esetben a => függvényhívást jelöl)
// (a két sor ekvivalens)
( 30, 1000 ) => Math.random2f;
Math.random2f( 30, 1000 );
Explicit értékadó ChucK operátor (@=>
)
A ChucK-ban nincs értékadó operátor (=
), az értékadás is ChucK operátorok segítségével
történik. Eddigi példáink során a (=>
) operátort használtuk értékadásra.
// 4-et értékül adjuk a foo változónak
4 => int foo;
// 1.5-et értékül adjuk a bar változónak
1.5 => float bar;
// 100 ezredmásodpercet értékül adjuk a duh időtartam változónak
100::ms => dur duh;
// a later idő változóba a jelen (now) időtől 5 másodperccel későbbi időt adjuk értékül
5::second + now => time later;
Az @=>
explicit értékadó operátor ugyanígy viselkedik a fenti típusokra. A különbség az,
hogy a @=>
használható objektumok referenciáinak értékadásához, míg a => csak
beépített típusokon működik. A =>
viselkedése objektumokra függ a környezetétől.
// primitív típusok esetén az @=> megegyezik az => operátorral
4 @=> int foo;
1.5 @=> float bar;
// (csak az @=> operátor alkalmazható objektum referenciák értékadására)
// moe referenciáját adjuk értékül a larry objektumnak
// (moe és larry változók ugyannara az objektumra hivatkoznak)
Object moe @=> Object @ larry;
// tömb inicializálás
[ 1, 2 ] @=> int ar[];
// new kulcsszó használata
new Object @=> moe;
Bár elsőre furcsának tűnhetnek a ChucK operátorok, megszűntetik az értékadó operátorok (@=>
és =>
) és az egyenlőségvizsgálat (==
) között más nyelvekben felmerült
kavarodást. A következő nem helyes ChucK utasítás:
// helytelen utasítás ChucK-ban!
int foo = 4;
Aritmetikai ChucK operátorok (+=>
, -=>
, *=>
, /=>
, stb.)
Ezen operátorok segítségével int
vagy float
típusú változókra kombinálhatjuk az értékadást egy művelettel.
// foo tartalmát 4-el növeljük, az eredményt a foo változóban tároljuk
foo + 4 => foo;
// az előző utasítással megegyezik
4 +=> foo;
// foo értékéből kivonunk 10-et, az eredményt a foo változóban tároljuk
// figyelem ez az érték (foo-10), nem pedig (10-foo)!
10 -=> foo;
// foo értékét megduplázzuk, az eredményt a foo változóban tároljuk
2 *=> foo;
// foo értékét 4-el elosztjuk, az eredményt a foo változóban tároljuk
// figyelem ez az érték (foo/4), nem pedig (4/foo)!
4 /=> foo;
Fontos különbséget tenni változó és érték között, mert ezen operátorok nem kommutatívak.
// foo változó értékének T-vel vett maradéka, az eredményt a foo változóban tároljuk
T %=> foo;
// bitenkénti ÉS a bar változóban tárolt érték és a 0xff érték között
// az eredményt a bar változóban tároljuk
0xff &=> bar;
// bitenkénti VAGY a bar változóban tárolt érték és a 0xff érték között
// az eredményt a bar változóban tároljuk
0xff |=> bar;
Aritmetikai operátorok (+
, -
, *
, /
)
Ezen operátorok a C++-beliekhez hasonlóan működnek.
// osztás (és értékadás)
16 / 4 => int four;
// szorzás
2 * 2 => four;
// összeadás
3 + 1 => four;
// kivonás
93 - 89 => four;
Konverziós operátorok
A ChucK az int
típusú értékeket szükség esetén automatikusan konvertálja, de fordítva nem,
ezért ha erre van szükségünk, explicit konverziós operátort kell hasznánunk.
// float és int összege float-ot eredményez
9.1 + 2 => float result;
// float típus explicit kasztolással alakítható int-té
4.8 $ int => int foo; // foo == 4
// a random2f függvény két float típusú értéket vár
Math.random2f( 30.0, 1000.0 );
// int típus implicit konvertálódik float típusúra
Math.rand2f( 30, 1000 );
Moduló (%
)
A moduló operátor megadja az egész, lebegőpontos, időtartam és idő/időtartam osztások maradékát.
// 7 mod 4 (result = 3)
7 % 4 => int result;
// 7.3 mod 3.2 lebegőpontos maradék (resultf = .9)
7.3 % 3.2 => float resultf;
// időtartam maradék (foo = 1::second)
5::second % 2::second => dur foo;
// idő%időtartam maradék
// (bar = az előző 5 mp-el osztható időpillanat óta eltelt idő)
now % 5::second => dur bar;
// szinkronizáláshoz az alábbi kódrészletet szokták alkalmazni
// (then = a következő egész másodperc időpillanata)
1:: second - (now % 1::second) => time then;
Az utóbbi kódrészleteket (idő%időtartam) gyakran használják shredek közti szinkronizációra.
Logikai operátorok (&&
, ||
, ==
, !=
, >
, >=
, <
, <=
)
A logikai operátorok két operandust várnak, és értékük integer 0 vagy 1.
Szemantikájuk a C++-beliekkel egyező.
// azonosan igaz állítások tesztje
if( 1 <= 4 && true )
<<<"horray">>>;
Bitoperátorok (>>
, <<
, &
, |
, ^
)
Ezen operátorok int
értékeken dolgoznak. A logikai operátorokhoz hasonlóan szemantikájuk a
C++-beliekkel egyező.
Növelő/csökkentő operátor (++
, --
)
Működésük a C++-beliekkel megegyező.
4 => int foo;
foo++;
foo--;
Unáris operátorok (!
, +
, -
, new
)
Ezen operátorok megelőzik az operandusukat.
// logikai negálás
if( !true == false )
<<<"yes">>>;
// aritmetikai negálás
-1 => int foo;
// példányosítás
new object @=> object @ bar;