为什么println被认为是一个不纯的函数



我正在读一本用scala编程的书,据说:

。。。在这种情况下,它的副作用是打印到标准输出流。

我不知道副作用在哪里,因为对于相同的输入,println将打印相同的输出(我认为(
更新
例如,任何时候我们调用:

println(5)

它将打印5,我看不到调用println(5)会打印5以外的值的情况!!

您可以通过将表达式替换为其结果来判断表达式是否有副作用。如果程序将更改为,则会产生副作用。例如,

println(5)

是的不同程序

()

也就是说,副作用是指未在表达式求值结果中编码的任何可观察到的效果。这里的结果是(),但这个值中没有任何内容来编码5现在已经出现在屏幕上的某个地方的事实。

副作用是在计算机状态下。每次调用println()时,内存状态都会发生变化,以便向终端显示给定值。或者更一般地,标准输出流的状态被改变。

考虑以下类比

var out: String = ""
def myprintln(s: String) = {
out += s // this non-local mutation makes me impure
()
}

这里myprintln是不纯的,因为除了返回值()之外,它还变异了非局部变量out作为副作用。现在假设out是香草println变异的流。

这个问题已经得到了很好的答案,但让我加两分钱。

如果您在println函数内部查看,它本质上与java.lang.System.out.println()相同——因此,当您在后台调用Scala的标准库println方法时,它会调用PrintStream对象实例上的方法println,该对象实例在System类中声明为字段out(或者更准确地说,在Console对象中声明为outVar(,从而更改其内部状态。这可以看作是CCD_ 18是不纯函数的另一种解释。

希望这能有所帮助!

这与引用透明度的概念有关。如果可以在不更改程序的情况下用其求值结果替换表达式,则表达式是引用透明的

当一个表达式不是引用透明的时,我们说它有副作用

f(println("effect"), println("effect"))
// isn't really equivalent to!
val x = println("effect")
f(x, x)

import cats.effect.IO
def printlnIO(line: String): IO[Unit] = IO(println(line))
f(printlnIO("effect"), printlnIO("effect"))
// is equivalent to
val x = printlnIO("effect")
f(x, x)

您可以在此处找到更详细的解释:https://typelevel.org/blog/2017/05/02/io-monad-for-cats.html

相关内容

  • 没有找到相关文章

最新更新