球拍中lambda函数的求值次序

球拍中lambda函数的求值次序,lambda,racket,expression-evaluation,Lambda,Racket,Expression Evaluation,目前正在通过《球拍指南》了解lambda功能。对它们的有用性的解释是清楚的,但我不确定我是否完全掌握了评估这些函数的顺序。从指南中考虑下面的例子: (define (twice f v) (f (f v))) (define (make-add-suffix s2) (lambda (s) (string-append s s2))) (twice (make-add-suffix "!") "hello") 这里对的函数调用两次的计算结果是“hello!!”。以下是我对评估过程的

目前正在通过《球拍指南》了解lambda功能。对它们的有用性的解释是清楚的,但我不确定我是否完全掌握了评估这些函数的顺序。从指南中考虑下面的例子:

(define (twice f v)
  (f (f v)))

(define (make-add-suffix s2)
  (lambda (s) (string-append s s2)))

(twice (make-add-suffix "!") "hello")
这里对
的函数调用两次
的计算结果是
“hello!!”
。以下是我对评估过程的猜测:

(twice (make-add-suffix "!") "hello")

((make-add-suffix "!") ((make-add-suffix "!") "hello")

((make-add-suffix "!") (string-append "hello" "!"))

(string-append (string-append "hello" "!") "!")

(string-append "hello!" "!")

"hello!!"

这是一个准确的评估,还是我遗漏了什么?

口号:应该首先计算最外层和最左侧的嵌套表达式

(twice (make-add-suffix "!") "hello")

; (define (f x) ...) is short for (define f (lambda (x) ...)) so,
; = { substitute twice with  (lambda (f v) (f (f v)))}

((lambda (f v) (f (f v))) (make-add-suffix "!") "hello")

; = { substition of make-add-suffix with (lambda (s2) (lambda (s) (string-append s s2)))}

((lambda (f v) (f (f v)))
 ((lambda (s2) (lambda (s) (string-append s s2))) "!")
 "hello")
继续之前的术语:

  • 测试版缩减:
    ((lambda(x-1…x-n)f-body)v-1…v-n)=f-body
    所有出现的
    x-1。。。x-n
    替换为
    v-1。。。分别为v-n

  • 按值调用:函数调用的参数在beta缩减之前进行评估


获得相同答案的另一种方法是:DrRacket包含一个“步进”工具,正是为了这个目的。如果您将语言级别设置为“中级学生和Lambda”,并单击“步骤”按钮,您应该能够看到程序的评估是一系列步骤,如thrvshl所述


编辑:您描述的评估策略,其中
两次
的第一个参数替换
两次
定义中的
x
的每个实例,称为“按名称调用”评估,并与la Haskell的懒惰相关联。若要查看差异,请考虑一个版本<代码>添加附加后缀,其中包含“<代码> Prtff <代码> >内部代码> lambda < /COD>

使Add后缀只被调用一次。结果值是一个函数,调用两次。大多数编程语言(但也有例外)不会像您的扩展那样进行多次纹理重写和调用。
; = { beta-reduction of ((lambda (s2) (lambda (s) (string-append s s2))) "!") }

((lambda (f v) (f (f v))) (lambda (s) (string-append s "!")) "hello")

; = { beta-reduction of the whole expression }

((lambda (s) (string-append s "!"))
 ((lambda (s) (string-append s "!")) "hello"))

; = { beta-reduction of the expression in the argument position first }

((lambda (s) (string-append s "!")) (string-append "hello" "!"))

; ... and the rest is easy:
((lambda (s) (string-append s "!")) "hello!")
(string-append "hello!" "!")
"hello!!"