Dlaczego odczyt z pamięci nie jest efektem ubocznym, ale odczyt z pliku?

16

Co dokładnie czyni odczyt z pamięci procesu czystą operacją? Załóżmy, że utworzyłem tablicę 100 liczb całkowitych w pamięci globalnej, a następnie wziąłem 42 element tej tablicy. To nie jest efekt uboczny, prawda? Dlaczego więc odczytanie tej samej tablicy 100 liczb całkowitych z pliku jest efektem ubocznym?

ZhekaKozlov
źródło
5
rozważ edycję, aby wyjaśnić, co sprawia, że ​​uważasz, że odczytanie tablicy 100 liczb całkowitych z pliku jest efektem ubocznym, a także, co oznacza dla Ciebie „czysta operacja”
gnat,
3
@gnat Ponieważ to I / O, a I / O to efekt uboczny
ZhekaKozlov
3
co sprawia, że ​​myślisz, że I / O to efekt uboczny? rozważ edycję, aby wyjaśnić to pytającym czytelnikom. Mówiąc bardziej ogólnie, dzielenie się badaniami pomaga wszystkim . Powiedz nam, co próbowałeś i dlaczego nie spełnia twoich potrzeb. To pokazuje, że poświęciłeś trochę czasu, aby spróbować sobie pomóc, oszczędza nam to powtarzania oczywistych odpowiedzi, a przede wszystkim pomaga uzyskać bardziej konkretną i odpowiednią odpowiedź. Zobacz także How to Ask
gnat
22
@gnat I / O to efekt uboczny, kropka. To jeden z klasycznych przykładów. Nie jesteśmy Wikipedią, nie potrzebujemy cytatów dla wiedzy ludowej. Jeśli uważasz, że coś można poprawić w kwestii pytania, powiedz to wprost, zamiast przechodzić przez tego słomianego człowieka.
7
„O” to efekt uboczny. „Ja” jest tylko efektem ubocznym, jeśli robienie „ja” zmienia stan tego, z czego robisz „ja”. Co jest prawdą w przypadku niektórych operacji we / wy odwzorowanych w pamięci, ale jest mało prawdopodobne, aby miało to miejsce w przypadku normalnego pliku.
Tom Tanner,

Odpowiedzi:

27

Jeśli pamięć, do której masz dostęp, może się zmienić, to rzeczywiście jest to efekt uboczny.

Na przykład w Haskell funkcja dostępu do tablicy zmiennych ( IOArray) ma typ

Ix i => IOArray i e -> i -> IO e

(nieco uproszczone dla naszych celów). Podczas uzyskiwania dostępu do niezmiennej tablicy ma typ

Ix i => Array i e -> i -> e

Pierwsza wersja zwraca coś w rodzaju, IO eco oznacza, że ​​ma skutki uboczne I / O. Druga wersja po prostu zwraca element typu ebez żadnych skutków ubocznych.

W przypadku uzyskania dostępu do pliku, po prostu nie możesz wiedzieć w czasie kompilacji, czy plik kiedykolwiek się zmieni podczas uruchamiania programu. Dlatego zawsze należy traktować to jako operację z potencjalnymi skutkami ubocznymi.

Tobias Brandt
źródło
4
Cóż, z plikami po prostu nie możesz być absolutnie pewien.
pią.
2
Nigdy nie możesz być pewien, ale co ważniejsze: kompilator nie może być pewien. Ponadto system plików może ulec uszkodzeniu lub dysk twardy może się rozłączyć podczas odczytywania pliku.
Tobias Brandt,
5
To nie są skutki uboczne programu, to skutki uboczne innych rzeczy. Pamięć nie jest również wolna od skutków ubocznych, ponieważ cząsteczka alfa lub neutron zbłąkany może nieco odwrócić się i spowodować zmianę w tablicy.
Blrfl,
3
@Blrfl To dobra uwaga, ale nie sądzę, by obie były porównywalne. Uszkodzenie pamięci nie jest czymś, z czym można sobie poradzić, ponieważ może wpływać na dane programu i instrukcje w dowolny sposób. Jeśli tak się stanie, jedyne, co należy zrobić, to zakończyć program (i prawdopodobnie system operacyjny). Z drugiej strony błąd odczytu spowodowany uszkodzeniem systemu plików jest czymś, czego należy się spodziewać i być w stanie sobie z tym poradzić. Jest to nieodłączna część postępowania z plikami.
Tobias Brandt,
2
Wychodzisz z królestwa efektów ubocznych i wykrywasz błędy oraz radzisz sobie z nimi, co jest zupełnie inną dyskusją. Pytanie o skutki uboczne dotyczy tego, czy operacja ma jakikolwiek wpływ na cokolwiek innego, czy nie, czy na wynik operacji mogą wpływać czynniki zewnętrzne.
Blrfl,
10

