球拍中lambda函数的求值次序
目前正在通过《球拍指南》了解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!!”。以下是我对评估过程的
(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!!"