我不明白Call-by-name和Call-by-need之间的区别。据我所知,Call-by-need方法会恢复返回的结果。但是它是如何帮助我们的,结果之间有什么根本的区别吗?
例如,
begin integer n;
procedure foo(e, n);
integer e, n;
begin
for n := 1 step 1 until 10 do begin
prints(`;;; the value of e is ');
printnln(e)
end
end;
foo(2 * n, n)
end因此,根据我的理解,在call-by-name中,我们将得到:
;;; the value of e is 2
;;; the value of e is 4
;;; the value of e is 8诸若此类。这是因为我们将2*n传递给e,并且每次都使用新的i对e求值。在call-by-need中会发生什么?
发布于 2012-01-06 05:16:59
在call by need中,我们进入循环,并且只计算一次值。因此,在上面的代码中,我们将在循环内复制(2*n) (宏样式),并且我们将只计算表达式一次(不像按名称调用)。因此,在第一次迭代中,我们将得到e=2。这也将是下一次迭代中e的值,输出将是:
;;; the value of e is 2
;;; the value of e is 2
;;; the value of e is 2发布于 2012-01-12 19:14:51
您的困惑似乎源于您在imperative上下文中思考的事实。关于按需调用与按值调用的讨论主要涉及声明性和函数式语言,以及lambda演算。
您可以在这篇关于evaluation strategies的文章中看到,按名称调用和按需要调用都被认为是懒惰的评估策略。惰性求值意味着当表达式作为参数传递给函数时,在进入函数体之前不会对其求值,而只是在函数内部第一次访问/读取时才进行求值。如果这样的表达式的结果从未在内部使用过,那么它将永远不会被计算。
例如,? :操作符在Java语言中是惰性的,如下面的代码所示:
String test(Object obj)
{
return 1 == 2 ? obj.toString() : "Hello World";
}
test(null); // this won't throw a NullPointerException按需调用是大多数具有纯子集的函数式语言的基本特性。在purely functional language中,每个函数都必须是referentially transparent,即它们不能有side-effects。这样的pure functions具有这样的特性:对于某些给定的输入,它们总是返回相同的输出,无论调用多少次,并且它们永远不会改变“世界状态”中的任何东西。它们的行为就像纸上写的数学函数。
正如您已经意识到的那样,在调用非纯函数时,按需调用策略是不可行的,因为您很可能对连续调用带来的副作用感兴趣。另一方面,当在纯函数式语言中使用时,它成为性能的基本特性(参见下面的第二个示例)。另外,请参阅这些关于Graph Reduction和Memoization概念的维基页面。
真实世界的例子
使用图形归约的常用系统的一个例子是Apache Ant。Ant不会对一个目标进行两次评估。这种设计使得绘制一个声明性的构建计划变得很方便。
Second。如果你想看一个很好的记忆演示,在GHC解释器中输入这段Haskell代码,看看会发生什么:
Prelude> let fibs = 0:1:(zipWith (+) fibs (tail fibs))
-- This defines the Fibonacci sequence.
Prelude> fibs !! 200000
-- Prints the 200,000th Fibonacci number,
-- takes several seconds to calculate.
Prelude> fibs !! 200000
-- Prints the same number as before,
-- but this time it returns immediately.注意:您可能还听说过按值调用的评估策略。与按名称调用和按需调用相比,按值调用是一种严格的评估策略。它类似于按名称调用,因为多次调用会导致多次求值。对于习惯于C#或Java等命令式语言的程序员来说,这是最常见的范例。
发布于 2012-01-12 00:24:54
Call- by -name是一种调用规程的函数,当调用接收函数foo时,foo (而不是正在计算的foo的参数)将(在幕后)接收一个适当的对象,该对象将允许它计算它需要的参数;或者等效地,计算通过宏替换进行。如果一个参数被多次需要,它将被多次求值。请参阅:http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_name
按需调用大致相同,不同之处在于传递的对象是一个promise,并且只会被计算一次;在随后引用参数时,将使用已记忆的值。请参阅:http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_need
https://stackoverflow.com/questions/8701834
复制相似问题