A Pascal nyelvtanban a legalapvetőbb komponens ami egy metódus testet alkot, egy statement (“állítás”). Egy metódus test listája a statementeknek, elválasztva pontosvesszővel egymástól őket. x := 5 egy statement, akárcsak a MyObject.DoSomething. A begin/end blokk szintén egy statement, ami többek között saját magába is beágyazható, illetve tartalmazza egy listáját további statementeknek.
Van egy speciális típusa a statementeknek, amik elég gyakran használtak, ezek pedig a kifejezések (expressions). Egy kifejezés egy statement, aminek van egy értéke és így felhasználható bármilyen kód konstrukcióban ami elvár egy értéket, úgy mint jobb oldalán egy hozzárendelésnek, aritmetikai formulákon belül, vagy mint paraméter egy másik metódusra például. Az 5 egy kifejezés, így a MyObject.ToString is.
A korai Pascal nyelvekben (még a Delphi előtt), a kifejezések nem kellett, hogy full statementek legyenek. Például, a függvények (eljárások, amik visszaadnak egy értéket) nem voltak hívhatóak a visszatérési érték használata nélkül. Más szóval, például az sqrt(9) önmagában nem volt egy érvényes statement, de az x := sqrt(9) igen. Ez egy dolga a múltnak.
Funkcionális programozás
Na hova akartam én mindezzel kijukadni? Nos, az eljövő Spring 2010-es kiadásával a Delphi Prism-nek a fejlesztők kiterjesztették a nyelvet. Van három közösen használt statement, melyet innentől fogva mint kifejezéseket fog kezelni a fordító. Ezek a lépések szükségesek voltak ahhoz, hogy több funkcionális programozási koncepció kerülhessen a nyelvbe. A funkcionális programozás egy egészen különböző paradigma, és mint kiderült nagyon jól használható hatékony többszálú kód írásához (lsd. Erlang vagy Haskell). A Microsoft is fokozta a munkát az F#-on, ami a .NET-hez készített első saját funkcionális nyelvük lesz, melyet a VS 2010 is tartalmazni fog többek között.
A Prismhez a fejlesztők egy kissé másfajta megközelítést választottak. Kiterjesztik a nyelvet további funkcionális nyelvi elemekkel, de a cél továbbra is ezek síkban tartása a tradícionális Pascal szintaxissal és érzéssel. Az F#-nak például van néhány érdekes koncepciója ami erőteljessé teszi a nyelvet, de istentelen és közel érthetetlen szintaxis.
A következő új kifejezés típusok az első lépések ebbe az irányba Delphi Prism részről:
“if” kifejezések
Az “if” statement engedi a feltételes futtatását egyik vagy másik statementnek, egy boolean feltételtől függően. Ez gondolom idáig nem új:
if Condition then ThenStatement else ElseStatement;
A kulcsszó itt a statement. Mind a then és az opcionális else ág tartalmaz egy statement-et (nem egy kifejezést!). A teljes “if” kikötés egy statement (de egy kifejezésen). A fejlesztők most kiterjesztették ezt a szintaxist, engedve a teljes “if” kikötést kifejezéssé válni:
if Condition then ThenExpression else ElseExpression;
A teljes konstrukció egy kifejezés, reprezentálva az értékét a ThenExpression vagy ElseExpression-nek. Ennek következtében például a következő szintaxis a jövőben teljesen érvényes:
var s := 'The Condition is ' + if Condition then 'true' else 'false';
A típusa az “if” kifejezésnek (jelen esetben string) a két kifejezés legkisebb közös nevezője által kerül meghatározásra. Amenyiben az opcionális else ág hiányzik, az eredmény egy false feltételhez nil lesz, illetve ha a then kifejezésnek a típusa egy érték típus, akkor az “if” kifejezés egy nullázható típus lesz. Példa:
var x := if Condition then 3;
Az “x” egy nullázható Int32 típus lesz és tartalmazni fogja a 3 vagy nil értékek egyikét a feltétel teljesülésétől függően.
Egyesek most biztos bekeverik ide a C# conditional operátorát (?:), ami egyébként Delphi Prism-ben szintén van iif néven, de ez nem arról szól, hanem magáról a C# if statementjéről is, ha úgy tetszik. Persze az kérdés, hogy a C#-ot mennyire akarják elvinni funkcionális irányba.
“case” kifejezések
Ugyanez a kiterjesztés vonatkozik a “case” statementekre szimmetrikusan. Egy case statement, ahol minden egyes eset egy kifejezés, önmaga is egy kifejezéssé válik. Mint korábban az “if” kifejezésnél, a típus a tartalmazott kifejezések legkisebb közös nevezője által kerül meghatározásra, illetve ha nincs else statement, akkor nullázható lesz:
var s := case Number of 1: 'One'; 2: 'Two'; else 'Many'; end;
A lényeg valójában az, hogy a kifejezések csak altípusai a statementeknek, melyeknek van egy értékük. S persze ha jobban belegondolunk a fentiekbe, akkor valóban látszik, hogy semmi ok nincs azt gondolni, hogy a fenti statementeknek/kifejezéseknek nem kellene legyen értékük, ezért is innentől kezdve ezek önmagukban is véve kifejezések a nyelvben.
“for” kifejezések
Az utolsó új típusa a kifejezéseknek a “for” kifejezések:
for each x in SomeSequence yield Expression;
és
for x := StartValue to EndValue yield Expression;
Elsőre ránézésre az tűnhet fel, hogy a do kulcsszó ki lett cserélve egy yield-el. Ez főként azért van így, mert a yield-nek sokkal több értelme van egy kifejezés kontextusában. A do inkább futtatásra utal, míg a yield inkább értékre utal minden ciklus iterációban. Ha ez valakinek ismerősen hangzik a Delphi Prism iterátorainál megszokottakhoz, akkor az nem véletlen. Egy “for” kifejezésnek nagyon hasonló tulajdonságai vannak, illetve iterátori viselkedése, így nevezhetjük őket akár “anonymous iterators”, azaz névtelen iterátoroknak is.
Tehát mi egy értéke egy “for” kifejezésnek? Az értéke egy “for” kifejezésnek egy szekvencia, tartalmazva minden egyes kifejezést. Példa:
var SomeNumbers := sequence of Int32; // IEnumerable<Int32> SomeNumbers := for i: Int32 := 0 to 100 yield i * i; // SomeNumbers tartalmazza 0-tól 100-ig az egész számok négyezeteit
Pont mint egy iterátor, ez a szekvencia is on-the-fly lesz generálva, amikor felsorolttá válik. A fenti példában nincs kód ami futna, hogy kalkulálja a számokat 0 –tól 10000-ig. A “for” loop maga egy O(1) művelet. Ez nincs addig, amíg hozzá nem férünk a szekvenciához, például egy másik for each loop használata által. Újra:
var AllInts := for i: Int64 := 0 to Int64.MaxValue yield i;
Ez például egy szekvenciájává válik minden pozitív Int64 értéknek, de a tényleges hozzáférés csak itt következik be:
for each x in AllInts index i do begin if i <= 1000 then break; Console.WriteLine(x); end;
Ezek az új kifejezéstípusok is már részét képezik az új Delphi Prism 2010 “Spring”-nek, ami hamarosan értkezik a Visual Studio 2010-el.