为什么“从文件中读取”不是纯粹的功能?

时间:2015-07-13 07:32:22

标签: scala functional-programming

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

  • 读取或写入文件

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

参见我的例子:

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

4 个答案:

答案 0 :(得分:13)

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

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

答案 1 :(得分:6)

如果函数是纯函数,那么执行common subexpression elimination总是安全的,即你可以替换下面的伪代码

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)
}

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

答案 2 :(得分:2)

在函数式编程中,如果

,函数为pure
  
      
  1. 在给定相同参数值的情况下,函数始终评估相同的结果值。功能结果值不能依赖于任何   程序执行时可能发生变化的隐藏信息或状态   继续或在程序的不同执行之间,也不可能   取决于I / O设备的任何外部输入。
  2.   
  3. 评估结果不会导致任何语义上可观察到的副作用或输出,例如可变对象或输出的突变   到I / O设备。
  4.   

I/O can be modelled in a pure way if

  
      
  1. 相关I / O设备上的操作序列被明确建模为参数和结果,并且
  2.   
  3. 当输入序列没有描述自程序开始以来实际采取的操作时,I / O操作失败   执行。
  4.   

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

答案 3 :(得分:0)

如果函数针对相同的输入参数给出相同的结果,则它是纯函数,因此:

  • 函数write(file)并不纯,因为给定相同的file可能导致成功或失败。

  • 函数read(file)并不纯,因为给定相同的file,每次返回或失败都会返回不同的数据。

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

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

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

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

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