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编译器重现这种行为,这太麻烦了。