Wydaje się, że czytając coś takiego jak ten artykuł Wikipedii o „czystych funkcjach” , wymieniają Today()
jako przykład nieczystej funkcji, ale wydaje mi się to dość czyste. Czy dlatego, że nie ma formalnego argumentu wejściowego? Dlaczego faktyczna pora dnia nie jest traktowana jako „wejście do funkcji”, w którym to przypadku, jeśli podałeś jej to samo wejście, tj. Wykonałeś today()
dwa razy w tym samym czasie lub cofnąłeś się w czasie, aby wykonać je ponownie (być może hipotetyczny: )), wynik będzie taki sam. Today()
nigdy nie daje ci losowej liczby. zawsze daje ci porę dnia.
Artykuł w Wikipedii mówi „w różnych momentach da to różne wyniki”, ale to tak, jakby powiedzieć, że dla różnych x
sin(x)
da różne proporcje. I sin(x)
jest ich przykładem czystej funkcji.
źródło
Odpowiedzi:
Jest tak, ponieważ wynik zależy od czegoś, co nie jest wejściem, a mianowicie od bieżącego czasu.
Ponieważ nie przekazałeś go jako parametru. Jeśli podasz go jako parametr, funkcja stanie się funkcją tożsamości w datach, co jest dość bezużyteczne. Celem całej
Today()
funkcji jest wyprowadzenie czegoś, co zależy od zewnętrznej i ciągle zmieniającej się wartości (czasu).Zaletą czystych funkcji jest to, że ich zachowanie jest absolutnie powtarzalne i deterministyczne, co ułatwia posiadanie formalnych dowodów i twardych gwarancji. Zawsze robią to samo.
Today()
jest wręcz przeciwnie: zawsze (uwzględniając ziarnistość czasu) robi coś innego.źródło
Today()
),Today()
staje się nieczysty. TaToday()
funkcja może być trochę głupim przykładem. Bardziej odpowiednia może być jakaśCount()
funkcja. Biorąc pod uwagę tę samą liczbę elementów do zliczeniaCount()
, zawsze zwróci tę samą liczbę, ale ponieważ jest to poza zakresemCount()
, jest nieczysta.count()
w większości języków programowania jest zdecydowanie czysty. Ma wyraźną wartość wejściową: kolekcję, której liczbę chcesz. Nie daj się pomylić składni takiej jakmyCollection.count()
; to tylko cukiercount(myCollection)
.sin(x)
zawsze zwraca tę samą wartość, o ilex
pozostaje taka sama.Today()
mogą zwracać różne wyniki w czasie, ponieważ zależy to od wartości poza twoją kontrolą . Na przykład, jeśli coś poza kontrolą twojego programu zmieni wnętrze systemu$current_datetime
podczas jego działania,Today()
nagle przyniesie inne wyniki.źródło
Today()
zwróci „czwartek” w poniedziałek.Today () jest nieczystą funkcją, ponieważ jej wynik zależy od czegoś, czego jej nie dajesz; konkretnie aktualny czas systemowy. Dlatego jego wynik nie jest deterministyczny, jeśli opiera się wyłącznie na danych wejściowych dostarczonych podczas wywołania.
Byłaby to czysta funkcja
int Add(int a, int b) {return a + b;}
. Funkcja działa wyłącznie z tym, co została podana, i nie wykorzystuje innych danych o stanie zewnętrznym. Naturalnym rezultatem tego jest to, że możeszAdd(2,2)
zdobyć 4 od teraz do końca czasu. Ponadto, ponieważ funkcja nie zmienia żadnego stanu zewnętrznego (nie ma „skutków ubocznych”), dodawanie (2) i 2 od teraz aż do końca czasu nie zmieni niczego innego w systemie, chyba że wtedy przypisz wynik funkcji do zmiennej lub w inny sposób użyj wartości do aktualizacji stanu (co nie jest operacją wykonywaną przez samą funkcję). Praktycznie wszystkie klasyczne operacje matematyczne są czystymi funkcjami i mogą być jako takie realizowane.Z drugiej strony Today () może wygenerować tę samą wartość, gdy zostanie wywołany dwa razy z rzędu, ale nie, jeśli zostanie wywołany wielokrotnie przez kilka dni. Wynika to z faktu, że jest on zależny od danych o stanie zewnętrznym, które nie są dostarczane przez Ciebie jako parametr funkcji. W rezultacie niemożliwe jest kontrolowanie wyniku funkcji Today () w granicach programu. Będzie generować określoną wartość w danym dniu i nigdy nie wytworzy tej wartości w żadnym innym dniu, chyba że zmienisz zegar systemowy komputera, na którym jest on uruchomiony (zmiana zwykle występuje poza granicami programu).
Zanieczyszczona funkcja niekoniecznie jest złą rzeczą; nieczyste funkcje są wymagane, nawet w językach funkcjonalnych, do interakcji z czymkolwiek poza granicami programu, takimi jak magazyny danych, potoki komunikacyjne, wyświetlacze interfejsu użytkownika, urządzenia peryferyjne itp. Program, który nie wykonuje żadnej z tych czynności, jest programem jest to znacznie ograniczone pod względem użyteczności; Posunąłbym się nawet do tego, że nazwałbym taki program trywialnym, ponieważ bez jakiegokolwiek sposobu akceptacji danych wejściowych lub jakiejkolwiek drogi do poinformowania cię o jego wyniku, równie dobrze mógłby nic nie robić. Programy napisane w językach funkcjonalnych mogą mieć tylko dane wejściowe dostarczone przez środowisko wykonawcze i generować dane wyjściowe zgłaszane do środowiska wykonawczego bez żadnych wyraźnie zdefiniowanych nieczystych metod, ale dzieje się tak, ponieważ środowisko wykonawcze wyodrębnia wszystkie te nieczyste szczegóły pracy w niedoskonałym systemie komputerowym,
Po prostu Bardzo Dobrą Rzeczą jest wiedzieć, które z funkcji, których używasz, są czyste, a które nie, abyś mógł podejmować trafne decyzje dotyczące ich użycia. Zanieczyszczone funkcje, ponieważ robią rzeczy lub są zależne od rzeczy, które nie są oczywiste z ich użycia, mogą zachowywać się nieprzewidywalnie, biorąc pod uwagę tylko wiedzę o użytkowaniu. Konieczna jest dalsza znajomość celu funkcji, a tym samym tego, czego potrzebuje od stanu zewnętrznego lub do czego służy, aby ustawić system, który używa go w spójnym stanie, a tym samym oczekiwać wyniku deterministycznego.
źródło
Wydaje się dość oczywiste, że ta funkcja nie spełnia pierwszego testu czystości podanego na samym początku tej strony:
Zauważ, że ponieważ nie przyjmuje żadnych argumentów, istnieje tylko jeden możliwy zestaw wartości argumentów - pusty zbiór. Ta funkcja może i zwraca różne wyniki dla tych samych „wartości argumentów”.
Ponadto, wartość wynik funkcji jest uzależnione od „ukrytej ... stanu, który może się zmienić w miarę postępu realizacji programu”. Więc kolejna porażka.
źródło
() => 1
byłaby czystą funkcją, ponieważ zawsze zwraca 1.Today()
może zwrócić „poniedziałek” lub „wtorek” lub prawie dowolną inną wartość.Innym sposobem myślenia o tym jest to, że czyste funkcje nie zależą od stanu. Świat jest zwykle uważany za stan. Musisz znać stan rzeczywistości, aby wiedzieć, jaki jest dzisiaj dzień.
Jednak nie musisz wiedzieć nic specjalnego o stanie świata, aby wiedzieć, co
sin(x)
jest. I zawsze wezwanie dosin(x)
danejx
zwraca tę samą wartość.źródło
Date(timestamp)
byłaby czystą funkcją. Z powodu jego idempotencji. A ponieważ nie byłoby żadnego efektu ubocznego.Today()
może różnić się w zależności od tego, kiedy do niego zadzwonisz. To czyni go nieczystym. To nie jest idempotentne. Nie ma to jednak żadnego efektu ubocznego, ale to nie czyni go czystym.źródło
Oto mały pseudo kod, o którym myślę omawiając czyste funkcje
Jeśli działa to w nieskończoność i nigdy nie może wywołać potwierdzenia, jest to czysta funkcja. Co więcej, jeśli masz funkcję, która używa argumentów, to mała modyfikacja ....
Jeśli możesz użyć tego po każdym przypisaniu zmiennej w swojej aplikacji, a to nie zmienia wyników w aplikacji i nigdy nie może zawieść potwierdzenia, to jest to czysta funkcja.
źródło
Po pierwsze, nie ma czegoś takiego jak funkcja bez argumentów (lub tablica bez indeksów lub mapa bez kluczy). Jest to cecha definiująca funkcję mapowania jednej lub więcej wartości argumentów na inną wartość.
Dlatego też
today
albo wcale nie jest funkcją, a zatem nie jest funkcją czystą. Lub możemy zinterpretować składniętrochę, żeby to znaczyło
Na przykład w Haskell byłoby to prawidłowe:
ponieważ istnieje typ () z pojedynczą wartością ().
Pytanie tylko, jak
today
obliczyć dzień tygodnia, jeśli ma tylko ()? Jest to po prostu niemożliwe bez odczytu timera systemowego, bezpośrednio lub za pomocą nieczystych funkcji pomocnika.Timer systemowy jest doskonałym przykładem stanu globalnego.
źródło
Problem
today()
polega na tym, że może dać inny wynik, jeśli zostanie wywołany dwa lub więcej razy w funkcji.Oto przykład kodu, który może wprowadzić błąd.
Jest to możliwe w powyższym przykładzie. To, że drugie
if
zdanie nie zostanie wykonane. Nawet jeśli pierwszy. Pozostawienie zasobu w złym stanie.źródło
Aby być czystą funkcją, zapewnienie tych samych parametrów musi dawać ten sam wynik za każdym razem.
Za każdym razem, gdy dzwonimy
Today()
, zapewniamy te same parametry (brak), ale niekoniecznie uzyskujemy ten sam wynik (poniedziałek, wtorek itp.).źródło