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

Scala 为什么println被认为是一个不纯函数?,scala,functional-programming,pure-function,Scala,Functional Programming,Pure Function,我正在读《scala编程》一书,书中说: 。。。在这种情况下,其副作用是打印到标准输出流 我不知道副作用在哪里,因为对于相同的输入,println将打印相同的输出(我认为) 更新 例如,任何时候我们打电话: println(5) 它将打印5,我没有看到调用println(5)将打印5以外的值的情况 您可以通过用结果替换表达式来判断表达式是否有副作用。如果程序改变了意思,就会有副作用。比如说, println(5) 这是一个不同的程序 () 也就是说,副作用是在计算表达式的结果中没有编码的任

我正在读《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
类中声明为field
out
(或者更准确地说是
outVar
Console
对象中),这会改变它的内部状态。这可以看作是另一种解释,
println
为什么是不纯函数


希望这有帮助

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

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

f(println(“效果”)、println(“效果”))
//真的不等于!
val x=println(“效果”)
f(x,x)

导入cats.effect.IO
def printlnIO(行:字符串):IO[单位]=IO(println(行))
f(打印输入(“效果”)、打印输入(“效果”))
//相当于
val x=打印输入(“效果”)
f(x,x)

你可以在这里找到更详细的解释:

如果这回答了你的问题,我将删除我在这里的答案。相关(lol)你混淆了副作用(非引用透明)和确定性
println
是一个确定性函数,但为了纯粹,它也必须是RT。因为它除了计算结果并返回结果外,还做其他事情。实际上,这不是“副作用”的好定义,副作用可以定义为破坏引用透明度的任何东西。你试图展示的是RT,但你的例子是错误的。由于多次执行某件事情应该多次执行同一件事情,因此,
val a=println(“hello”);val b=(a,a)
应该与
val b=(pritnln(“hello”)、println(“hello”)
@LuisMiguelMejíaSuárez相同也许我的例子不清楚,但我不认为这是错的。我本质上是在指出程序
println(5)
()
之间的区别。或者你是说最后一句话?是的,但你不清楚。因为,正如我所说,问题不是多次调用某个对象,问题是用它的定义替换引用是否会产生这种影响。我认为这是错误的,因为某个对象完全可能有副作用,并且是幂等的,所以重复它不会改变效果。例如,分配给可变变量;如何区分
x=1
x=1;x=1;x=1
?@AlexeyRomanov我已经编辑了我的答案。但以你为例,我不明白第二次和第三次作业是如何产生副作用的。没有任何变化。如果部分为真,执行任何操作都会改变指令计数器的状态,因此任何操作都是副作用。副作用的定义源于引用透明性的定义,许多人将其定义为对共享可变状态的修改。。。。将是不纯的,因为它改变了内存cpu的状态…,谢谢您的响应,很明显您的函数是不纯的,但是,为什么scala中定义的println()不是不纯的呢pure@aName因为除了返回值
()
它也会在中变异非局部状态。我认为这个答案缺少的关键事实是println在输入中添加了换行符。我不明白为什么f(x,x)与f(println(“效果”)、println(“效果”)不同
f(println(“效果”),println(“效果”)
将在控制台“效果”中打印两次,而
val x=println(“效果”);f(x,x)
将打印一次。函数f的定义是什么