Nie do końca zrozumiałem pojęcie efektu ubocznego.
- Jaki jest efekt uboczny w programowaniu?
- Czy to zależy od języka programowania?
- Czy istnieje coś takiego jak zewnętrzne i wewnętrzne skutki uboczne?
Podaj przykład przyczyn, które powodują skutki uboczne.
programming-languages
functional-programming
Amir Rezaei
źródło
źródło
Odpowiedzi:
Efektem ubocznym odnosi się po prostu do zmiany swego rodzaju stanu, na przykład -:
W przeciwieństwie do tego, co niektórzy ludzie mówią:
Efekt uboczny nie musi być ukryty ani nieoczekiwany (może być, ale nie ma to nic wspólnego z definicją, ponieważ dotyczy informatyki);
Efekt uboczny nie ma nic wspólnego z idempotencją. Funkcja idempotentna może mieć skutki uboczne, a funkcja niebędąca idempotentna może nie mieć żadnych skutków ubocznych (takich jak uzyskanie bieżącej daty i godziny systemowej).
To naprawdę bardzo proste. Efekt uboczny = coś gdzieś zmienić.
PS Jak zauważa komentator Benjol, kilka osób może łączyć definicję efektu ubocznego z definicją czystej funkcji , która jest funkcją, która jest (a) idempotentna i (b) nie ma skutków ubocznych. Jedno nie implikuje drugiego w ogólnej informatyce, ale funkcjonalne języki programowania zwykle mają tendencję do egzekwowania obu ograniczeń.
źródło
++a
. Nie wygląda jak zadanie.b = ++a;
ma dwa skutki uboczne. Oczywiste i krypto-przypisaniea
. Jest to coś, co jest efektem ubocznym, który (dla niektórych) jest pożądany. Ale został nazwany efektem ubocznym w całej mojej karierze, aby nie był subtelny.Mówi się, że każda operacja, która zmienia stan komputera lub wchodzi w interakcję ze światem zewnętrznym, ma efekt uboczny. Zobacz Wikipedia na temat efektów ubocznych .
Na przykład ta funkcja nie ma skutków ubocznych. Jego wynik zależy tylko od argumentów wejściowych i nic nie zmienia stanu programu ani jego środowiska, gdy jest wywoływane:
Natomiast wywołanie tych funkcji da różne wyniki w zależności od kolejności, w jakiej je wywołujesz, ponieważ zmieniają coś o stanie komputera:
Ta funkcja ma efekt uboczny zapisywania danych na wyjściu. Nie wywołujesz funkcji, ponieważ chcesz jej wartość zwracaną; nazywacie to, ponieważ chcecie, aby miało to wpływ na „świat zewnętrzny”:
źródło
Write
pokazuje twój przykład, wywoływanie efektów ubocznych nie oznacza, że funkcja kiedykolwiek zmienia swoje dane wyjściowe w odniesieniu do swoich danych wejściowych, ani nawet że ich wyniki zależą w ogóle od danych wejściowych.square(x)
może spowodować załadowanie modułu, w którym zdefiniowano funkcję, z dysku. Czy należy to uznać za efekt uboczny? W końcu to męskie, że (pierwsze) wywołanie zajmuje nieoczekiwanie długo, że zwiększa się użycie pamięci RAM itp.square(x)
ponieważ chcesz zmienić stan komputera zewnętrznego, możesz uznać to za efekt uboczny.Myślę, że istniejące odpowiedzi są całkiem dobre. Chciałbym rozwinąć niektóre aspekty, które IMO nie były wystarczająco zestresowane.
W matematyce funkcja jest po prostu odwzorowaniem krotki wartości na wartość. Tak więc, biorąc pod uwagę funkcję
f
i wartośćx
,f(x)
zawsze będzie ten sam wyniky
. Można również wymienićf(x)
sięy
wszędzie w wyrażeniu i nic się nie zmieni.W wielu językach programowania funkcja (lub procedura) nazywana jest konstrukcją (fragmentem kodu), którą można wykonać, ponieważ:
Efekty można więc powiązać ze stanem, ale także z innymi aspektami, takimi jak wystrzelenie pocisku lub wstrzymanie egzekucji na kilka sekund.
Termin efekt uboczny może wydawać się negatywny, ale zwykle efekt wywołania funkcji jest głównym celem samej funkcji. Podejrzewam, że skoro termin funkcja był pierwotnie używany w matematyce, obliczenie wartości jest uważane za główny efekt funkcji, podczas gdy wszelkie inne efekty są uważane za skutki uboczne . Niektóre języki programowania używają terminu procedura, aby uniknąć pomyłek z funkcjami w sensie matematycznym.
Zauważ, że
sleep()
W Pythonie, są użyteczne tylko dla ich (ubocznych) efektów,. Często są one modelowane jako funkcje, które zwracają specjalną wartośćNone
lubunit
lub()
lub…, co po prostu wskazuje, że obliczenia zakończyły się poprawnie.źródło
Efekt uboczny występuje, gdy operacja ma wpływ na zmienną / obiekt, który jest poza zamierzonym użyciem.
Może się to zdarzyć, gdy wywołasz funkcję złożoną, której efektem ubocznym jest zmiana jakiejś zmiennej globalnej, nawet jeśli nie z tego powodu ją wywołałeś (być może wywołałeś ją, aby wyodrębnić coś z bazy danych).
Przyznaję, że mam problem z wymyśleniem prostego przykładu, który nie wygląda na całkowicie wymyślony, a przykłady z rzeczy, nad którymi pracowałem, są zbyt długie, aby je tutaj opublikować (a ponieważ jest to związane z pracą, prawdopodobnie i tak nie powinienem ).
Jednym z przykładów, które widziałem (jakiś czas temu), była funkcja, która otworzyła połączenie z bazą danych, jeśli połączenie było w stanie zamkniętym. Problem polegał na tym, że miał on zamknąć połączenie na końcu funkcji, ale programista zapomniał dodać ten kod. Tak więc tutaj wystąpił niezamierzony efekt uboczny: wywołanie procedury miało jedynie wykonać zapytanie, a efektem ubocznym było to, że połączenie pozostało otwarte, a jeśli funkcja zostanie wywołana dwa razy z rzędu, pojawi się błąd informujący, że połączenie było już otwarty.
Ok, skoro wszyscy podają teraz przykłady, myślę, że ja też;)
Funkcja
do_task_x
ma podstawowy wpływ powrocie wynik pewnych obliczeń i boczny efekt ewentualnie modyfikując zmienną globalną.Oczywiście, który jest pierwotny i który jest efektem ubocznym, może być otwarty na interpretację i może zależeć od faktycznego użycia. Jeśli wywołam tę funkcję w celu modyfikacji globalnej i odrzucę zwróconą wartość, powiedziałbym, że modyfikacja globalnej jest głównym efektem.
źródło
Z Wikipedii - Efekt uboczny
W sensie matematycznym funkcja jest odwzorowaniem między danymi wejściowymi a wyjściowymi. Zamierzonym efektem wywołania funkcji jest odwzorowanie danych wejściowych na wynik, który zwraca. Jeśli funkcja robi cokolwiek innego, nie ma znaczenia co, ale jeśli ma jakieś zachowanie, które nie mapuje danych wejściowych na dane wyjściowe, wiadomo, że takie zachowanie jest efektem ubocznym.
Mówiąc bardziej ogólnie, efektem ubocznym jest każdy efekt, który nie jest zamierzonym efektem projektanta konstrukcji.
Efektem jest wszystko, co wpływa na aktora. Jeśli wywołam funkcję, która wysyła mojej dziewczynie wiadomość tekstową zerwania, która wpływa na grupę aktorów, mnie, ją, sieć firmy komórkowej itp. Jedynym zamierzonym efektem wywołania funkcji bez skutków ubocznych jest funkcja aby zwrócić mi mapowanie z moich danych wejściowych. Więc dla:
Jeśli ma to być funkcja, jedyne, co powinien zrobić, to return void. Jeśli byłby wolny od skutków ubocznych, nie powinien tak naprawdę wysyłać wiadomości tekstowej.
W większości języków programowania nie ma konstrukcji dla funkcji matematycznej. Żaden konstrukt nie jest przeznaczony do takiego zastosowania. Dlatego większość języków mówi, że masz metody lub procedury. Z założenia są one w stanie wykonać znacznie więcej efektów. W potocznym języku programowania nikt tak naprawdę nie dba o to, czym jest metoda lub procedura, więc kiedy ktoś mówi, że ta funkcja ma efekt uboczny, oznacza to, że konstrukcja nie zachowuje się jak funkcja matematyczna. A kiedy ktoś mówi, że ta funkcja jest wolna od efektów ubocznych, oznacza to, że konstrukcja ta zachowuje się jak funkcja matematyczna.
Z definicji czysta funkcja jest zawsze wolna od skutków ubocznych. Czysta funkcja jest sposobem, aby powiedzieć, że ta funkcja, mimo że używa konstrukcji, która pozwala na więcej efektów, ma tylko taki sam efekt jak funkcja matematyczna.
Wzywam każdego, by powiedział mi, kiedy funkcja bez skutków ubocznych nie byłaby czysta. O ile pierwotny zamierzony efekt kontekstu zdania przy użyciu terminu czysty i wolny od skutków ubocznych nie jest skutkiem matematycznego zamierzonego efektu funkcji, to są one zawsze równe.
Jako takie, czasami, choć rzadziej, i uważam, że jest to rozróżnienie, w którym brakuje ludzi, a także wprowadzających w błąd ludzi (ponieważ nie jest to najczęstsze założenie) w przyjętej odpowiedzi, ale czasami zakłada się, że zamierzonym efektem funkcji programowania jest odwzorować dane wejściowe na dane wyjściowe, gdzie dane wejściowe nie są ograniczone do jawnych parametrów funkcji, ale dane wyjściowe są ograniczone do jawnej wartości zwracanej. Jeśli założymy, że jest to zamierzony efekt, to funkcja odczytująca plik i zwracająca inny wynik na podstawie tego, co znajduje się w pliku, jest nadal wolna od efektów ubocznych, ponieważ zezwalasz na dane wejściowe pochodzące z innych miejsc zamierzonego efektu.
Dlaczego to wszystko jest tak ważne?
Chodzi o kontrolę i utrzymanie go. Jeśli wywołujesz funkcję, która robi coś innego, a następnie zwraca wartość, trudno jest uzasadnić jej zachowanie. Będziesz musiał zajrzeć do funkcji, aby znaleźć właściwy kod, aby odgadnąć, co robi i potwierdzić jego poprawność. Idealną sytuacją jest to, że jest bardzo jasne i łatwe do zrozumienia, z jakiego wejścia korzysta funkcja, i że nie robi nic innego, niż zwracanie dla niej wyniku. Możesz to trochę rozluźnić i powiedzieć, że wiedza o tym, czego używa, nie jest tak pomocna, jak pewność, że nie robi nic innego, czego możesz nie być świadomy, a następnie zwrócić wartość, więc być może jesteś zadowolony z samego tylko egzekwowania że nie robi nic innego, ale mapuje dane wejściowe, bez względu na to, skąd je bierze, na dane wyjściowe.
W prawie wszystkich przypadkach celem programu jest uzyskanie efektów innych niż mapowanie rzeczy wchodzących do rzeczy wychodzących. Idea kontrolowania efektu ubocznego polega na tym, że możesz uporządkować kod w sposób łatwiejszy do zrozumienia i uzasadnienia. Jeśli połączysz wszystkie skutki uboczne w miejscu, które jest bardzo wyraźne i centralne, łatwo jest wiedzieć, gdzie szukać i ufać, że to wszystko, co się dzieje, nigdy więcej. Jeśli dane wejściowe są również bardzo wyraźne, pomaga to przetestować zachowanie dla różnych danych wejściowych i jest łatwiejsze w użyciu, ponieważ nie trzeba zmieniać danych wejściowych w wielu różnych miejscach, niektóre z nich mogą nie być oczywiste, po prostu aby dostać to, czego chcesz.
Ponieważ najbardziej pomocne w zrozumieniu, zrozumieniu i kontrolowaniu zachowania programu jest wyraźne pogrupowanie wszystkich danych wejściowych i jednoznaczne, a także zgrupowanie wszystkich skutków ubocznych i jednoznaczne, o tym mówią ludzie, kiedy mówią efekt uboczny, czysty itp.
Ponieważ najbardziej pomocne jest grupowanie skutków ubocznych i ich jawność, czasami ludzie będą to tylko oznaczać i rozróżniać, mówiąc, że nie jest czysty, ale nadal „wolny od skutków ubocznych”. Ale efekt uboczny jest związany z założonym „zamierzonym efektem pierwotnym”, więc jest to termin kontekstowy. To, co znajduję, jest rzadziej używane, choć o dziwo w tym wątku wiele się mówi.
Wreszcie, idempotent oznacza wielokrotne wywoływanie tej funkcji z tymi samymi danymi wejściowymi (nieważne, skąd pochodzą) zawsze skutkuje tymi samymi efektami (efekt uboczny lub nie).
źródło
Podczas programowania efektem ubocznym jest zmiana procedury spoza zakresu. Efekty uboczne nie są zależne od języka. Istnieje kilka klas języków, które mają na celu wyeliminowanie skutków ubocznych (czysto funkcjonalne języki), ale nie jestem pewien, czy istnieją takie, które wymagają efektów ubocznych, ale mogę się mylić.
O ile mi wiadomo, nie ma wewnętrznych i zewnętrznych skutków ubocznych.
źródło
Oto prosty przykład:
Definicja efektu ubocznego nie jest specyficzna dla programowania, więc po prostu wyobraź sobie skutki uboczne twojego meds lub jedzenia zbyt dużej ilości jedzenia.
źródło
x++
modyfikuje zmienną,x
jest powszechnie uważany za efekt uboczny. Ta wartość wyrażenia jest wartością wstępną inkrementux
; jest to część wyrażenia niezwiązana z efektem ubocznym.Efektem ubocznym są rzeczy, które dzieją się w kodzie, które nie są oczywiście oczywiste.
Powiedzmy na przykład, że masz tę klasę
Kiedy początkowo tworzysz klasę, dajesz jej zalążek.
Nie znasz elementów wewnętrznych, po prostu oczekujesz, że otrzymasz losową wartość i możesz oczekiwać, że randomGenerator. Seed nadal będzie miał 15 ... ale tak nie jest.
Wywołanie funkcji miało efekt uboczny zmiany wartości Seed.
źródło