Javascript 一个返回thunk的函数是纯函数,而不管潜在的操作是什么?
Javascript 一个返回thunk的函数是纯函数,而不管潜在的操作是什么?,javascript,functional-programming,Javascript,Functional Programming,getFeedbackThunk是纯的吗 function setWinTitle(msg) { window.document.title = msg; } function getFeedbackThunk(msg) { return () => setWinTitle(msg); } voteButton.onclick = getFeedbackThunk('Thanks for voting!'); 它不与外部状态交互,输出总是由输入决定的。令人困惑的是,输
getFeedbackThunk
是纯的吗
function setWinTitle(msg) {
window.document.title = msg;
}
function getFeedbackThunk(msg) {
return () => setWinTitle(msg);
}
voteButton.onclick = getFeedbackThunk('Thanks for voting!');
它不与外部状态交互,输出总是由输入决定的。令人困惑的是,输出的目的是产生效果,但我认为我们可以说函数本身是纯函数。在这个特定示例中,我同意您的观点。但一般来说(即为了暗示代码优化),没有语法保证。在C++中,有强制执行的常量方法:
// C++ code
class Feedback {
string state;
// here the const guarantees not to change the state
void getFeedbackThunk(string msg) const {
...
}
};
但是在JS中没有这样的const用法。是的,它是纯的,因为您推迟了有效的计算。尽管如此,它仍然不安全,因为没有任何东西可以阻止你释放效果并破坏你的纯程序。您需要一个包含不纯计算的类型,并且不提供提取它的方法。为了使这种类型有用,它还必须包含一种在其内部构成不纯计算的方法。你可能已经知道我在说什么了:不可避免的单子。在Javascript中我们没有编译器,因此我们唯一能做的就是使用Monad来处理延迟的计算。@bob“在Javascript中我们没有编译器”老实说,我们有一个JIT编译器。@Seblor更迂腐,机器级别以上的每种语言都有编译器,否则它不会运行。但在这种情况下,我很确定他指的是一个强制执行静态类型系统的编译器。@JaredSmith“更迂腐一些,机器级别以上的每种语言都有一个编译器,否则它就不会运行了。”你这是什么意思?除非你对“compiler”或“has”有一些非常奇怪的定义,否则这是不对的。翻译一种语言而不把它翻译成机器代码(或任何其他语言)是完全可能的。JIT编译器(甚至字节码编译器)纯粹是一种优化——完全可以使用基于AST的解释器解释编程语言。@JaredSmith在这一点上重要的是,在JS中,您可以通过调用不纯净的表达式来释放效果,因为它只是包装在一个普通的thunk中:
getFeedbackThunk(msg)(
)。没有任何机制可以阻止你。在Haskell中,这个thunk看起来像RealWorld->((),RealWorld)
,但是因为没有RealWorld
类型的值,所以不能调用它。只有运行时系统才能做到这一点。我认为不可能用解释器或JIT编译器重现这种行为,这太麻烦了。