scala 什么是“点名”?

wfsdck30  于 5个月前  发布在  Scala
关注(0)|答案(4)|浏览(47)

我正在做一个家庭作业,我们被要求用我们开发的某种语言(使用Scheme)实现一种名为“按名称呼叫”的评估策略。
我们得到了一个example in Scala,但我不明白“按名称呼叫”是如何工作的,以及它与“按需要呼叫”有何不同?

ffx8fchx

ffx8fchx1#

按需调用是按名称调用的备忘录版本(参见wikipedia)。
在call-by-name中,参数在每次使用时都被求值,而在call-by-need中,参数在第一次使用时被求值,并记录值,以便随后不需要重新求值。

g0czyy6m

g0czyy6m2#

按名称调用是一种参数传递方案,其中参数在使用时计算,而不是在调用函数时计算。下面是伪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.
}

字符串
使用参数表达式的当前值访问参数表达式时,将延迟计算参数表达式。

6yoyoihd

6yoyoihd3#

将此添加到上述答案中:
通过流上的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.

djp7away

djp7away4#

  • 按名称调用 * 策略在使用函数的参数之前不会对其求值。

Scala中的 call-by-name 步骤示例:

def square(a: Int) = a * a

// (b: => Int, c: => Int means that Scala will evaluate b and c with call-by-name startegy
def sumSquare(b: => Int, c: => Int ): Int = square(b) + square(c)

sumSquare(2, 3+3)
square(2) + square(3+3)
2 * 2 + square(3+3)
4 + square(3+3)
4 + (3+3) * (3+3) // duplicate evaluation
4 + 9 * (3+3)
4 + 9 * 9
85

字符串

  • 按名称调用 * 可能会产生重复的计算。此外,这种策略的副作用是不可预测的。这就是为什么Scala默认策略是 * 按值调用 *。

你可以在这里阅读 call-by-name 策略和 call-by-value 策略之间的区别:
https://www.scaler.com/topics/call-by-name/

  • 按需调用 * 策略,也称为惰性求值策略,在表达式第一次调用时求值,并使用字典来保存特定表达式的求值结果。

更多关于延迟评估(call-by-need)的信息,请点击这里:
https://medium.com/background-thread/what-is-lazy-evaluation-programming-word-of-the-day-8a6f4410053f

相关问题