A konkatenatív programozási nyelv egy olyan programozási nyelv , amely azon a tényen alapul, hogy két kódrészlet összefűzése fejezi ki azok összetételét . Egy ilyen nyelvben széles körben használják a függvényargumentumok implicit specifikációját (lásd értelmetlen programozás ), az új függvényeket függvényösszetételként definiálják, és az alkalmazás helyett az összefűzést alkalmazzák [1] . Ez a megközelítés ellentétes az aplikatív programozással .
Sok konkatenatív nyelv használ postfix jelölést és egy veremet az argumentumok tárolására és a műveletek értékeinek visszaadására, így az összefűző nyelvek általában veremnyelveket jelentenek. A konkatenatív nyelvek azonban más elvekre is épülhetnek, így a veremnyelv és a konkatenatív nyelv kifejezések nem szinonimák.
A konkatenatív nyelvek egyszerűek, hatékonyak és könnyen megvalósíthatók, ezért az ilyen típusú legnépszerűbb nyelveket a programozható számológépekben és a kis mikroprocesszoros rendszerekbe való beágyazáshoz használják. Például az RPL konkatenatív nyelvet használják a Hewlett-Packard HP-28 és HP-48 programozható számológépek . A Forth programozási nyelvet számos nagyon korlátozott számítási képességű processzoron implementálták [2] , például a Jupiter ACE számítógépen használták mindössze 1 KB-os alap RAM-mal. A szokatlanságuk és a programok forráskódjának olvasási nehézségei miatt azonban a konkatenatív programozási nyelvek résben maradtak.
A legelterjedtebb konkatenatív nyelv a PostScript oldalleíró nyelv , amelynek egy korlátozott részhalmaza a PDF -ben használatos . Tolmácsa számos nagy teljesítményű nyomtatóba be van építve.
Egy programozási nyelvet konkatenatívnak nevezünk, ha megfelel a következő követelményeknek:
Konkatenatív nyelvben minden kifejezés függvény. Nincs speciális alkalmazási művelet, a függvény argumentumokra való alkalmazásához elég az argumentumok mellé a függvény nevét feltenni, vagyis szöveg "ragasztást" (összefűzést) végezni. Az új függvényeket összefűzés is meghatározza, ami egyszerűen más függvénynevek sorozata.
Legyen fookét argumentum és baregy argumentum függvényei adottak. Az argumentumok alkalmazásához fooaz előtag jelölésében elegendő egy ilyen kifejezést összeállítani:
foo 4 5
Most alkalmazza a függvényt a függvény bareredményére foo:
bar foo 4 5
Végül definiáljunk egy függvényt bazhárom függvény összefűzéseként:
define baz
bar foo 4
end-define
A kifejezés baz 8megegyezik a kifejezéssel bar foo 4 8. Vagyis bármely függvény neve lecserélhető a definíciójának szövegére, és megkapható a helyes kifejezés. Ez az egyszerű elv határozza meg a konkatenatív nyelvek sajátosságait, előnyeiket és hátrányaikat.
Ahhoz, hogy a kódrészletek összefűzése mindig kifejezze összetételüket, a nyelvnek csak egy argumentum függvényei lehetnek. [3] Ebben az esetben megtagadhatja az argumentum explicit megadását, így egységes előtag vagy utótag jelöléssel létrehozhat olyan programozási nyelvet, amelyben a kódrészletek összefűzése kifejezi azok összetételét, vagyis egy konkatenatív nyelvet.
Ennek a megközelítésnek az egyik egyszerű és hatékony módja a verem használata . A függvények argumentumokat vesznek a veremből, és az eredményt a verembe helyezik. Ezért azt mondhatjuk, hogy a konkatenatív veremprogramozási nyelvekben a függvények egy argumentumot vesznek fel - a verem állapotát, és a verem új állapotát adják vissza. [4] Ezek a nyelvek általában postfix jelölést használnak , mivel a verem LIFO -ban működik .
Vannak más módok is. Például egy függvény felveszi a program szövegét, és visszaadja néhány változtatással, amely tükrözi a munkáját. Erre az elvre egy nagyon egyszerű és rugalmas homoikonikus nyelvet lehet építeni. [5] Lehetséges egy nyelvet felépíteni a UNIX-folyamat elve köré : minden függvény vesz egy karakterláncot, és feldolgozás után egy új karakterláncot ad vissza. [6] Az előző elvvel ellentétben a függvénynek átadott szöveg csak argumentumokat tartalmaz, nem a teljes programot. Ezek a módszerek mind az elő-, mind az utótag-jelöléssel működhetnek.
Verem helyett más adatszerkezetek is használhatók, mint például a queue vagy a deque (deque) [7] .
A konkatenatív nyelv gondolata a következő: minden kifejezés olyan függvény, amely ugyanazt az adatstruktúrát veszi fel, és visszaadja az új állapotát. Ez az adatstruktúra (stack, deque, queue, text string stb.) a függvények programba "ragasztásának" ragasztó szerepét tölti be, tárolja a program állapotát. Ez a megközelítés meghatározza a konkatenatív nyelvek előnyeit és hátrányait.
Előnyök:
Hibák:
Az első magas szintű konkatenatív nyelv a Forth volt , amelyet Charles Moore fejlesztett ki az 1960-as évek végén és az 1970-es évek elején. Típus nélküli veremet használt, könnyen implementálható és rendkívül hatékony volt, ami lehetővé tette a fordítók megvalósítását rendkívül korlátozott számítási erőforrások mellett is. A Forth jelentősen befolyásolta a későbbi konkatenatív nyelveket.
Manfred von Thun oktató és programozó a La Trobe Egyetemen , John Backus „ Megszabadulhat-e a programozás Neumann stílusától?” című híres előadása hatására. kifejlesztette a Joy stack programozási nyelvet , és lefektette a konkatenatív programozás elméleti alapjait. Ez volt az örömnyelv, amelyet először konkatenatívnak neveztek.
Forth és Joy hatására Slava Pestov 2003-ban megalkotta a Factor verem programozási nyelvet . "Gyakorlati veremprogramozási nyelvként" van elhelyezve. Később kifejlesztették a Cat és Kitten halmozott konkatenatív nyelveket , amelyeket a statikus gépelés különböztet meg . Egy másik modern konkatenatív nyelv, a min , minimalista szintaxissal és nagyon kompakt megvalósítással rendelkezik (körülbelül 1 megabájt), és a HastySite webhelygenerátorban használatos .
A speciális veremnyelvek közül a legismertebb a PostScript , amely az oldalak leírására és nyomtatására szolgál, valamint az RPL , a HP-28 és HP-48 számológépek programozási nyelve .
A legtöbb konkatenatív programozási nyelv a veremet használja argumentumok átadására. Ez a könnyű implementációnak és a verem tulajdonságainak köszönhető, amely postfix jelöléssel kényelmesen használható. Fontolja meg a veremmel való munkát, példaként a Forth nyelv használatával.
A Forthban egy program szóközzel elválasztott szavakból áll. Ha a szó egy szám, akkor az a verem tetejére kerül. Ha a szó egy függvény neve, akkor ezt a függvényt hívják meg (a Forth terminológiában a függvényeket szavaknak nevezzük). Érveket vesz a veremből, és az eredményt a verembe tolja. Tekintsük a legegyszerűbb programot, amely négy szóból áll:
3 4 + .
Az első két szó szám, ezért a verembe kerülnek. Ezután a függvényt hívják +, amely két számot vesz ki a veremből, összeadja őket, és az eredményt a verembe tolja. Ezután a függvényt hívják .meg, amely megjeleníti a veremből a számot. Így az argumentumok megelőzik a függvényt, ezért ezt a jelölést postfixnek nevezik.
Az általános célú konkatenatív nyelvek nem szereztek jelentős népszerűséget. Ennek oka a sajátos előnyeik és hátrányaik, amelyek az alapelv következményei: minden függvény egy argumentumot vesz fel, és egy értéket ad vissza. Amikor pontosan erre van szükség, nincs probléma, és a konkatenatív nyelvek lehetővé teszik, hogy nagyon egyszerű, tömör és világos programokat írjon. Tegyük fel, hogy egy konkatenatív nyelv postfix jelöléssel rendelkezik a következő függvényekkel, amelyek szöveges karakterláncokat fogadnak el és adnak vissza:
input – a felhasználó által beírt szöveget adja vissza nyomtatás – szöveget jelenít meg a képernyőn upcase – A karakterlánc kisbetűit nagybetűkre változtatja first_word – a karakterlánc első szavát adja vissza (a karakterláncot az első szó utáni első szóközre vágja)Írjunk velük egy programot, amely nagybetűvel jeleníti meg a felhasználó nevét:
input first_word upcase print
Nehézségek akkor merülnek fel, ha különböző számú argumentummal rendelkező függvényeket kell használni. A veremnyelvben az argumentumokat egy bizonyos sorrendbe kell helyeznie, és gyakran fel kell cserélnie őket. Továbbá, ha egy argumentumot többször használnak egy függvényben, akkor meg kell duplikálni. Ez nehezen érthető kifejezésekhez vezet. Például a függvény
f x y z = y² + x² − |y|
verem nyelven a következőképpen van írva:
f = drop dup dup × swap abs rot3 dup × swap − +
A változókat kifejezetten használják a modern konkatenatív nyelvekben, mint például a Kitten és a min, hogy leküzdjék ezeket a nehézségeket. A Kitten nyelvben a változók a következőképpen vannak deklarálva:
->x; // Az x változó értékét a veremből kapja 5 -> y; // y = 5 1 2 3 -> xyz; // x = 1; y=2; z = 3Tekintsük egy szám négyzetre emelésének függvényét. Hagyományosan a stack nyelvekhez a Kittenben a következőképpen írják: [8]
define square (Int32 -> Int32):
dup (*)
Így átírható egy változó segítségével:
define square (Int32 -> Int32):
-> x;
x * x
Ebben a legegyszerűbb példában ennek nincs különösebb értelme. Ha azonban egy argumentumot vagy argumentumokat sokszor használunk egy függvényben, a változók használata nagyban leegyszerűsíti a program írását és a forráskód olvasását. A 99 üveg sör című dalt megjelenítő programkód töredéke :
definiálja a bottles_of_beer (Int32 -> +IO): ->x; xverse ha (x > 1): (x - 1) üveg_sörA min programozási nyelvben a szimbólumokat hasonlóan használják:
x define ; символ x получит значение из стека
:x ; сокращённая запись
8 :x ; x = 8
Vegyünk például egy min programot , amely igazat ad vissza, ha egy fájl 1 megabájtnál nagyobb, és nemrégiben módosították:
dup dup
"\.zip$" match
swap fsize 1000000 > and
swap mtime now 3600 - >
A szimbólum használatával elkerülheti a veremelemek megkettőzését és átrendezését, és jelentősen javíthatja a kód olvashatóságát:
:filepath
filepath "\.zip$" match
filepath fsize 1000000 >
filepath mtime now 3600 - >
and and
A változók használata közelebb hozza a konkatenatív nyelveket az alkalmazó nyelvekhez, de még mindig vannak alapvető különbségek közöttük. Konkatenatív nyelvekben a programozó választhat a verem (vagy hasonló mechanizmus) használata között, vagy a változók deklarálása között. Ezenkívül a változókkal való munka mechanizmusa meglehetősen átlátható és kezelhető. Ez rugalmasságot és lehetőséget ad a hatékony és viszonylag egyszerű megvalósításra.