Referenciális átláthatóság

A referenciális átlátszóság egy programozási nyelv kifejezéseinek olyan tulajdonsága , amely egy kifejezés helyettesíthető annak értékével anélkül, hogy megváltoztatná a program viselkedését .

Meghatározás

Ha a kifejezésben szereplő összes funkció tiszta , vagyis ha mindig ugyanazok a visszatérési értékek vannak ugyanazon argumentumoknál, és ha nincsenek mellékhatásai , akkor a kifejezés referenciálisan átlátszó. De fordítva hamis: egy referenciálisan átlátszó kifejezés nem tiszta funkciókat jelenthet.

A referenciális átláthatóság a funkcionális programozás sarokköve . Különösen lehetővé teszi a referenciálisan átlátszó függvények memorizálását (vagyis a korábban kiszámított értékek memorizálását).

Példák és ellenpéldák

Az aritmetikai műveletek referenciálisan átlátszók: így helyettesíthetjük 4*3az értékével 12vagy a 2*6vagy segítségével 3*4. A kifejezés matematikai értelmében vett függvények referenciálisan átlátszók: ez a helyzet például sin(x)a referenciálisan átlátszó függvény esetében, mivel egy xadott eredményre mindig ugyanazt az eredményt adja, és nincs mellékhatása.

Ezzel szemben x++a C nyelv kifejezése nem referenciálisan átlátszó, mert megváltoztatja az értéket x. Ugyanez van azzal, today() aki nem referenciálisan átlátszó, mert ha ma értékeljük, akkor nem kapjuk meg ugyanazt az eredményt, mintha holnap futtatnánk.

Kontraszt az elengedhetetlen programozással

Ha egy kifejezésnek az értékével való helyettesítése csak a program bizonyos pontjain érvényes, akkor a kifejezés nem hivatkozási szempontból átlátszó. A definíció és annak pontsorozata  (be) rendezése az imperatív programozás elméleti alapja , és az imperatív programozási nyelvek szemantikájának kapuja.

Mivel azonban egy referenciálisan átlátszó kifejezés mindig helyettesíthető az értékével vagy az azonos értéket produkáló kifejezéssel, nincs szükség szekvenciapontok meghatározására vagy az értékelés sorrendjének megőrzésére. A tisztán funkcionális programozást programozási paradigmának nevezzük, amely mentes a végrehajtások fix ütemezésének gondjaitól.

A referenciálisan átlátszó kódírás előnye, hogy a statikus kódelemzés könnyebb és automatikus kódjavító transzformációk lehetségesek. Például a C programozásnál egy függvénynek egy hurokban való szerepeltetése ára a teljesítménynek, míg ez a függvény a program eredményeinek megváltoztatása nélkül áthelyezhető a hurokból. Ennek a funkciónak a mozgatásával a programozó elveszítheti a kód olvashatóságát . De ha a fordító képes meghatározni a függvényhívás referenciális átlátszóságát, automatikusan végrehajtja ezt a lépést, így hatékonyabb kódot állít elő.

A referenciális átláthatóságot igénylő nyelvek megnehezítik a műveletek írását, amelyeket természetesen lépéssorozatokként fejeznek ki. Az ilyen nyelvek olyan mechanizmusokat tartalmazhatnak, amelyek megkönnyítik ezeket a feladatokat, miközben megőrzik pusztán funkcionális minőségüket, például monádok és határozott záradékú nyelvtanok .

Míg a matematikában az összes függvényalkalmazás referenciálisan átlátszó, az imperatív programozásnál ez nem mindig így van. Például egy olyan paraméter nélküli függvény esetében, amely a billentyűzeten beírt karakterláncot adja vissza , a visszatérési érték a megadott értéktől függ, így az azonos paraméterű függvény többszörös hívása (az üres lista) eltérő eredményt adhat.

Egy olyan függvény hívása, amely globális változót , vagy dinamikus vagy lexikális hatókörű változót használ az eredmények kiszámításához, nem referenciálisan átlátható. Mivel ezt a változót nem adják meg paraméterként, de megsérülhetnek, a függvény későbbi hívásainak eredményei eltérhetnek annak ellenére, hogy a paraméterek ugyanazok. A tiszta funkcionális nyelvekben a hozzárendelés nem megengedett, azonban a monádok használata lehetővé teszi a tiszta funkcionális programozást, miközben olyan mechanizmusuk van, amely szorosan hasonlít a globális változókra.

A referenciális átláthatóság fontossága az, hogy lehetővé teszi a programozónak vagy a fordítónak, hogy a program viselkedésével kapcsolatban érveljen. Ez segíthet bebizonyítani helytállóságát, megtalálni a teszteléssel nem megtalálható hibákat, egyszerűsíteni egy algoritmust , segíteni a kód módosítását a törés nélkül, optimalizálni a kódot memorizálással vagy megszüntetni a gyakori alkifejezéseket .

Bizonyos funkcionális programozási nyelvek (például a Haskell ) minden függvényre kiterjesztik a referencia átláthatóságot.

A parancs-kérés szétválasztásának elve

Bár az imperatív programozáson alapszik, az Eiffel szigorú elkülönítést ír elő a parancsok között, amelyek mellékhatásokat és kérelmeket hozhatnak létre, amelyeknek referenciálisan átláthatóknak kell lenniük. A lekérdezések eredményt adnak, de nem változtatják meg a környezetet. Ezt a szabályt a parancs-lekérdezés elválasztásának elvének nevezzük , amely lehetővé teszi számunkra, hogy olyan stílust érjünk el, amely egyértelműen elválasztja a referenciálisan átlátszó részeket a többitől. Például a listák manipulálásakor:

my_list.finish -- Déplace le curseur à la fin de la liste value := my_list.item -- Obtient la valeur à la position du curseur : référentiellement transparent

Még olyan kötelező tulajdonságokat is érint, mint a bemenetek:

my_file.read_integer -- obtient le prochain entier; effet de bord, mais pas de valeur de retour value := my_file.last_integer -- obtient le dernier entier lu: réferentiellement transparent

Ha többször hívja sorozatosan, last_integerugyanazt az eredményt kapja minden alkalommal.

Egy másik példa

Tekintsünk két funkciót, amelyek közül az egyik rqreferenciálisan átlátszatlan, a másik pedig rtreferenciálisan átlátszó:

globalValue = 0; integer function rq(integer x) begin globalValue = globalValue + 1; return x + globalValue; end integer function rt(integer x) begin return x + 1; end

Ha ezt rtreferenciálisan átlátszónak mondjuk, az azt jelenti, hogy n esetén az adott rt( n ) mindig ugyanazt az értéket adja. Például ,, rt(6) = 7, rt(4) = 5és így tovább. De ez nem igaz, rqmert egy globális változót használ, amelyet módosít.

Lásd is

Hivatkozások

  1. Alapvetően, ha egy monádot használsz StateHaskellben és alkalmazod rá, Inthogy megszerezd Stat Int, akkor mintha egy globális típusú változó lenne Int, nem kevesebb, nem több. Ezért a típusnak köszönhetően bármikor rendelkezünk teljes és statikus ismeretekkel az általunk használt globális változókról.