Co oznacza termin przejrzystość referencyjna ? Słyszałem, że opisano to jako „oznacza to, że możesz zastąpić równe równym”, ale wydaje się to niewłaściwym wyjaśnieniem.
Co oznacza termin przejrzystość referencyjna ? Słyszałem, że opisano to jako „oznacza to, że możesz zastąpić równe równym”, ale wydaje się to niewłaściwym wyjaśnieniem.
Odpowiedzi:
Termin „przejrzystość referencyjna” pochodzi od filozofii analitycznej , gałęzi filozofii, która analizuje konstrukcje języka naturalnego, stwierdzenia i argumenty oparte na metodach logiki i matematyki. Innymi słowy, jest to najbliższy przedmiot poza informatyką, który nazywamy semantyką języka programowania . Filozof Willard Quine był odpowiedzialny za zainicjowanie koncepcji przejrzystości referencyjnej, ale był także dorozumiany w podejściach Bertranda Russella i Alfreda Whitehead.
U ich podstaw „przejrzystość referencyjna” jest bardzo prostym i jasnym pomysłem. Termin „odniesienie” jest używany w filozofii analitycznej do mówienia o rzeczy, do której odnosi się wyrażenie . Jest to mniej więcej to samo, co rozumiemy przez „znaczenie” lub „denotację” w semantyce języka programowania. Na przykładzie Andrew Birkett ( post na blogu ) termin „stolica Szkocji” odnosi się do Edynburga. To prosty przykład „odniesienia”.
Kontekst w zdaniu jest „referencyjnie przejrzysty”, jeśli zastąpienie terminu w tym kontekście innym terminem odnoszącym się do tego samego bytu nie zmienia znaczenia. Na przykład
Parlament szkocki spotyka się w stolicy Szkocji.
oznacza to samo co
Parlament szkocki spotyka się w Edynburgu.
Zatem kontekst „Parlament szkocki spotyka się w ...” jest kontekstem przejrzystym pod względem referencyjnym. Możemy zastąpić „stolicę Szkocji” „Edynburgiem” bez zmiany znaczenia. Innymi słowy, kontekst dba tylko o to, do czego odnosi się ten termin i nic więcej. W tym kontekście kontekst jest „referencyjnie przejrzysty”.
Z drugiej strony w zdaniu
Edynburg jest stolicą Szkocji od 1999 roku.
nie możemy zrobić takiej wymiany. Gdybyśmy to zrobili, otrzymalibyśmy „Edynburg był Edynburgiem od 1999 r.”, Co jest szaloną rzeczą do powiedzenia i nie ma takiego samego znaczenia jak oryginalne zdanie. Wydaje się więc, że kontekst „Edynburg był… od 1999 r.” Jest referencyjnie nieprzejrzysty (odwrotnie niż referencyjnie przejrzysty). Najwyraźniej zależy mu na czymś więcej niż to, o czym mówi ten termin. Co to jest?
Rzeczy takie jak „stolica Szkocji” nazywane są definitywnymi terminami i przez długi czas nie sprawiały kłopotów logistom i filozofom. Russell i Quine uporządkowali je, mówiąc, że tak naprawdę nie są „referencyjne”, tzn. Błędem jest myśleć, że powyższe przykłady są używane w odniesieniu do bytów. Właściwy sposób na zrozumienie „Edynburg jest stolicą Szkocji od 1999 roku” to powiedzieć
Szkocja ma stolicę od 1999 roku, a stolicą jest Edynburg.
To zdanie nie może zostać przekształcone w orzechowe. Problem rozwiązany! Celem Quine było stwierdzenie, że język naturalny jest niechlujny, a przynajmniej skomplikowany, ponieważ jest wygodny w praktycznym użyciu, ale filozofowie i logicy powinni zapewnić jasność, rozumiejąc je we właściwy sposób. Referencyjna przejrzystość jest narzędziem, które można wykorzystać do uzyskania takiej przejrzystości znaczenia .
Co to wszystko ma wspólnego z programowaniem? Właściwie nie bardzo. Jak powiedzieliśmy, przejrzystość referencyjna jest narzędziem, które można wykorzystać w zrozumieniu języka, tj. W przypisywaniu znaczenia . Christopher Strachey , który założył dziedzinę programowania języka, wykorzystał ją w swoich badaniach znaczenia. Jego podstawowy artykuł „ Podstawowe pojęcia w językach programowania ” jest dostępny w Internecie. To piękny papier i każdy może go przeczytać i zrozumieć. Więc proszę, zrób to. Będziecie znacznie oświeceni. Wprowadza termin „przejrzystość referencyjna” w tym akapicie:
Jedną z najbardziej użytecznych właściwości wyrażeń jest ta, którą wywołuje przezroczystość referencyjna Quine. Zasadniczo oznacza to, że jeśli chcemy znaleźć wartość wyrażenia zawierającego podwyrażenie, jedyne, co musimy wiedzieć o podwyrażeniu, to jego wartość. Wszelkie inne cechy wyrażenia podrzędnego, takie jak jego struktura wewnętrzna, liczba i charakter jego składników, kolejność ich oceny lub kolor tuszu, w którym są napisane, nie mają znaczenia dla wartości głównego wyrażenie.
Użycie słowa „w istocie” sugeruje, że Strachey parafrazuje go, aby wyjaśnić to w prosty sposób. Funkcjonalni programiści zdają się rozumieć ten akapit na swój własny sposób. W artykule jest 9 innych przypadków „referencyjnej przejrzystości”, ale wydaje się, że nie zawracają sobie głowy żadnym z pozostałych. W rzeczywistości cała praca Strachey poświęcona jest wyjaśnieniu znaczenia imperatywnych języków programowania . Ale dzisiaj programiści funkcjonalni twierdzą, że imperatywne języki programowania nie są względnie przejrzyste. Strachey odwróciłby się w grobie.
Możemy uratować sytuację. Powiedzieliśmy, że język naturalny jest „niechlujny, a przynajmniej skomplikowany”, ponieważ jest wygodny w praktycznym użyciu. Języki programowania są takie same. Są „niechlujne lub przynajmniej skomplikowane”, ponieważ zostały stworzone z myślą o praktyczności. To nie znaczy, że muszą nas mylić. Należy je po prostu zrozumieć we właściwy sposób, używając meta-języku, który jest referencyjnie przejrzysty, abyśmy mieli jasność znaczenia. W cytowanym przeze mnie artykule Strachey właśnie to robi. Wyjaśnia znaczenie imperatywnych języków programowania, dzieląc je na podstawowe pojęcia, nigdy nie tracąc przejrzystości. Ważną częścią jego analizy jest wskazanie, że wyrażenia w językach programowania mają dwa rodzaje „wartości”,wartości r . Przed pismem Stracheya nie zostało to zrozumiane, a zamieszanie zapanowało nadrzędnie. Dzisiaj definicja C wspomina o tym rutynowo i każdy programista C rozumie to rozróżnienie. (Trudno powiedzieć, czy programiści w innych językach rozumieją to równie dobrze).
Zarówno Quine, jak i Strachey zajmowali się znaczeniem konstrukcji językowych, które wymagają pewnej formy zależności od kontekstu. Na przykład nasz przykład „Edynburg jest stolicą Szkocji od 1999 r.” Oznacza fakt, że „stolica Szkocji” zależy od czasu, w którym jest rozpatrywana. Taka zależność od kontekstu jest rzeczywistością, zarówno w językach naturalnych, jak i językach programowania. Nawet w programowaniu funkcjonalnym zmienne swobodne i powiązane należy interpretować w odniesieniu do kontekstu, w którym się pojawiają. Zależność kontekstowa dowolnego rodzaju blokuje w pewien sposób przezroczystość referencyjną. Jeśli spróbujesz zrozumieć znaczenie terminów bez względu na kontekst, od którego są zależne, znów wpadniesz w zamieszanie. Quine zajmował się logiką modalną. Trzymał tologika modalna była referencyjnie nieprzezroczysta i powinna zostać oczyszczona poprzez przełożenie jej na referencyjnie przejrzyste ramy (np. przez uznanie konieczności za sprawdzalną). W dużej mierze przegrał tę debatę. Logicy i filozofowie uznali, że możliwa semantyka świata Kripke jest całkowicie wystarczająca. Podobna sytuacja panuje również przy programowaniu imperatywnym. Zależność od państwa wyjaśniona przez Stracheya i zależność od sklepu wyjaśniona przez Reynoldsa (w sposób podobny do możliwej semantyki świata Kripkego) są całkowicie wystarczające. Funkcjonalni programiści niewiele wiedzą o tych badaniach. Ich pomysły dotyczące przejrzystości referencyjnej należy przyjmować z dużym ziarnem soli.
[Uwaga dodatkowa: powyższe przykłady pokazują, że proste wyrażenie, takie jak „stolica Szkocji”, ma wiele poziomów znaczenia. Na pewnym poziomie możemy mówić o stolicy w obecnym czasie. Na innym poziomie moglibyśmy mówić o wszystkich możliwych stolicach, które Szkocja mogła mieć z biegiem czasu. Możemy „przybliżyć” do określonego kontekstu i „oddalić”, aby dość łatwo objąć wszystkie konteksty w normalnej praktyce. Efektywność języka naturalnego wykorzystuje naszą zdolność do tego. Imperatywne języki programowania są wydajne w bardzo podobny sposób. Możemy użyć zmiennej x po prawej stronie przypisania (wartość r ), aby mówić o jej wartości w określonym stanie. Lub możemy porozmawiać o jego wartości lktóry obejmuje wszystkie stany. Ludzie rzadko są zdezorientowani takimi rzeczami. Mogą jednak, ale nie muszą, być w stanie precyzyjnie wyjaśnić wszystkie warstwy znaczeń właściwe dla konstrukcji językowych. Wszystkie takie warstwy znaczeń niekoniecznie są „oczywiste”, a ich prawidłowe zbadanie jest kwestią nauki. Jednak brak umiejętności zwykłych ludzi do wyjaśniania takich warstwowych znaczeń nie oznacza, że są zdezorientowani].
Osobny „postscriptum” poniżej wiąże tę dyskusję z obawami dotyczącymi programowania funkcjonalnego i imperatywnego .
Przezroczystość referencyjna, termin powszechnie używany w programowaniu funkcjonalnym, oznacza, że biorąc pod uwagę funkcję i wartość wejściową, zawsze otrzymasz ten sam wynik. To znaczy, że w funkcji nie jest używany stan zewnętrzny.
Oto przykład referencyjnej przezroczystej funkcji:
int plusOne(int x)
{
return x+1;
}
Dzięki referencyjnej przezroczystej funkcji, podanej wartości wejściowej i funkcji, możesz zastąpić ją wartością zamiast wywoływać funkcję. Zamiast więc wywoływać plusOne z parametrem 5, moglibyśmy po prostu zastąpić to 6.
Innym dobrym przykładem jest ogólnie matematyka. W matematyce z podaną funkcją i wartością wejściową zawsze będzie odwzorowywana na tę samą wartość wyjściową. f (x) = x + 1. Dlatego funkcje w matematyce są referencyjnie przezroczyste.
Ta koncepcja jest ważna dla badaczy, ponieważ oznacza, że gdy masz referencyjnie przejrzystą funkcję, nadaje się do łatwej automatycznej równoległości i buforowania.
Przezroczystość referencyjna jest zawsze używana w językach funkcjonalnych, takich jak Haskell.
-
W przeciwieństwie do tego istnieje pojęcie referencyjnej nieprzezroczystości. Oznacza to odwrotnie. Wywołanie funkcji może nie zawsze dawać taki sam wynik.
//global G
int G = 10;
int plusG(int x)
{//G can be modified externally returning different values.
return x + G;
}
Innym przykładem jest funkcja członka w zorientowanym obiektowo języku programowania. Funkcje składowe zwykle działają na zmiennych składowych, dlatego też byłyby referencyjne nieprzezroczyste. Funkcje członka mogą oczywiście być referencyjnie przejrzyste.
Jeszcze innym przykładem jest funkcja, która czyta z pliku tekstowego i drukuje dane wyjściowe. Ten zewnętrzny plik tekstowy może się zmienić w dowolnym momencie, więc funkcja będzie referencyjnie nieprzezroczysta.
Referencyjnie przezroczysta funkcja to taka, która zależy tylko od jej danych wejściowych.
[To jest postscriptum do mojej odpowiedzi z 25 marca, aby przybliżyć dyskusję do problemów związanych z programowaniem funkcjonalnym / imperatywnym.]
Pomysł funkcjonalnej programisty dotyczący przejrzystości odniesienia wydaje się różnić od standardowego pojęcia na trzy sposoby:
Podczas gdy filozofowie / logicy używają terminów takich jak „odniesienie”, „denotacja”, „desygnat” i „ bedeutung ” (niemiecki termin Frege'a ), programiści funkcjonalni używają terminu „wartość”. (Nie jest to całkowicie ich dzieło. Zauważam, że Landin, Strachey i ich potomkowie również używali terminu „wartość”, aby mówić o referencjach / denotacji. Może to być tylko terminologiczne uproszczenie, które wprowadzili Landin i Strachey, ale wydaje się, że duża różnica w przypadku naiwnego użycia).
Funkcjonalni programiści wydają się wierzyć, że te „wartości” istnieją w języku programowania, a nie na zewnątrz. W ten sposób różnią się zarówno od filozofów, jak i semantystów języka programowania.
Wydaje się, że wierzą, że te „wartości” powinny być uzyskane na podstawie oceny.
Na przykład artykuł Wikipedii na temat przejrzystości referencyjnej mówi dziś rano:
Mówi się, że wyrażenie jest względnie przezroczyste, jeśli można je zastąpić jego wartością bez zmiany zachowania programu (innymi słowy, dając program, który ma takie same efekty i dane wyjściowe na tym samym wejściu).
Jest to całkowicie sprzeczne z tym, co mówią filozofowie / logicyści. Mówią, że kontekst jest referencyjny lub referencyjnie przejrzysty, jeśli wyrażenie w tym kontekście można zastąpić innym wyrażeniem, które odnosi się do tej samej rzeczy ( wyrażenie rdzenne ). Kim są ci filozofowie / logicy? Należą do nich Frege , Russell , Whitehead , Carnap , Quine , Churchi niezliczeni inni. Każdy z nich jest niesamowitą postacią. Połączona siła intelektualna tych logików jest co najmniej wstrząsająca ziemią. Wszyscy są zgodni co do tego, że odniesienia / denotacje istnieją poza językiem formalnym, a wyrażenia w tym języku mogą tylko o nich mówić . Wszystko, co można zrobić w tym języku, to zastąpić jedno wyrażenie innym wyrażeniem, które odnosi się do tego samego bytu. Same odnośniki / oznaczenia nie istnieją w języku. Dlaczego programiści funkcjonalni odchodzą od tej ugruntowanej tradycji?
Można przypuszczać, że semantycy języka programowania mogli ich wprowadzić w błąd. Ale nie zrobili tego.
Landin :
(a) każde wyrażenie ma zagnieżdżoną strukturę podwyrażenia, (b) każde podwyrażenie oznacza coś (zwykle liczbę, wartość prawdy lub funkcję numeryczną) , (c) rzecz, którą oznacza wyrażenie, tj. jej „wartość”, zależy tylko od wartości jego podwyrażeń, a nie innych ich właściwości. [Dodano nacisk]
Stoy :
Jedyną rzeczą, która ma znaczenie dla wyrażenia, jest jego wartość, a każde podwyrażenie można zastąpić dowolną inną równą wartością [Dodatkowe wyróżnienie]. Ponadto wartość wyrażenia jest, w pewnych granicach, taka sama, ilekroć występuje ”.
wartość wyrażenia zależy tylko od wartości jego wyrażeń składowych (jeśli istnieją) i te podwyrażenia mogą być dowolnie zastępowane przez inne osoby o tej samej wartości [Dodatkowe wyróżnienie].
Z perspektywy czasu wysiłki Landina i Stracheya mające na celu uproszczenie terminologii poprzez zastąpienie „odniesienia” / „denotacji” „wartością” mogły być nieuzasadnione. Gdy tylko usłyszy się o „wartości”, pojawia się pokusa, aby pomyśleć o procesie oceny, który do niej prowadzi. Równie kuszące jest myślenie o tym, co powstaje w wyniku oceny, jako o „wartości”, chociaż może być całkiem jasne, że to nie jest denotacja. To, co zbieram, stało się z koncepcją „przejrzystości referencyjnej” w oczach programistów funkcjonalnych. Ale „wartość”, o której mówili pierwsi semantycy, nie jest wynikiem oceny, rezultatu funkcji lub czegoś takiego. Jest to oznaczenie tego terminu.
Kiedy zrozumiemy tak zwaną „wartość” wyrażenia („odniesienie” lub „denotacja” w dyskursie filozofów klasycznych) jako złożony obiekt matematyczno-konceptualny, otwierają się wszelkie możliwości.
Niechęć programistów funkcyjnych do nazywania takich języków „referencyjnie przejrzystymi” oznacza po prostu, że niechętnie przyjmują tak złożone obiekty matematyczne / koncepcyjne jako „wartości”. Z drugiej strony wydają się doskonale gotowi nazwać transformator stanu „wartością”, gdy jest on umieszczony w swojej ulubionej składni i ubrany w brzęczące słowo, takie jak „monada”. Muszę powiedzieć, że są one całkowicie niespójne, nawet jeśli przyznamy im, że ich idea „przejrzystości odniesienia” ma pewną spójność.
Trochę historii może rzucić nieco światła na to, jak powstały te zamieszania. Okres od 1962 do 1967 roku był bardzo intensywny dla Christophera Stracheya. W latach 1962-65 podjął pracę w niepełnym wymiarze godzin jako asystent naukowy u Maurice'a Wilkesa, aby zaprojektować i wdrożyć język programowania, który stał się znany jako CPL. Był to imperatywny język programowania, ale miał też mieć potężne możliwości funkcjonalnego języka programowania. Landin, który był pracownikiem Strachey w swojej firmie konsultingowej, miał ogromny wpływ na pogląd Stracheya na języki programowania. W przełomowym artykule z 1965 r. „ Następne 700 języków programowania ” Landin bezwstydnie promuje funkcjonalne języki programowania (nazywając je denotatywnymi)języki) i opisuje imperatywne języki programowania jako „antytezę”. W dalszej dyskusji Strachey wątpi w silną pozycję Landina.
... DL tworzą podzbiór wszystkich języków. To interesujący podzbiór, ale niewygodny w użyciu, chyba że jesteś do tego przyzwyczajony. Potrzebujemy ich, ponieważ w tej chwili nie wiemy, jak konstruować dowody w językach, które zawierają imperatywy i skoki. [Dodano nacisk]
W 1965 roku Strachey objął stanowisko Czytelnika w Oksfordzie i wydaje się, że pracował w pełnym wymiarze godzin nad opracowaniem teorii imperatywów i skoków. W 1967 r. Był gotowy na teorię, której nauczał na kursie „ Podstawowe pojęcia w językach programowania ” w letniej szkole w Kopenhadze. Notatki z wykładu miały zostać opublikowane, ale „niestety, z powodu opieszałej redakcji, postępowanie nigdy się nie zmaterializowało; podobnie jak większość prac Strachey w Oxfordzie, gazeta miała wpływowy prywatny obieg”. ( Martin Campbell-Kelly )
Trudność w uzyskaniu pism Stracheya mogła doprowadzić do rozpowszechnienia zamieszania, a ludzie polegali na źródłach wtórnych i pogłoskach. Ale teraz, gdy „ podstawowe pojęcia ” są łatwo dostępne w Internecie, nie ma potrzeby uciekać się do zgadywania pracy. Powinniśmy to przeczytać i zdecydować, co miał na myśli Strachey. W szczególności:
Mówienie o „referencyjnej przezroczystości” bez zrozumienia rozróżnienia między wartościami L, wartościami R i innymi złożonymi obiektami, które zaludniają wszechświat konceptualny programisty, jest zasadniczo błędne.
Referencyjnie przejrzysta funkcja to taka, która działa jak funkcja matematyczna; przy tych samych danych wejściowych zawsze będzie generować te same dane wyjściowe. Oznacza to, że przekazany stan nie jest modyfikowany i że funkcja nie ma własnego stanu.
Dla tych, którzy potrzebują zwięzłego wyjaśnienia, zaryzykuję jedno (ale przeczytaj poniższe ujawnienie).
Przezroczystość referencyjna w języku programowania promuje rozumowanie z równań - im większa jest przejrzystość z odniesieniami, tym łatwiej jest robić rozumowanie z równań. Np. Z definicją funkcji (pseudo)
fx = x + x,
łatwość, z jaką można (bezpiecznie) zamienić f (foo) na foo + foo w zakresie tej definicji, bez zbyt wielu ograniczeń co do miejsca, w którym można wykonać tę redukcję, jest dobrym wskaźnikiem tego, ile przejrzystości referencyjnej ma język programowania ma.
Na przykład, jeśli foo to x ++ w sensie programowania C, to nie można bezpiecznie wykonać tej redukcji (to znaczy, jeśli wykonując tę redukcję, nie uzyskałbyś tego samego programu, z którym zacząłeś).
W praktycznych językach programowania nie zobaczysz doskonałej przejrzystości referencyjnej, ale funkcjonalnym programistom zależy na tym bardziej niż większości (por. Haskell, gdzie jest to główny cel).
(Pełne ujawnienie: Jestem programistą funkcjonalnym, więc przy pierwszej odpowiedzi powinieneś wziąć to wyjaśnienie z odrobiną soli.)
W 1 widać klarowność dwóch języków:
W 2, dzięki bliskości przedmiotu i języków metalowych, można je pomylić.
Jako realizator języka uważam, że muszę stale pamiętać o tym rozróżnieniu.
Prof. Reddy, mogę sparafrazować was w ten sposób :-)
W kontekście programowania funkcjonalnego i semantyki termin Przezroczystość referencyjna nie jest referencyjnie przejrzysty.
Poniższa odpowiedź, mam nadzieję, uzupełnia i kwalifikuje kontrowersyjne odpowiedzi 1 i 3.
Przyznajmy, że wyrażenie oznacza lub odnosi się do jakiegoś odniesienia. Pytanie brzmi jednak, czy odniesienia te mogą być kodowane izomorficznie jako część samych wyrażeń, nazywając takie wyrażenia „wartościami”. Na przykład wartości liczb literalnych są podzbiorem zbioru wyrażeń arytmetycznych, wartości prawdy są podzbiorem zbioru wyrażeń boolowskich itp. Chodzi o to, aby ocenić wyrażenie na jego wartość (jeśli ma takie wyrażenie). Zatem słowo „wartość” może odnosić się do denotacji lub do wyróżnionego elementu zestawu wyrażeń. Ale jeśli istnieje izomorfizm (bijection) między odniesieniem a wartością, możemy powiedzieć, że są tym samym. (To powiedziawszy, należy uważać, aby zdefiniować odniesienia i izomorfizm, czego dowodzi pole semantyki denotacyjnej. Aby podać przykład wspomniany w odpowiedziach na trzecią odpowiedź,data Nat = Zero | Suc Nat
nie odpowiada oczekiwanemu zestawowi liczb naturalnych).
Napiszmy E[·]
dla wyrażenia z dziurą, znanego również w niektórych miejscach jako „kontekst”. Dwa kontekstowe przykłady wyrażeń podobnych do C to [·]+1
i
[·]++
.
Napiszmy [[·]]
dla funkcji, która przyjmuje wyrażenie (bez dziury) i podaje swoje znaczenie (odniesienie, denotacja itp.) W jakimś wszechświecie dostarczającym znaczenia. (Pożyczam notację z dziedziny semantyki denotacyjnej.)
Dostosujmy definicję Quine'a nieco formalnie w następujący sposób: kontekst E[·]
jest referencyjnie przejrzysty iff, biorąc pod uwagę dowolne dwa wyrażenia E1
i E2
(bez dziur) taki, że [[E1]] = [[E2]]
(tj. Wyrażenia oznaczają / odnoszą się do tego samego odwołania) to jest tak, że [[E[E1]]] = [[E[E2]]]
(tj. Wypełnienie -w otworze z albo E1
albo E2
powoduje wyrażenie, które również oznacza to samo odniesienie).
Zasada Leibniza polegająca na zamianie równości na równość jest zwykle wyrażana jako „jeśli
E1 = E2
to E[E1] = E[E2]
”, co E[·]
oznacza, że jest to funkcja. Funkcja (lub w tym przypadku program obliczający funkcję) to mapowanie ze źródła do celu, tak że dla każdego elementu źródłowego istnieje co najwyżej jeden element docelowy. Funkcje niedeterministyczne są mylącymi nazwami, są albo relacjami, funkcjami dostarczającymi zbiory itp. Jeśli w regule Leibniza równość =
jest denotacyjna, to podwójny nawias jest po prostu brany za pewnik i unika. Tak więc referencyjnie przejrzysty kontekst jest funkcją. Reguła Leibniza jest głównym składnikiem rozumowania równań, więc rozumowanie równania jest zdecydowanie powiązane z przejrzystością referencyjną.
Chociaż [[·]]
jest funkcją od wyrażeń do denotacji, może być funkcją od wyrażeń do „wartości” rozumianych jako ograniczony podzbiór wyrażeń i [[·]]
może być rozumiany jako ocena.
Teraz, jeśli E1
jest wyrażeniem i E2
wartością, mamy to, co myślę, że ma na myśli większość ludzi, definiując przejrzystość referencyjną pod względem wyrażeń, wartości i oceny. Ale jak ilustrują 1. i 3. odpowiedź na tej stronie, jest to niedokładna definicja.
Problem z kontekstami takimi jak [·]++
nie jest efektem ubocznym, ale że jego wartość nie jest zdefiniowana w C izomorficznie do jego znaczenia. Funkcje nie są wartościami (no, wskaźniki do funkcji), podczas gdy w funkcjonalnych językach programowania są. Landin, Strachey i pionierzy denotacyjnej semantyki dość sprytnie używali światów funkcjonalnych do nadawania znaczenia.
W przypadku imperatywnych języków podobnych do C możemy (z grubsza) zapewnić semantykę wyrażeń za pomocą funkcji [[·]] : Expression -> (State -> State x Value)
.
Value
jest podzbiorem Expression
. State
zawiera pary (identyfikator, wartość). Funkcja semantyczna przyjmuje wyrażenie i dostarcza jako swoje znaczenie funkcję od stanu bieżącego do pary ze stanem zaktualizowanym i wartością. Na przykład [[x]]
jest funkcją od stanu bieżącego do pary, której pierwszym składnikiem jest stan bieżący, a drugim składnikiem jest wartość x. Natomiast [[x++]]
jest funkcją od stanu bieżącego do pary, której pierwszym składnikiem jest stan, w którym wartość x jest zwiększana, a którego drugim składnikiem jest właśnie ta wartość. W tym sensie kontekst [·]++
jest referencyjnie przejrzysty, jeżeli spełnia powyższą definicję.
Myślę, że programiści funkcjonalni mają prawo do korzystania z przezroczystości referencyjnej w tym sensie, że naturalnie odzyskują [[·]]
funkcję funkcji od wyrażeń do wartości. Funkcje są pierwszorzędnymi wartościami, a stan może być również wartością, a nie denotacją. Monada stanu jest (częściowo) czystym mechanizmem przekazywania (lub tworzenia wątków) stanu.
Zauważ, że ta koncepcja „znaczenia” dzieje się w umyśle obserwatora. Zatem to samo „odniesienie” może oznaczać różne rzeczy dla różnych ludzi. Na przykład w Wikipedii mamy stronę z ujednoznacznieniem w Edynburgu.
Powiązanym zagadnieniem, które może pojawić się w kontekście programowania, może być polimorfizm.
Być może powinniśmy mieć nazwę specjalnego przypadku polimorfizmu (a może nawet rzutowania), w którym dla naszych celów różne przypadki polimorficzne są semantycznie równoważne (a nie tylko podobne. Na przykład liczba 1 - która może być reprezentowana przy użyciu typu liczby całkowitej, typu złożonego lub dowolnego z wielu innych typów - można je traktować polimorficznie).
Uznałem, że definicja przejrzystości referencyjnej w książce „ Struktura i implementacja programów komputerowych ” (Wizard Book) jest przydatna, ponieważ uzupełnia ją wyjaśnienie, w jaki sposób naruszona została przejrzystość referencyjna poprzez wprowadzenie operacji przypisania . Sprawdź następującą zjeżdżalnię, którą zrobiłem na ten temat: https://www.slideshare.net/pjschwarz/introducing-assignment-invalidates-the-substitution-model-of-aluation-and-violates-referenceial-transparency-as- wyjaśnił-w-sicp-the-Wizard-book
Przejrzystość odniesienia można po prostu określić jako:
Na przykład język programowania Haskell jest językiem czysto funkcjonalnym; co oznacza, że jest referencyjnie przejrzysty.