Beszéljünk még emberebbül a számítógéppel!
Korábban belevágtam egy sorozatba, ami arról szól, hogy milyen fontos eltérések vannak az emberi és a számítógépes nyelvek között, és hogy hogyan közelíthetnénk egymáshoz a kettőt. Most folytatom a sorozatot, de megint csak néhány lépést teszek a megoldás felé.
Az előző rész tartalmából
Az előző részben láttuk, hogy a programozási nyelvekben egy-egy eljárás, programrészlet vagy egész program egy csomó különböző valóságos folyamatot írhat le, és az, hogy pontosan hogyan megy végbe a folyamat a program(részlet) végrehajtásától, attól függ, hogy a program paramétereit (változó részeit) hogyan rögzítjük.
Elmeséltem, hogy a programok általában azt várják el, hogy a paramétereiket egy bizonyos sorrendben rögzítsük: onnan „tudják”, hogy melyik paraméter melyik, hogy hanyadikként soroljuk fel őket, amikor leírjuk azt a parancsot, „hívást”, ami a program végrehajtását írja elő. Például ha van egy eljárásunk, ami egy betűsorozatnak (stringnek) egy részét egy másikkal helyettesíti, akkor annak legalább három paramétere szokott lenni: mi a kiinduló betűsorozat, hogy melyik részét akarjuk helyettesíteni, és az, hogy mivel akarjuk helyettesíteni. Például az Awk programozási nyelvben ez így nézne ki:
sub("akarom", "szeretném", "ebben akarom helyettesíteni");
Ezzel szemben Python nyelven ugyanez:
str.replace("ebben akarom helyettesíteni", "akarom", "szeretném")
Vagyis a két nyelvben más-más sorrendben kell megadnunk, hogy melyik paramétert hogyan akarjuk rögzíteni.
Az viszont teljes egészében a program írójának (ebben az esetben a sub, illetve a str.replace program szerzőjének) az önkényes döntése, hogy milyen sorrendet ír elő, és ez óriási különbség az emberi nyelvekhez képest, amikben például az igék bővítményeinek a sorrendje nem tetszőleges, és pláne nem áll a beszélők hatalmában ennek a meghatározása.
Egy kicsit teljesebb igazság
A valóság jóval összetettebb, mint az az egyszerű helyzet, amit az előző részben leírtam. Ugyanis sok programozási nyelv lehetővé teszi, hogy a paraméterek szerepét ne egyszerűen a sorrendjük jelölje, hanem például kulcsszavakkal utaljunk a szerepükre, és ilyenkor a sorrendjük sem számít. Például az előző részben már említett Python nyelvben azt az eljárást, ami valahova (a képernyőre vagy egy file-ba) kiír egy betűsorozatot, így hívhatjuk meg:
print("Ezt akarom kiíratni",
file="filenév.txt",
end="")
Itt az látható, hogy a print nevű eljárás három paraméterének az értékét rögzítettük, de ezek közül csak az elsőnél fontos a sorrend (hogy a legelső legyen) – ez az első adja meg, hogy mi legyen a kiírt betűsorozat, string. A második paramétert, azt, hogy hova írja a program a betűsorozatot (itt egy filenév.txt nevű file-ba), egy kulcsszó, a file jelöli. Ennek betűről betűre így kell szerepelnie, utána kell szerepelnie egy egyenlőségjelnek, és utána annak, hogy mi legyen a paraméter értéke. Az end kulcsszóval pedig a harmadik paramétert adjuk meg, hogy mit biggyesszen a program a kiírt betűsorozat végére (ha nem adjuk meg, akkor egy „sor vége” jelet ír oda; ha az üres betűsorozatot, ahogy itt tettük, akkor pedig semmit). A két kulcsszóval megadott paraméter sorrendje más is lehetne, tehát ez ugyanazt jelöli, mint az előző:
print("Ezt akarom kiíratni",
end="",
file="filenév.txt")
Ezek a kulcsszavak a természetes nyelvben azoknak az eszközöknek felelnek meg, amik a bővítmények szerepét jelölik. Például az angolban az ige előtt áll az alany, utána jelölés nélkül a tárgy (itt tehát a sorrend jelöli a bővítmény szerepét), más bővítmények szerepét pedig ún. elöljárószók jelölik (for, to, about, with stb.) A magyarban az alany jelöletlen (nincs végződése), a többi bővítmény szerepét vagy ún. esetrag (esetleg névutó) jelöli, vagy kifejezetten bizonyos szerepek betöltésére szolgáló ún. határozószók a bővítmények, pl. [te] vidd haza Kati helyett a kutyát!. Az alanyt (ahogy ebben a példában is) általában el is hagyhatjuk, de ha kitesszük, akkor jelöletlen („alanyesetben” áll). A haza egy határozószó, ami kifejezetten a célpontot, végpontot jelölő bővítmény szerepét tudja játszani (amit máskor pl. az -ig vagy -hoz esetragos, a mögé, alá stb. névutós szerkezet, és így tovább). A Kati helyett esetében a helyett névutó, végül az a kutyát szerkezetben a -t tárgyrag jelöli a bővítmény szerepét. Ezek az eszközök tehát olyasmik, mint a Python-példánkban a file vagy az end kulcsszavak.
A hasonlóságok mellett ugyanakkor különbségek is vannak. A helyett névutót és a többi eszközt nagyjából mindig ugyanazokban az értelmezésekben használjuk (bár persze a természetes nyelvekre jellemző módon ez sokféle lehet). A számítógépes programozási és parancs-nyelvekben viszont ebből a szempontból is a programozó kezében vagyunk. Bár a kulcsszavak általában értelmes (angol) szavak, de ez sem kötelező, az pedig végképp nem következik semmiből, hogy ugyanaz a kulcsszó többféle paraméter esetén hasonló szerepre utaljon, vagy megfordítva, hogy eltérő kulcsszavak mindig eltérő szerepre utaljanak.
Vagyis a kulcsszavak és más hasonló eszközök használata (a paraméterek sorrendje helyett) nem sokat változtat azon az alapproblémán, amiről az előző részben beszéltem. A programozó önkényes döntése az, hogy mit hogyan kell nekünk, felhasználóknak jelölnünk, és ennek legfeljebb a jó ízlése vagy a valamiféle szokásokhoz való igazodása szab határt. De sajnos kialakult szokások sokkal kevésbé léteznek, mint az emberi nyelvek esetében – az emberi nyelvek éppen hogy csupa ilyen szokásból állnak.
Paraméterek és szerepek
Az előzőekben két rettentő fontos fogalomhoz jutottunk el, amikor a paraméterek megadásának módjairól beszéltünk. Az egyik a szerep: a programok, programrészletek, parancsok paraméterei nem egyszerűen olyanok, mint a matematikai egyenletekben az ismeretlenek vagy változók, amiknek csak meg kell adnunk az értékét, hanem valamilyen szerepet játszanak, ahogy a természetes nyelvben a bővítmények. (Ugye emlékszünk? Az iskolában ezeknek a bővítményi szerepeknek mindenféle neveket adtunk: „alany”, „tárgy”, „célhatározó” stb.).
A másik fontos fogalom a szokások fogalma. Az emberi nyelvekben a bővítmények használatát azért könnyebb megtanulni, mint a programoknál a paraméterezést, mert olyan szokásokon alapul, amik jó esetben nem egy-egy igére vonatkoznak, hanem sok-sok igére. Például a magyarban döntően alanyesetben állnak az aktív, tudatos cselekvő szerepét játszó bővítmények (pl. A majom játszik), meg azok is, amik passzívan szenvednek el hely- vagy állapotváltozást, ha nem tárgyas az ige (pl. A majom leesett az ágról). Ha az ige tárgyas, akkor az elszenvedő szerepét játszó bővítmény a tárgyeset toldalékát kapja meg (pl. A majom megette a banánt).
Néha előfordul, hogy egyes igék egyes bővítményeit különleges, külön megtanulandó esetragok, névutók vagy ilyesmi jelölik. Például rejtélyes, hogy miért kap -ra/-re toldalékot az a bővítmény, ami azt fejezi ki, hogy valami rá hasonlít: Ez a majom a macskámra hasonlít. Legfeljebb történeti magyarázatot lehet rá adni (ha valaki ismeri a történetét, én nem). Mondhatnánk tehát, hogy a magyar nyelv se jobb mint egy programozási nyelv, hiszen sokszor ilyen önkényes módon kell jelölni egy-egy bővítmény szerepét. Ebben van is valami igazság, de mégis van egy különbség. Az emberi nyelvekben ez leginkább olyankor fordul elő, amikor a bővítmény azt a bizonyos szerepet csak nagyon kevésféle ige mellett játssza, mert az a szerep nagyon sajátos, nem pedig olyan, mint az „aktív cselekvő” vagy a „változást elszenvedő”, aminek millió ige mellett van értelme. Tehát nem egyszerűen arról van szó, hogy a -ra/-re toldalékos szerkezet csak a hasonlít ige mellett jelöl egy bizonyos szerepet, hanem arról is, hogy ez a szerep (mindegy is, hogy hogy nevezzük el) nem is nagyon értelmes más igék esetében. Vagy ha mégis, akkor előfordulhat a -ra/-re, például Ez a majom az anyjára ütött, a macskámra emlékeztet stb.
A továbblépés útja
Megint csak egy pár lépéssel jutottunk előbbre, de szerintem tettünk néhány érdekes megállapítást. Mi legyen a következő lépés? Először is valahogy értelmeznünk kellene, hogy mit jelentene a számítógépes nyelvek esetében egy-egy paraméter szerepe. Eközben persze azt is világosabban kellene látnunk, hogy mit jelent ez a természetes nyelvekben. Másrészt pedig azt is tisztáznunk kellene, hogy a természetes nyelvek szokásainak mi felel meg a számítógépes nyelvek esetében. Nyilván ott is vannak írott és íratlan szabályok, de vajon hogyan lehetne „kikényszeríteni”, hogy ezekhez alkalmazkodjanak a programozók? Persze erőszakról szó sem lehet, ahogy a természetes nyelvek esetében sem kényszerít minket senki arra, hogy a megfelelő esetragokat, névutókat stb. használjuk.
A természetes nyelvek használatakor egyszerűen azért alkalmazkodunk a szokásokhoz, hogy megértsenek minket. Tehát valahogy így kellene eljárnunk a számítógépes nyelvek esetében is. Olyan módszert kellene kitalálnunk, ami lehetővé teszi, hogy csak akkor legyen értelmes (a számítógép számára értelmezhető) a programunk, ha a megfelelő módon adják meg a paramétereiket, méghozzá úgy, akkor járunk el megfelelően, ha általános szokásokhoz igazodunk.
Erről a két kérdésről szól majd a gondolatmenetem következő része.
A szerző nyelvész, az MTA Nyelvtudományi Intézetének főmunkatársa. A Qubit.hu-n megjelent írásai itt olvashatók.
Kapcsolódó cikk a Qubiten: