繁体   English   中英

为什么“从文件中读取”不是纯函数?

[英]Why "reading from a file" is not pure function?

在《Scala 函数编程》一书中,给出了几个“副作用”的例子,其中之一是:

  • 读取或写入文件

我可以理解“写入文件”并不纯粹,因为它改变了环境。 但为什么“读文件”不纯? 它不会改变任何东西。

看我的例子:

val readFile: File => String = file => readingTheContentFromFile(file)

给定相同的输入,纯函数总是返回相同的值。 否则它是基于副作用(如更改文件)。 如果您从文件中读取,结果可能会更改,而不会更改给函数的参数。

相关概念是“参考透明度”。 这意味着您可以用函数将返回的结果替换一个函数调用和一组给定的参数。 因此,从文件中读取不是引用透明的!

如果函数是纯函数,那么执行 公共子表达式消除总是安全的,即您可以替换以下伪代码

do {
  x = readFile "file.txt"
  writeFile "file.txt" "Goodbye"
  return (x + readFile "file.txt")
}

do {
  x = readFile "file.txt"
  writeFile "file.txt" "Goodbye"
  return (x + x)
}

你会得到同样的结果。 但很明显,由于在第一个示例中两次调用readFile之间出现了对writeFile的调用,因此这不是一个安全的转换,因此该函数不是纯函数。

在函数式编程中,如果函数是函数

  1. 给定相同的参数值,该函数始终计算相同的结果值。 函数结果值不能依赖于在程序执行过程中或在程序的不同执行之间可能发生变化的任何隐藏信息或状态,也不能依赖于来自 I/O 设备的任何外部输入。
  2. 结果的评估不会导致任何语义上可观察的副作用或输出,例如可变对象的突变或输出到 I/O 设备。

I/O 可以以纯粹的方式建模,如果

  1. 相关 I/O 设备上的操作序列被显式建模为参数和结果,以及
  2. 当输入序列没有描述自程序开始执行以来实际执行的操作时,I/O 操作将被视为失败。

也就是说,不是实际从文件中读取,而是将“文件的内容”作为参数,而不是实际写入文件,而是将“文件的输出”作为值返回。 在大多数实用语言中,这似乎是一种思考练习。

如果一个函数对于相同的输入参数给出相同的结果,那么它是纯函数,所以:

  • 函数write(file)不是纯函数,因为在给定相同的file情况下,它可能导致成功或失败。

  • 函数read(file)不是纯函数,因为在给定相同的file ,它每次都可以返回不同的数据或失败。

因为它们不是纯的,它们不是引用透明的,也就是说,函数调用write(file)read(file)不能被其结果替换,因为下次进行相同的调用时可能会产生不同的结果。

纯函数的美妙之处在于,如果它们现在成功,那么如果它们和它们调用的函数此后没有改变,您就可以确信它们将继续成功。

请注意,纯度与改变或不改变环境无关,因为:

  • 每个函数内部都对计算机内存进行读写,并消耗能量,因此每个函数都会改变环境;

  • 如果读取和写入同一个文件总是返回相同的结果,那么这些函数将是纯函数,尽管它们接触环境。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM