纯函数和不纯函数的区别?
Posted
技术标签:
【中文标题】纯函数和不纯函数的区别?【英文标题】:Difference between pure and impure function? 【发布时间】:2014-04-19 04:08:14 【问题描述】:我假设纯函数必须始终有一个返回类型(即,不能是void
),并且无论对象的状态如何,都必须具有相同的输出,并且不纯函数会更改对象的状态或打印对象的状态。
但我使用的教科书指出:
访问器通常包含返回语句,但打印对象状态信息的方法也可以归类为访问器。
我很困惑。哪一个是正确的?
编辑
稍微澄清一下,让我问的是这个问题:
最后一个问题是“给出使用的函数的类型”,那里评论的人说它是一个不纯的函数,因为它正在打印。
那么这个函数是纯的还是不纯的?
【问题讨论】:
我一直听说“访问器”被用作“getter”的同义词:一个基本上只返回一个值的函数,可能首先进行一些状态检查。但是这个概念与纯度正交,所以我不太确定你的问题是什么意思。您假设函数子集的属性(“纯函数必须具有返回类型”),然后在完全不同的函数子集上声明另一个属性,然后询问哪个是正确的。没有什么能阻止两者都是正确的(除了我从未听说过访问器的定义)。 编辑后,在我看来,这里真正的问题是access()
是否实际上是一个访问器;我会说不是。纯度问题似乎仍然是正交的,从您的问题来看,您似乎已经知道该部分的答案。 :)
Re“打印对象状态信息的方法也可以归类为访问器。” - 教科书是错误的。 Accessors
返回信息给调用者 - 他们不使用“边带”通信(在这种情况下是打印)从对象获取信息到其他地方。打印是一种副作用;它不会被视为“访问”/“访问”数据。
请注意,图像中的示例代码无法编译:access()
被声明为返回 Void
类型的实例,但其主体没有。此外,这个例子违反了 Java 命名约定,因为它规定类名应该用 PascalCase 编写。
【参考方案1】:
内容取自this link
纯函数的特性:
纯函数的返回值完全取决于它的参数 因此,如果您使用相同的参数集调用纯函数,您将始终获得相同的返回值。
它们没有任何副作用,例如网络或数据库调用
它们不会修改传递给它们的参数不纯函数的特征
不纯函数的返回值不仅仅取决于它的参数 因此,如果您使用相同的参数集调用不纯函数,您可能会得到不同的返回值 例如,Math.random()、Date.now()
它们可能有任何副作用,例如网络或数据库调用
他们可以修改传递给他们的参数
function impureFunc(value)
return Math.random() * value;
function pureFunc(value)
return value * value;
var impureOutput = [];
for(var i = 0; i < 5; i++)
impureOutput.push(impureFunc(5));
var pureOutput = [];
for(var i = 0; i < 5; i++)
pureOutput.push(pureFunc(5));
console.log("Impure result: " + impureOutput); // result is inconsistent however input is same.
console.log("Pure result: " + pureOutput); // result is consistent with same input
【讨论】:
【参考方案2】:来自Wikipedia - 如果关于函数的这两个陈述都成立,则函数可以被描述为纯函数:
-
给定相同的参数值,该函数始终评估相同的结果值。函数结果值不能依赖于任何隐藏信息或状态,这些信息或状态可能会随着程序执行的进行或在程序的不同执行之间发生变化,也不能依赖于来自 I/O 设备的任何外部输入。
结果的评估不会导致任何语义上可观察的副作用或输出,例如可变对象的突变或输出到 I/O 设备。
因此,如果与您的代码相比,任何一个语句都是错误的,那么它就是不纯的。
【讨论】:
我个人认为打印诊断或跟踪输出在语义上是不可观察的,这就是为什么我不愿以一种或另一种方式发表关于打印任何内容的声明。 并从***链接添加到您的答案。 printf() 是不纯的,因为它会导致输出到 I/O 设备作为副作用。似乎该功能在打印时不纯 - System.out.println【参考方案3】:Mu. 您似乎假设访问器根据定义是纯函数。不一定是这种情况——访问器(甚至是返回值的get
-accessor)可能是不纯的,例如在访问顺序模式下LinkedHashMap
的get
方法(它将请求的条目移动到迭代顺序的最后一个位置)。
【讨论】:
【参考方案4】:两个陈述都是正确的。
当您创建称为 ACCESSOR METHODS 的获取价值的方法时
例如:
public String getName()
return this.name;
对于设置值,我们使用带有 VOID 的方法,称为 MUTATOR METHODS
例如:
public void setName(String n)
this.name=n;
【讨论】:
【参考方案5】:不纯函数或 Mutator 方法改变对象的状态并修改存储在实例变量中的值。
【讨论】:
以上是关于纯函数和不纯函数的区别?的主要内容,如果未能解决你的问题,请参考以下文章