Co To jest czysta funkcja?
korzyści
korzystanie z czystych funkcji ma wiele zalet, zarówno pod względem wydajności, jak i użyteczności.
czytelność
czyste funkcje są znacznie łatwiejsze do odczytania i rozsądne. Wszystkie istotne dane wejściowe i zależności są dostarczane jako parametry, więc nie obserwuje się żadnych efektów, które zmieniają zmienne poza zestawem danych wejściowych.
oznacza to, że możemy szybko zrozumieć funkcję i jej zależności, po prostu czytając deklarację funkcji. Tak więc, jeśli funkcja jest zadeklarowana jako f(a, b, c)
to wiemy, że tylko a
b
I c
są zależnościami f
.
przenośność
ponieważ wszystkie zależności są dostarczane jako parametry wejściowe i nie są dostępne za pośrednictwem globalnego kontekstu, te zależności mogą być zamieniane w zależności od kontekstu, w którym funkcja jest wywoływana.
oznacza to, że ta sama funkcja może działać na różnych implementacjach tego samego zasobu, na przykład.
To sprawia, że kod jest znacznie bardziej przenośny i wielokrotnego użytku, ponieważ ta sama funkcja może być używana w różnych kontekstach, zamiast pisać inną funkcję tylko po to, aby użyć innej implementacji tej samej klasy.
na przykład, zamiast pisać dwie różne nieczyste funkcje, aby używać dwóch różnych rejestratorów, które są przechowywane globalnie, czysta funkcja po prostu przyjmowałaby żądany rejestrator jako dane wejściowe.
testowanie
brak efektów ubocznych sprawia, że czyste funkcje są bardzo łatwe do przetestowania, ponieważ musimy tylko sprawdzić, czy wejścia wytwarzają pożądane wyjścia. Nie musimy sprawdzać poprawności żadnego globalnego stanu programu w naszych testach konkretnych funkcji.
Ponadto, ponieważ wszystkie zależności są dostarczane jako dane wejściowe, możemy łatwo kopiować zależności. W nieczystym otoczeniu musielibyśmy śledzić stan jakiejś globalnej zależności przez wszystkie testy.
jednak w czystym ustawieniu po prostu podalibyśmy wszystkie zależności jako dane wejściowe. Nie musimy już martwić się o utrzymanie globalnego stanu w trakcie naszych testów i możemy teraz potencjalnie dostarczać różne wersje zależności do różnych testów.
To pozwala nam testować funkcje, jednocześnie wyraźnie kontrolując dostarczone zależności w każdym teście.
przezroczystość referencyjna
przezroczystość referencyjna odnosi się do możliwości zastąpienia wywołania funkcji odpowiednią wartością wyjściową bez zmiany zachowania programu.
aby uzyskać przejrzystość odniesienia, funkcja musi być czysta. Ma to zalety pod względem czytelności i szybkości. Kompilatory są często w stanie zoptymalizować kod, który wykazuje referencyjną przezroczystość.
buforowanie
ponieważ czyste funkcje zawsze zwracają to samo wyjście dla tego samego wejścia, możemy buforować wyniki czystych wywołań funkcji.
buforowanie odnosi się do używania techniki, takiej jak memoizacja, do przechowywania wyników funkcji tak, że musimy je obliczyć tylko raz.
zazwyczaj dla funkcjif: Input -> Output
jest to realizowane poprzez mapę (taką jak hash-map) zInput -> Output
.
wykonując funkcję, najpierw sprawdzamy, czy mapa zawiera dane wejściowe jako klucz. Jeśli tak, zwracamy wartość wyjściową mapy, w przeciwnym razie obliczamy f(input)
, a następnie przechowujemy wynik na mapie przed zwróceniem go.