我昨天是在StackOverflow的开发天会议和扬声器的人谈论的Python。 他表现出了memoize的功能,我问是否有什么办法阻止它在非纯函数中使用。 他说,不,这基本上是不可能的,如果有人能想出一个办法做到这一点,将成为一位伟大的博士论文。
那种搞糊涂了,因为它似乎并不那么困难的编译器/解释递归解决。 在伪代码:
function isPure(functionMetadata): boolean;
begin
result = true;
for each variable in functionMetadata.variablesModified
result = result and variable.isLocalToThisFunction;
for each dependency in functionMetadata.functionsCalled
result = result and isPure(dependency);
end;
这是基本的想法。 显然,你需要某种形式的检查,以防止互相依赖的功能无限递归的,但是这不是太难以成立。
称取函数指针高阶函数可能是有问题的,因为他们不能静态验证,但我原来的问题的前提是,编译器具有某种语言的约束来指定,只有纯函数的指针可以传递给某个参数。 如果一个人的存在,可能被用来满足该条件。
显然,这将是一个比一个解释编译语言更容易,因为在执行程序之前,所有这些数字运算将完成,因此不会慢下来什么,但我真的没有看到任何根本问题,就不可能评估。
有没有人在这方面多一点知识,知道我缺少的是什么?
它是在Python特别难。 由于anObject.aFunc
可以任意在运行时改变,你不能在编译时该功能将决定anObject.aFunc()
调用或者即使这将是一个功能都没有。
您还需要标注每个系统调用,每个FFI,...
进而最小的“泄漏”易于泄漏到整个代码库。
这不是一个理论上棘手的问题,但在实践中是非常非常困难的方式,整个系统不会觉得脆做。
顺便说一句,我不认为这成为一名优秀的博士论文; 哈斯克尔有效地已经有(一版),这一点,与IO单子。
我相信很多人继续看这个“实践”。 (狂炒)20年后,我们可能都没有了。
在这里除了其他优秀的答案:你看的伪代码仅在功能是否修改变量。 但是,这并不是真的是“纯粹”的手段。 “纯”通常是指更接近于“引用透明。” 换句话说,输出是完全依赖于输入。 因此,作为读当前时间和制作,在结果的因素(或输入读取或读机的状态,或......)这样简单的事情,使功能非纯,而无需修改任何变量。
此外,你可以写做了修改变量“纯”的功能。
下面是突然出现在我的脑海里,当我读了你的问题的第一件事。
类层次结构
确定是否修改的变量包括穿过其被称为该变量以确定它是否突变每个单独的方法挖的行为。 这是有点...直线前进用于密封型与非虚拟方法。
但考虑虚拟方法。 你必须找到每一个派生类型,并验证该方法的每一个覆盖不发生变异状态。 确定这是根本不可能在任何语言/框架,允许动态代码生成或仅仅是动态的(如果可能的话,这是非常困难的)。 之所以是一组派生类型是不固定的,因为一个新的可以在运行时产生的。
取C#作为一个例子。 尽管没有理由产生在运行时派生类将覆盖虚拟方法,并修改状态阻止我。 验证静态将不能够检测到这种类型的修饰的并因此无法验证方法是纯的或没有。
我认为主要的问题将得到有效地这样做。
d-语言具有纯函数,但是你必须自己指定,所以编译器会知道进行检查。 我认为,如果你手工指定它们那么这将是更容易做到。
决定一个给定的功能是否是纯粹的,一般情况下还原为决定任何给定的程序是否将停止 - 这是众所周知,停机问题是不能有效地解决问题的一种。
需要注意的是复杂性取决于语言了。 对于更多的动态语言,它可以在任何时候重新定义什么。 例如,在Tcl的
proc myproc {a b} {
if { $a > $b } {
return $a
} else {
return $b
}
}
每一个单件的,可以在任何时间进行修改。 例如:
- “如果”命令可以改写使用和更新全局变量
- “返回”命令,沿着相同的路线,可能会做同样的事情
- 所述可能是在,当“如果”被使用时,返回命令是基于输入到如果命令重新定义了如果命令的执行轨迹
诚然,Tcl是一个极端的例子; 最动态的语言之一,也是。 话虽这么说,它强调的是它可以是难以确定甚至一旦你进入它的功能的纯度问题。