在MIT Scheme/Racket中,值可以既是运算符又是操作数吗?i、 e.(兰姆达(y)(y))
对于函数foo6,给出计算结果为3的过程的当前应用程序在MIT Scheme/Racket中,值可以既是运算符又是操作数吗?i、 e.(兰姆达(y)(y)),scheme,racket,currying,sicp,Scheme,Racket,Currying,Sicp,对于函数foo6,给出计算结果为3的过程的当前应用程序 (define foo6 (lambda (x) (x (lambda (y) (y y))))) 我定义了一个foo7来查看最后一行是如何工作的 (define foo7 (lambda (y) (y y))) 是否存在既可以是运算符又可以是操作数的“y” 编辑:问题应改为: 是否有一些“y”既可以是运算符也可以是操作数,不会导致错误或无限循环 问题取自计算机程序(SICP)样本编程作业的结构和解释: 来自“介绍性作业”
(define foo6
(lambda (x)
(x (lambda (y) (y y)))))
我定义了一个foo7来查看最后一行是如何工作的
(define foo7 (lambda (y) (y y)))
是否存在既可以是运算符又可以是操作数的“y”
编辑:问题应改为:
是否有一些“y”既可以是运算符也可以是操作数,不会导致错误或无限循环
问题取自计算机程序(SICP)样本编程作业的结构和解释:
来自“介绍性作业”,练习11:
- PDF版本:
- PS(原版):
是的。Scheme和Racket都是Lisp1,这意味着它们只有一个名称空间,因此。变量
v
可以是包括过程在内的任何值
第二次看到类似于(lambda(y)(y))
的内容,从应用的方式来看,很明显y
是一个什么类型的过程。对于过程以外的任何其他值,它将以应用程序错误结束:
((lambda (y) (y y)) 5)
; ERROR: application: 5 is not a procedure
这个过程本身可能会期望它本身是一个参数,所以我们可以假设某种ω或z组合式
我们有更高阶的过程,您可以将函数作为值传递到操作数位置,然后将它们放在运算符位置使用:
(define (times n p)
(lambda (arg)
(let loop ((n n) (acc arg))
(if (<= n 0)
acc
(loop (sub1 n) (p acc))))))
(define double (lambda (v) (+ v v)))
(define test (times 3 double))
(test 5) ; ==> 40
Z组合子是语言的Y组合子。它可以在不改变环境的情况下进行自我参考。是的
(define (foobar n)
((foo6
(lambda (u) (u (lambda (y)
(lambda (n)
(if (zero? n)
1
(* n ((y y) (- n 1)))))))))
n))
是吗?我是说,为什么?因为
因此,foo6
的参数应该是一个函数x
期望u
,这样uy=yy
。所以我们给它这样的函数
(foobar n)
=
((foo6 x) n)
=
((x u) n)
=
((u y) n) so, x = (lambda (u) (u (lambda (y) (lambda (n) ...))))
=
((y y) n) so, y = (lambda (y) (lambda (n) ...))
=
((lambda (n)
(if (zero? n)
1
(* n ((y y) (- n 1)))))
n)
随后,当需要计算/if((y)(-n1))
时,作为(y)
应用程序的结果,再次到达相同的(lambda(n)…
函数,并且在需要计算/if((y)(-n1)1))
时再次使用该函数
试试看!(foobar 5)
评估的目的是什么?(乌鲁巴诺)
所以,一切都合适。你看见我了吗
(lambda(y)(y))
实际上有一个名称:它是“Ucombinator”。foo7是否可以应用一些不会导致错误的y值?i、 e.“(foo7)”请注意,问题要求的是(当前)应用foo6,而不是定义。谢谢回复@Sylvester@注意模糊是的。您可以执行(foo7 foo7)
。它将产生一个无限循环,但没有错误。这是我尝试的第一件事,但对foo6的应用没有帮助。我将编辑问题以反映这一点。再次感谢@Sylvester@注意模糊你确实看到了我的编辑,你的代码是Z组合器的一部分,可以完美地计算斐波那契?@sylvester现在读一下编辑,它很吸引人!我从未遇到过Z组合器。尽管如此,还不清楚如何使用Z组合符来导出一个当前应用的foo6,以计算为3。也许我最初的问题(在标题中)在弄清楚如何最终使foo6评估为3时可能没有用处?
(foo6 x)
=
(x (lambda (y) (y y))
=
(x u) where u = (lambda (y) (y y))
i.e. (u y) = (y y)
(foobar n)
=
((foo6 x) n)
=
((x u) n)
=
((u y) n) so, x = (lambda (u) (u (lambda (y) (lambda (n) ...))))
=
((y y) n) so, y = (lambda (y) (lambda (n) ...))
=
((lambda (n)
(if (zero? n)
1
(* n ((y y) (- n 1)))))
n)