我在做一项作业任务,要求我们在我们所开发的语言中(使用Scheme),实现一种称为“按名传递”的评估策略。
我们被提供了一个Scala示例,但我不理解“按名传递”是如何工作的,以及它与“按需传递”有何不同?
我在做一项作业任务,要求我们在我们所开发的语言中(使用Scheme),实现一种称为“按名传递”的评估策略。
我们被提供了一个Scala示例,但我不理解“按名传递”是如何工作的,以及它与“按需传递”有何不同?
按需调用是呼叫方式的记忆化版本(call-by-name),具体请参见维基百科。
在按名字调用中,参数每次使用时都会被评估(evaluate),而在按需调用中,参数第一次使用时被评估,并记录下其值,这样随后就不需要重新评估。
按名称调用是一种参数传递方案,其中参数在使用时进行评估,而不是在函数被调用时。以下是一个伪C语言的示例:
int i;
char array[3] = { 0, 1, 2 };
i = 0;
f(a[i]);
int f(int j)
{
int k = j; // k = 0
i = 2; // modify global i
k = j; // The argument expression (a[i]) is re-evaluated, giving 2.
}
当使用当前参数表达式的值访问时,该参数表达式是惰性地计算。
在上面的答案中添加以下内容:
阅读SICP流部分。它很好地解释了按名称调用和按需调用,并展示了如何在Scheme中实现它们。顺便说一句,如果你正在寻找一个快速的解决方案,这里有一个基本的按需调用在Scheme中实现:
;; Returns a promise to execute a computation. (implements call-by-name)
;; Caches the result (memoization) of the computation on its first evaluation
;; and returns that value on subsequent calls. (implements call-by-need)
(define-syntax delay
(syntax-rules ()
((_ (expr ...))
(let ((proc (lambda () (expr ...)))
(already-evaluated #f)
(result null))
(lambda ()
(if (not already-evaluated)
(begin
(display "computing ...") (newline)
(set! result (proc))
(set! already-evaluated #t)))
result)))))
;; Forces the evaluation of a delayed computation created by 'delay'.
(define (my-force proc) (proc))
一个样例运行:
> (define lazy (delay (+ 3 4)))
> (force lazy)
computing ... ;; Computes 3 + 4 and memoizes the result.
7
> (my-force lazy)
7 ;; Returns the memoized value.