Scheme 中 lambda 表达式的求值顺序

Order of the evaluation of lambda expressions in Scheme

博士。球拍用户。

这里有两个表达式:

((lambda(x)(+ x 1))3)

((lambda(x)(+ x 1)2)3)

第一个是 lambda 表达式,接受一个输入并将其增加 1。因此它以 3 作为其操作数并使 (lambda(3)(+ 3 1) 等于 4。

第二个对我来说非常模糊,因为它的计算结果为 2,而且我无法理解其计算顺序。我知道它必须用改变顺序的括号做一些事情,但我不明白怎么做。显然它甚至没有将 "the 1" 和 "the x" 相加只是出于某种原因产生 2 作为输出。我想念对评估的一些基本理解。提前致谢!

如球拍中所述docs

A function definition can include multiple expressions for the function’s body. In that case, only the value of the last expression is returned when the function is called. The other expressions are evaluated only for some side-effect, such as printing.

例如:

(define (f x)
  (+ 1 1)              ;; evaluates to 2, but not returned    
  (= 3 4)              ;; evaluates to false, but not returned
  0                    ;; evaluates to 0, but not returned
  1000                 ;; evaluates to 1000, but not returned
  pi                   ;; evaluates to pi, but not returned
  "I am a string")     ;; last expression; evaluates and returns "I am a string"

(f 10)
=> "I am a string"
(f 'okay)
=> "I am a string"
(f pi)
=> "I am a string"

同样的事情发生在你的最后一个 lambda 中,由此:

((lambda (x) (+ x 1) 2) 3)
=> ((lambda () (+ 3 1) 2))
=> ((lambda () 4 2))   ;; last expression is 2, so output 2
=> 2

来自 lambda 的所有派生形式的主体按 begin 中的顺序从左到右求值。除了最后一个表达式之外的所有表达式仅针对副作用进行评估,而最后一个表达式的结果将是您的函数的结果:

((lambda (x)
   (+ x 1) ; not in tail position. no effect so it's dead code
   2)      ; the evaluation of 2 will be the result every time
 3) ; argument, only used by dead code.

它实际上确实产生了总和,然后将其丢弃以计算最后一个表达式。死代码的唯一用处就是在冬天保暖。在正文中更明智地使用更多表达式的示例:

(define (hypopotemus a b)
  (define (square x)                ; Not in tail position, creates 
    (* x x))                        ; a function as side effect.
  (sqrt (+ (square a) (square b)))) ; Tail expression calculates the result

并且因为这里提到了评估顺序。虽然函数的参数在所有 Scheme 报告中 #lang racket 严格从左到右计算,如 #!r6rs,但实现(如 racket)可以选择任何顺序。例如

((lambda (a b c) (display "d")) 
 (display "a")
 (display "b")
 (display "c")

虽然上面的代码总是在 #lang racket 中打印 "abcd" 它只是其中之一 Scheme 中有 6 种可能的结果,因为您不知道首先、中间和最后评估参数的顺序,并且打印将按评估顺序进行。我知道球拍当然会从左到右评估他们的 Scheme 代码,而 Ikarus 会以相反的顺序进行计算。