W informatyce mówi się, że funkcja lub wyrażenie ma efekt uboczny, jeśli oprócz zwracania wartości modyfikuje także pewien stan lub ma zauważalną interakcję z funkcjami wywoływania lub światem zewnętrznym. Czytanie z pliku to obserwowalna interakcja ze światem zewnętrznym. Spełnia definicję działania niepożądanego. Odczytanie 42. elementu z pamięci globalnej byłoby również skutkiem ubocznym, chyba że tablica jest stała, ponieważ byłaby obserwowalną interakcją z innymi funkcjami, które mogą modyfikować tablicę.

kamieniste
źródło
2

Jeśli masz współużytkowany uchwyt pliku, to odczytanie pliku spowoduje przeniesienie tego uchwytu pliku do pozycji, w której przeczytałeś i pozostawi go w tej pozycji.

Jeśli masz dwa wątki z osobnymi uchwytami plików do tego samego pliku, odczyt jednego z nich nie będzie miał zauważalnego efektu ubocznego na drugim.

Jednak w obu przypadkach, podczas odczytu pamięci i odczytu plików, może wystąpić ukryty efekt uboczny buforowania systemu operatora.

Dojną krową
źródło
0

Odczytywanie z pamięci nie wpływa na inne funkcje i dlatego jest wolne od skutków ubocznych. Odczytywanie z pliku zazwyczaj przesuwa wskaźnik pozycji pliku, dzięki czemu po ponownym czytaniu odczytujesz dane po tym, co już przeczytałeś, więc jedna funkcja odczytu zmienia wynik innych funkcji odczytu, co jest efektem ubocznym. Jeśli zamiast tego otworzysz, przeczytasz i zamkniesz plik za jednym razem, ten efekt uboczny zniknie, ale nie jest to możliwe w przypadku dużych plików. Dodatkowo, w zależności od sposobu otwierania pliku, może on zostać zablokowany po otwarciu, więc pierwsza próba otwarcia i odczytania pliku zakończy się powodzeniem, a kolejne próby zakończą się błędem Plik już otwarty , co znowu jest efektem ubocznym.

Utworzenie funkcji odczytu bez skutków ubocznych, która odczytuje plik za jednym razem i umożliwia wielokrotne odczytywanie w tym samym czasie, jest trudne, ponieważ istnieją funkcje zapisu plików, na które wpływ ma funkcja odczytu, a pozbycie się funkcji zapisu plików ponownie nie jest możliwe .

nwp
źródło
1
Mógłbyś mieć odczyt skutków ubocznych z pliku, jeśli plik się nie zmienił i zmieniłeś plik w strumień (leniwa lista).
Giorgio
2
Dotarcie do systemu operacyjnego w celu uzyskania pliku, który nie jest pod Twoją kontrolą, jest efektem ubocznym. Tylko jeśli potrafisz kontrolować zmienność pliku (a może operacje mutacji sekwencji na nim… za pomocą IOmonady?), Możesz zrobić funkcję odczytu bez skutków ubocznych.
Bergi
0

Odczytywanie ze strumienia jest już efektem ubocznym, ponieważ wynik takich funkcji, jak isEOFmoże zwrócić inny wynik po odczycie niż przed odczytem.

Hagen von Eitzen
źródło