为什么从内存读取不是副作用,而从文件读取却是副作用?


16

是什么使从过程存储器中进行的读取真正成为纯操作?假设我在全局内存中创建了一个100个整数的数组,然后使用了该数组的第42个元素。这不是副作用,对吗?那么,为什么从文件中读取相同的100个整数数组会产生副作用呢?


5
考虑编辑以解释是什么使您认为从文件中读取100个整数的数组是一个副作用,以及“纯运算”对您的含义是什么?
2014年

3
@gnat因为它是I / O,并且I / O是一个副作用
ZhekaKozlov 2014年

3
是什么让您认为I / O是副作用?考虑编辑以向读者提问。概括地说,分享您的研究成果对每个人都有帮助。告诉我们您尝试过的内容以及为什么它不能满足您的需求。这表明您已花时间尝试自我帮助,这使我们免于重复显而易见的答案,并且最重要的是,它可以帮助您获得更具体和相关的答案。另请参阅“ 如何提问
2014年

22
@gnat I / O是一个副作用。这是经典示例之一。我们不是维基百科,我们不需要引用民间知识。如果您认为可以改善此问题,请直言不讳,而不要直言不讳。

7
“ O”是副作用。如果执行“我”更改了您正在执行“我”的状态,则“我”只是一个副作用。这对于某些内存映射的I / O事情是正确的,但对于普通文件则不太可能。
汤姆·坦纳

Answers:


27

如果您访问的内存可以更改,则确实是副作用。

例如,在Haskell中,访问可变数组(IOArray)的函数的类型为

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

(出于我们的目的略有简化)。访问不可变数组时,类型为

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

第一个版本返回某种类型的东西,IO e这意味着它具有I / O副作用。第二个版本仅返回类型的元素,e而没有任何副作用。

在访问文件的情况下,您根本无法在编译时知道文件在程序运行期间是否会更改。因此,您必须始终将其视为具有潜在副作用的手术。


4
好吧,对于文件,您根本无法完全确定。
ftr

2
您永远无法确定,但更重要的是:编译器无法确定。此外,在读取文件时,文件系统可能已损坏或硬盘可能断开连接。
Tobias Brandt 2014年

5
这些不是程序的副作用,它们是其他事情的副作用。内存也不是没有副作用的,因为α粒子或杂散中子会翻转一点并导致阵列发生变化。
Blrfl 2014年

3
@Blrfl很好,但是我不认为两者具有可比性。内存损坏不是您可以解决的问题,因为它会以任意方式影响程序数据和指令。如果发生这种情况,唯一要做的就是终止程序(可能是操作系统)。另一方面,由于文件系统损坏而导致的读取错误是您必须期望并能够处理的。这是处理文件的固有部分。
Tobias Brandt 2014年

2
您将摆脱副作用,而进入错误检测和处理,这是完全不同的讨论。副作用问题是一项操作是否会对其他任何事情产生影响,而不是一项操作的结果是否会受到外部因素的影响。
Blrfl 2014年


2

如果您具有共享文件句柄,则读取文件会将文件句柄移至您已读取的位置,并将其保留在该位置。

如果您有两个线程具有对同一个文件的单独文件句柄,则从一个线程进行读取不会对另一个线程产生明显的副作用。

但是,在这两种情况下(内存读取和文件读取),操作员系统缓存都可能具有隐藏的副作用。


0

从内存中读取不会影响其他功能,因此没有副作用。从文件中进行读取通常会移动文件的位置指针,因此,当您再次读取时,您将在已读取的内容之后读取数据,因此一个读取函数会更改其他读取函数的结果,这是一个副作用。如果改为打开,读取和关闭文件,则此副作用消失了,但这不适用于大文件。此外,根据打开文件的方式,打开文件后它可能会被锁定,因此首次尝试打开和读取文件成功,而随后的尝试将失败,并出现“ 文件已打开”错误,这也是一个副作用。

创建一个一次性读取文件并允许多次读取的无副作用读取功能是困难的,因为有些文件写入功能会受到读取功能的影响,而放弃文件写入功能又不可行。


1
如果文件没有更改,并且已将文件转换为流(惰性列表),则可能会有副作用,可以从文件中自由读取。
乔治

2
向操作系统寻求不受您控制的文件一种副作用。仅当您可以控制文件的可变性(并可能通过IOmonad 对它进行序列变异操作吗?)时,您才能实现无副作用的读取功能。
Bergi 2014年

0

从流中进行读取已经是一种副作用,因为诸如之类的函数的isEOF结果在读取之后可能会与读取之前返回不同的结果。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.