javascript - Javascript "delay evaluation"想要避免急切评估时如何运行?

标签 javascript recursion functional-programming control-flow

这个例子是从Javascript Allonge这本书上摘下来的。该主题涉及控制流运算符和函数参数的评估。

const or = (a, b) => a || b

const and = (a, b) => a && b

const even = (n) =>
  or(n === 0, and(n !== 1, even(n - 2)))

even(42)
  //=> Maximum call stack size exceeded.

书中指出,这将导致无限递归。我相信我理解这部分。因为所有的参数都会被求值,即使or()中的a参数为真,b参数仍然会被求值(当or() 函数在even() 下被调用,即)。 and() 也是如此。 even(n - 2) 参数最终将被反复计算,n 为 2、0、-2、-4...

作为一种解决方案,它说可以将匿名函数作为参数传递。

const or = (a, b) => a() || b()

const and = (a, b) => a() && b()

const even = (n) =>
  or(() => n === 0, () => and(() => n !== 1, () => even(n - 2)))

even(7)
  //=> false

现在我明白了如何重写代码以使用包含原始表达式的匿名函数,但我不明白这种“延迟计算”是如何造成的。因为匿名函数仍然是 or()even() 函数的参数,是什么阻止它们评估并达到与之前代码相同的结果?

最佳答案

Because the anonymous functions are still parameters to the or() and even() functions, what's to prevent them from evaluating and reaching the same outcome as the previous code?

or()/and() 调用的参数确实被评估了。但它意味着函数表达式被评估(到一个函数)然后传递给or/and,而不是真正调用函数。它仅在函数内部从 a()/b() 调用,并且仅在实际需要时调用(由于运算符的短路) - 那是实际进行递归调用的地方。

顺便说一句,这个概念也被称为 thunk .

关于javascript - Javascript "delay evaluation"想要避免急切评估时如何运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32188435/

相关文章:

haskell - 签名为 : `(a -> a -> b) -> (a -> b)` 的函数名称

java - 使用 Java 登录函数式编程

php - Codeigniter 通过单击按钮更改表单操作

recursion - 递归记忆化比递归慢

javascript - 在 Wordpress 帖子中使用 jQuery

java - 循环遍历SoapMessage主体中的所有元素并返回我想要的节点

list - 将整数附加到 Ocaml 中的列表

java - 为什么 ADT 好而继承不好?

javascript - React - 使用外部 URL 时未定义 Map 函数

javascript - .innerHTML 丢失 HTML 语法格式