Az Algol68 programozási nyelv

Amőba példaprogram


Szofver minőségi követelményei

Az alábbi fejezetben elsősorban arra szeretnék rávilágítani, hogy az Algol68 mennyiben felel meg a szoftvertermékkel szemben támasztott minőségi követelményeknek. Ezek a szempontok: helyesség, megbízhatóság, karbantarthatóság, újrafelhasználhatóság, barátságosság, hatékonyság, stb. A nyelv kialakításánál figyelembe vett szempontok: az ortogonalitás és a kiterjeszthetőség. Az volt a szándék, hogy általános célú programozási nyelvet hozzanak létre. A nyelv magjában kevés alapkonstrukció van, ezek kombinálásával újakat hozhatunk létre, ezeket elég széles körben alkalmazatjuk. Ez az előnyös tulajdonsága vezetett oda, hogy pl.: a C++ nyelv tervezésekor sokszor visszanyúltak az Algol68-hoz, joggal nevezhetjük a "programozási nyelvek latinjának". Azonban az Algol68 kialakulása és elterjedése óta felmerültek a szoftvertermékekkel szemben olyan elvárások, amelyek akkoriban még nem jelentek meg. Kiderült, hogy a szoftvertermékek kapcsán felmerülő költségek legnagyobb része a program karbantartása, pontosabban a programok nehéz karbantarthatósága miatt merül fel.

Az Algol68-ban még nem jelentek meg az osztályok, amelyek a mai minőségi elvárásoknak leginkább megfelelnek. A modularizáció, részfeladatokra bontás fontos kérdés nagy projektek fejlesztése során. Bár az Algol68-ban is léteznek eljárások, amelyek bizonyos fokig modularizációt valósítanak meg, segítségükkel átláthatóvá válik a program.

A megbízhatóság szempontjából fontos megjegyezni, hogy a nyelv erősen típusos, és számos módon lehetőséget ad a programozónak saját típusok létrehozására is. Az automatikus típuskonverzió persze segít azáltal, hogy biztosítja azon típusok között az értékadás lehetőségét, ahol ez még nem veszélyezteti a biztonságosságot.

Az Algol68 tervezői - a ma már furcsaságszáma menő - megoldásokkal: pl.: az operátorok és közöttük lévő a prioritási sorrend átdefiniálásával talán egy kicsit "túllőttek a célon". Ez a megoldás már önmagában is nagyban csökkenti a program olvashatóságát, újrafelhasználhatóságát és ezzel a karbantarthatóságot is. Természetesnek gondoljuk, hogy ha két egész szám között "+" jel van, akkor az az összeadást jelenti. Nem biztos, hogy szükséges az egészek közötti összeadást átdefiniálni. Ha arra van szükség, hogy valamilyen új típust alkossunk (amely az egészeknek résztípusa), és ezek közötti műveleteket szeretnénk felüldefiniálni, ma már erre az osztály tökéletesen megfelel. (Pl.: modulo 7 maradékosztály típus, ebben az esetben pl.: 5+3=1, ilyen esetet tudok elképzelni, amelyben felmerülhetett az az operátor felüldefiniálásának kérdése). Ezáltal, ha valaki egy korábban megírt programot szeretne továbbfejleszteni, komoly nehézségeket okoz egyáltalán a meglévő program megértése is, amely sok értékes programozói munkaórát elrabol.

Ennél is nagyobb galibát okoz a műveletek prioritásának felüldefiniálása. Úgy érezhetnénk, hogy a helyességet veszélyezteti, hiszen egy leírt műveletsor eredménye nem felel meg a matematikailag. (Bár ha úgy specifikáljuk a feladatot, hogy pl.: az összeadás legyen magasabb rendű művelet, mint a szorzás, akkor a helyesség rendben van). Ez a nagyfokú szabadság a karbantarthatóságot szintén nagyban veszélyezteti. A számok közötti műveletek eredményének matematikai helyessége szintén egy "természetes elvárás".

Összegezve elmondható, hogy a nyelv tervezése során említett ortogonalitás és ehhez kapcsolódó nagyfokú szabadság, alapötletként jó, hiszen új távlatokat nyit meg a programozó előtt, lehetőségeket ad, ami nagyon fontos egy általános célú nyelv kialakításánál. Azonban szem előtt kell tartani azt is, hogy egy programot nem feltétlenül egy ember fejleszt, így szükség van bizonyos "kompromisszumokra", korlátozásokra, amelyek segítségével a programozók "megértik egymást". Ezen kívül bizonyos esetekben a szabad változtatás esetében meg kell vizsgálni, hogy egyáltalán szükséges-e, illetve "megéri-e" (nem okoz több problémát, mintha nem valósítanánk meg).

