2015-07-13 17 views
6

W książce „Programowanie funkcji w Scala”, to daje kilka przykładem tego, co jest „skutki uboczne”, jednym z nich jest:Dlaczego "czytanie z pliku" nie jest czystą funkcją?

  • odczytywania lub zapisywania danych do pliku

Rozumiem, że "pisanie do pliku" nie jest czyste, ponieważ zmienia środowisko. Ale dlaczego "czytanie pliku" nie jest czyste? Nic nie zmienia.

Zobacz mój przykład:

val readFile: File => String = file => readingTheContentFromFile(file) 
+1

Czy zastanawiałeś się, w jaki sposób tylko część pliku zmienia tylko "odczytany wskaźnik" pliku, czy też dotyczy tylko odczytu całego pliku i zakładając, że zawartość pliku jest zawsze taka sama (co jest, oczywiście, odcinek)? –

+0

możliwy duplikat [Czy jest to czysta funkcja, jeśli odczytuje niektóre dane z zewnątrz zamiast parametrów?] (Http://stackoverflow.com/questions/31376933/is-it-a-pure-function-if-it-reads -some-data-from-outside-rather-than-parameters) –

Odpowiedz

13

Czysty funkcja zawsze dobrze zwraca taką samą wartość podaną samo wejście. W przeciwnym razie opiera się na efektach ubocznych (takich jak zmiana pliku). Jeśli czytasz z pliku, wyniki mogą ulec zmianie bez parametrów przypisanych do zmiany funkcji.

Właściwa koncepcja to "przejrzystość referencyjna". Oznacza to, że możesz zastąpić wywołanie funkcji i dany zestaw parametrów wynikiem, który funkcja zwróci. Czytanie z pliku nie jest zatem referencyjnie przejrzyste!

+0

Tak, czysta funkcja może zmienić się tylko wtedy, gdy zmieniają się jej parametry. Jeśli odczytuje z pliku, plik ten może się zmienić niezależnie od parametrów funkcji. –

2

W programowaniu funkcjonalnej funkcja jest pure jeśli

  1. Funkcja ocenia zawsze taką samą wartość wyników podano taką samą wartość (wartości) argumentów. Wartość wyniku funkcji nie może zależeć od ukrytej informacji lub stanu, które mogą ulec zmianie podczas wykonywania programu, ani od jego wpływu na jakiekolwiek zewnętrzne wejście urządzeń I/O.
  2. Ocena wyniku nie powoduje żadnego zauważalnego semantycznie efektu ubocznego lub wyniku, takiego jak mutacja zmiennego obiektu lub wyjście do urządzeń we/wy.

I/O can be modelled in a pure way jeśli

  1. sekwencji operacji na odpowiednich urządzeń I/O jest modelowana wyraźnie zarówno jako argumentu, a w wyniku, a
  2. operacje We/Wy są brane zawodzi, gdy sekwencja wejściowa nie opisuje operacji faktycznie wykonanych od momentu uruchomienia programu.

Oznacza to, że zamiast rzeczywiście czyta z pliku, masz „zawartość pliku jest” jako parametr, a zamiast rzeczywiście pisanie do pliku, będzie zwrot „Plik wyjściowy jest” jako wartość. Wydaje się, że jest to ćwiczenie myślowe w większości praktycznych języków.

6

Jeśli funkcja jest czysta, to jest zawsze bezpieczne wykonywanie common subexpression elimination to można zastąpić następujący pseudokod

do { 
    x = readFile "file.txt" 
    writeFile "file.txt" "Goodbye" 
    return (x + readFile "file.txt") 
} 

z

do { 
    x = readFile "file.txt" 
    writeFile "file.txt" "Goodbye" 
    return (x + x) 
} 

i co można uzyskać ten sam rezultat.Ale oczywiście, z powodu wywołania writeFile, które pojawia się między dwoma wywołaniami do readFile w pierwszym przykładzie, nie jest to bezpieczna transformacja, a zatem funkcja nie jest czysta.

+0

Dzięki, to jest dobry przykład! – Freewind