是什么使从过程存储器中进行的读取真正成为纯操作?假设我在全局内存中创建了一个100个整数的数组,然后使用了该数组的第42个元素。这不是副作用,对吗?那么,为什么从文件中读取相同的100个整数数组会产生副作用呢?
是什么使从过程存储器中进行的读取真正成为纯操作?假设我在全局内存中创建了一个100个整数的数组,然后使用了该数组的第42个元素。这不是副作用,对吗?那么,为什么从文件中读取相同的100个整数数组会产生副作用呢?
Answers:
如果您访问的内存可以更改,则确实是副作用。
例如,在Haskell中,访问可变数组(IOArray
)的函数的类型为
Ix i => IOArray i e -> i -> IO e
(出于我们的目的略有简化)。访问不可变数组时,类型为
Ix i => Array i e -> i -> e
第一个版本返回某种类型的东西,IO e
这意味着它具有I / O副作用。第二个版本仅返回类型的元素,e
而没有任何副作用。
在访问文件的情况下,您根本无法在编译时知道文件在程序运行期间是否会更改。因此,您必须始终将其视为具有潜在副作用的手术。
在计算机科学中,如果函数或表达式除了返回值之外还修改了某些状态或与调用函数或外界有可观察的交互作用,则称其具有副作用。 从文件读取是与外界的可观察的交互。它符合副作用的定义。除非您的数组是一个常量,否则从全局内存中读取第42个元素也是一个副作用,因为这是与其他可能修改数组的函数的可观察的交互。
从内存中读取不会影响其他功能,因此没有副作用。从文件中进行读取通常会移动文件的位置指针,因此,当您再次读取时,您将在已读取的内容之后读取数据,因此一个读取函数会更改其他读取函数的结果,这是一个副作用。如果改为打开,读取和关闭文件,则此副作用消失了,但这不适用于大文件。此外,根据打开文件的方式,打开文件后它可能会被锁定,因此首次尝试打开和读取文件成功,而随后的尝试将失败,并出现“ 文件已打开”错误,这也是一个副作用。
创建一个一次性读取文件并允许多次读取的无副作用读取功能是困难的,因为有些文件写入功能会受到读取功能的影响,而放弃文件写入功能又不可行。
IO
monad 对它进行序列变异操作吗?)时,您才能实现无副作用的读取功能。