Przejdź do zawartości

Przejrzystość referencyjna

Z Wikipedii, wolnej encyklopedii

W filozofii analitycznej i informatyce (nie)przejrzystość referencyjna jest cechą konstruktów lingwistycznych, a co za tym idzie, języków. Konstrukcję językową nazywamy przejrzystą referencyjnie, gdy dla dowolnego zbudowanego z niej wyrażenia zastąpienie podwyrażenia innym, oznaczającym tę samą wartość[1] nie powoduje zmiany wartości wyrażenia. [2] W przeciwnym razie, mamy do czynienia z wyrażeniem nieprzejrzystym referencyjnie. Każde wyrażenie zbudowane na podstawie referencyjnie nieprzejrzystej konstrukcji językowej stwierdza coś na temat podwyrażenia, podczas gdy każde wyrażenie zbudowane na podstawie referencyjnie przejrzystej konstrukcji językowej stwierdza coś nie dotyczącego podwyrażenia, co oznacza, że podwyrażenia są „przejrzyste” względem wyrażenia, pełniąc jedynie rolę „odniesień” do czegoś innego.[3] Na przykład, wyrażenie „_ był mądry” jest referencyjnie przejrzyste (np. Sokrates był mądry jest równoznaczne z Założyciel filozofii zachodniej był mądry), ale „_ powiedział _” jest referencyjnie nieprzejrzyste (np. Ksenofont powiedział, że Sokrates był mądry nie jest równoznaczne z Ksenofont powiedział, że założyciel filozofii zachodniej był mądry).

Przejrzystość referencyjna zależy od wartości nadawanych wyrażeniom, czyli semantyki języka. Zarówno deklaratywne, jak i imperatywne języki programowania mogą zatem być referencyjnie przejrzyste lub referencyjnie nieprzejrzyste, w zależności od używanej semantyki. Na przykład swobodna modyfikacja globalnego stanu z reguły nie jest referencyjnie transparentna, gdyż dane wyjściowe funkcji nie są zależne wyłącznie od jej danych wejściowych, ale również od ukrytych zależności (będących poza zakresem funkcji i jej wywołania). Taka funkcja przestaje wówczas być czystą funkcją, tj. funkcją w matematycznym tego słowa znaczeniu i staje się potencjalnie niedeterministyczna.[4]

Istotą przejrzystości referencyjnej jest umożliwienie programistom i kompilatorom analizę zachowania programu jako systemu przepisywania. Może to ułatwiać dowodzenie poprawności, upraszczanie algorytmów, modyfikacje kodu bez „psucia” go lub optymalizacje z użyciem memoizacji, eliminacji wspólnych podwyrażeń, leniwego wartościowania lub obliczeń równoległych. Dla przykładu system gwarantujący, iż więcej niż jeden wątek nie dokona modyfikacji tych samych danych może wyeliminować konieczność stosowania niektórych mechanizmów synchronizacji, jak m.in. mechanizmy wzajemnego wykluczania (por. model aktorów stosowany np. w Erlangu, czy też pamięć transakcyjna).[5][6][7]

Przypisy

[edytuj | edytuj kod]
  1. Tutaj wartość jest denotacją (zwaną także znaczeniem, przedmiotem lub odniesieniem) wyrażenia, a nie wynikiem procesu ewaluacji kodu.
  2. Willard Van Orman Quine: Word and Object. Wyd. 1st. Cambridge, Massachusetts: MIT Press, 1960, s. 144. ISBN 978-0-262-17001-7.
  3. Alfred North Whitehead: Principia Mathematica. Wyd. 2nd. T. 1. Cambridge: Cambridge University Press, 1927, s. 665. ISBN 978-0-521-06791-1.
  4. Referential Transparency as a mechanism for building Reliable Programs [online], Habr, 8 sierpnia 2023 [dostęp 2024-05-06] (ang.).
  5. Paolo Costa, Concurrent Programming in Java. [online], Dipartimento di Elettronica e Informazione Politecnico di Milano, Włochy [dostęp 2024-05-06] (ang.).
  6. Konrad Siek, Distributed Pessimistic Transactional Memory: Algorithms and Properties, Politechnika Poznańska, 2016 [dostęp 2024-08-05] (ang.).
  7. Beyond Locks: Software Transactional Memory [online], Bartosz Milewski's Programming Cafe, 11 września 2010 [dostęp 2024-08-05] (ang.).