A nyelv kihalásához vezető okok

Eddigiekben arról beszéltem, miért nem felelne meg sok szempontból az Algol68 nyelv a mai elvárásainknak. Mi vezetett azonban a nyelv kihalásához? Ezért is a már sokat említett ortogonalitás tehető felelőssé. Egyrészt a programozás ebben a nyelvben elég nehézkes volt, így hát nem csoda, hogy nem terjedt el. További jelentős problémát jelentett, hogy a programozási nyelvben kialakított funkciókat gépi kódra fordítsák. A nyelv túlságosan nagyfokú komplexitása kellően megnehezítette a fordítóprogramok írását. Ez vezetett a nyelv kihalásához. Szintén a kihaláshoz vezető dolognak tartják az Algol68 fájlkezelését is.

Összehasonlítás

Az Algol68 a mai használatos nyelvek közül a Pascal-ra hasonlít a leginkább, bár sok más nyelv tervezésénél is visszanyúltak hozzá (pl.: C++). Ezek miatt mindenképp érdekes és tanulságos lehet a két nyelv összehasonlítása. A két nyelv hasonló célokkal jött létre: segítségével algoitmusokat lehessen implementálni, futtatható legyen az akkori gépeken és hasznos, tanító célzatú, mindenki számára könnyen tanulható legyen. Annak ellenére, hogy úgy tartják a Pascalnak az Algol volt az alapja, láthatjuk, hogy sok lényeges különbség van a két nyelv között. A különbségek többsége abból ered, hogy bizonyos dolgok, amelyek az Algol68-ban még megengedettek voltak, a Pascal-ban már nem azok (esetenként ezzel csökkentve a komplexitást).

  • Kezdve a lexikális elemekkel, érdekes különbség: az Algol68-ban használatos "boldface words" segítségével kulcsszakvak is szerepelhetnek változónévként (jelölés: 'begin , "begin", .begin). A Pascal foglalt szavak használatát változónevekben megtiltja.
  • Lényeges különbség, hogy az Algol68 kifejezésnyelv, a Pascal nem. Az Algol68-ban minden konstrukciónak (az értékadás kivételével) van visszatérési értéke. A Pascal határozottan szétválasztja a "statement"-et és az "expression"-t, a kettő nem keverhető.
  • Lexikális érdekesség, hogy míg Algol68-ban a kommentek jelölésénél a kommentet nyitó és lezáró jel ugyanaz, addig Pascal-ban a {}-ek használatosak. Ezek segítségével elkerülhető, hogy egy komment-vége jel lehagyása (ekkor az Algol68-ban a hátralévő programszöveg kommentté, az abban található komment programszöveggé alakuló) érthetetlen hibaüzenetek tömkelegét hozza elő.
  • A primitív típusok többé-kevésbé megegyeznek a két nyelvben.
  • A tömbökre vonatkozóan ismert, hogy az Algol68-ban megengedett a nem fix hosszúságú tömb. Igazából a tömb hossza nem is része a típusnak. A Pascal-ban viszont meg kell határozni a tömb határait, ezt már nem lehet változtatni. A tömb típusnak itt része a tömb mérete. Ami előrelépés történt a Pascal-ban az Algol68-hoz képest, hogy a tömb indexei tetszőleges skaláris típusú elemek lehetnek, míg Algol68-ban csak egészek. Mindkét nyelvben lehetőség van több dimenziós tömbök használatára.
  • Az Algol68-ban már lehetőség volt unió típus létrehozására, amiről elmondható, hogy azóta csak nagyon kevés nyelvben valósították meg. Az unió az Algol68-ban teljesen biztonságosan használható volt. A Pascal-ban sincs meg ez a konstrukció, azonban megenged olyan rekordokat, amelyek mezőjének több lehetséges alternatívája van (variáns rekordok). Ez a konstrukció hasonlít valamelyest az Algol68 unió típusához, de ez a Pascal-ban nem biztonságos! Ha a programozó hibázik, az eredmény meghatározhatatlan lesz.
  • Mindkét nyelvben megtalálhatók a mutatók (pointerek). Közös tulajdonság, hogy mindkét nyelvben típusos pointerek vannak, előre meghatározott annak az objektumnak a típusa, amire a pointer mutat. Különbség azonban, hogy míg az Algo68-ban van automatikus típuskényszerítés (dereferencing), addig a Pascal-ban nincs. Az Algol68-ban a pointer bármely (megfelelő típusú) objektumra mutathat, míg Pascal-ban csak a heap-ben lévő ("new"-val létrehozott) objektumra, és nem tud a stack-ban lévő, lokális objektumra mutatni. Sőt, csak a heap-beli objektum elejére tud mutatni, egy köztes mezőjére nem.
  • Az eljárásokkal kapcsolatban az a különbség, hogy ezek az Algol68-ban objektumok, míg a Pascal-ban nem. A Pascal-ban egy eljárást meg lehet hívni, neki paramétereket átadni, és gyakorlatilag ennyi, nincs típusa (lévén nem objektum). A Pascal élesen elkülöníti az eljárást (procedure) és a függvényt (function), ez utóbbinak van visszatérési értéke. Az Algol68-ban bármely eljárásnak van visszatérési értéke (lehet void), és ezek típusa - az ortogonalitás miatt - tetszőleges lehet.
  • A fájlok kezelését az Algol68 egészen különösen oldotta meg, bevezette a könyv fogalmát. Ez egy három dimenziós karaktertömb (oldal, sor, karakter). Ennek köszönhetően az egész fájl egyben kezelhető, lehet benne tetszőlegesen ugrálni, tetszőleges helyre írni. A Pascal-ban ettől teljesen eltérő a fájlok használata. A fájl nem objektum, egydimenziós tömbhöz hasonlít a megvalósítása. Két művelet használható: read: következő elem beolvasása, write: következő elem kiírása. Csak a következő elemmel (ez lehet karakter, rekord) lehetséges műveletet végezni.
  • A Pascal-ban lehetőség van a halmaz típus (set) használatára. A set elemei skaláris típusok lehetnek. Az Algol68-ban ez a konstrukció kimaradt, a bits típusnak vannak a halmazhoz hasonló műveletei.
  • Minden blokkstruktúrált nyelvben - az Algol68 és a Pascal is az - szükség van lokális változóra, amely az adott eljáráson (vagy blokkon) belül érhető csak el, ha kiléptünk, gyakorlatilag megszűnik. Az Algol68-ban tetszőleges blokkban deklarálható lokális változó, míg a Pascal ezt csak az eljárás (vagy függvény) dekarációs részében engedi meg.
  • Az operátorok tekintetében is mutatkoznak különbségek. A Pascal-ban operátor csak valós, egész, boolean, skalár és halmaz típusok között lehetséges, nincs opertátor tömbök, rekordok, pointerek vagy fájlok között. A Pascal-ban nem is lehet új operátorokat definiálni. Természetesen nem lehet - a most következő lehetőségek csak az Algol68-ban jelentek meg - predefinit típusok predefinit operátorait felüldefiniálni, illetve megváltoztatni az operátorok prioritásának a sorrendjét.
  • A vezérlési szerkezetek alapvetően hasonlóak a két nyelvben. Az Algol68-ban az if-nél a fi zárja le a szerkezetet, nincs szükség begin end blokkokra. A ciklusoknál a különbség annyi, hogy az Algol68-ban - ez is a nagyfokú szabadságnak köszönhető - a for és a while tetszőlegesen kombinálható. A Pascal-ban a for ciklus lépésköze csak +1 ill. -1 lehet. A Pascal-ban a már említett két konstrukción kívül létezik a hátultesztelős ciklus is (repeat). Az Algol68-ban is elérhető hasonló hatás, köszönhetően annak, hogy a ciklus feltétel nem kell, hogy feltétlenül egy kifejezés legyen. Íme egy példa a hátultesztelős ciklusra Algol68-ban:
    while S1; ... Sn; feltétel do skip od
  • A paraméterátadás tekintetében is mutatkoznak különbségek. Az Algol68-ban csak az érték szerinti paraméterátadás volt a jellemző. A Pascal-ban azonban már megjelent a cím szerinti paraméterátadás is.
  • (A. S. Tannenbaum: A comparison of PASCAL and ALGOL 68, The Computer Journal, 1977 június)

    A különbségeket még hosszasan sorolhatnánk. A cikk a különbségeket azon nyelvi elemek esetében tárgyalja, amelyek valamilyen szinten mindkét nyelvben megtalálhatók. Nem tesz említést pl.: arról az igen lényeges különbségről, hogy míg az Algol68 már elég komoly eszközökkel (Dijstra-féle szemafor) támogatja a párhuzamosságot, addig ez a Pascalból teljesen kimaradt.

    A fentiek alapján elmondható, hogy az Algol68-ban szinte minden tekintetben egy szélesebb eszköztár áll a rendelkezésre (több lehetőség, többet enged meg), mint a Pascal-ban. Persze emiatt lényegesen nehezebb jó fordítóprogramot készíteni az Algol68-hoz. Azon kívül - ahogy már azt korábban említettem - az Algol68-ban a nagyfokú szabadság esetenként nem feltétlenül szükséges, sőt rontja a program újrafelhasználhatóságát.