在 MIT Scheme/Racket 中,一个值可以同时是运算符和操作数吗?即 (lambda (y) (y y))
In MIT Scheme/Racket, can a value be both the operator and operand? i.e. (lambda (y) (y y))
对于函数 foo6,给出计算结果为 3 的过程的 Curried 应用程序。
(define foo6
(lambda (x)
(x (lambda (y) (y y)))))
我已经定义了一个 foo7 来查看最后一行是如何工作的
(define foo7 (lambda (y) (y y)))
是否有一些"y"既可以是操作符又可以是操作数?
编辑:问题应为:
有没有一些"y"既可以是运算符又可以是操作数而不会导致错误或无限循环的?
问题取自计算机程序的结构和解释 (SICP) 示例编程作业:
https://mitpress.mit.edu/sicp/psets/index.html
来自 "Introductory assignment," 练习 11:
是的。 Scheme 和 Racket 都是 Lisp1,这意味着它们只有一个命名空间,因此。变量 v
可以是任何值,包括过程。
第二次您看到类似 (lambda (y) (y y))
的内容时,很明显 y
是一种类型的过程,因为它正在被应用。对于过程之外的任何其他值,它将以应用程序错误结束:
((lambda (y) (y y)) 5)
; ERROR: application: 5 is not a procedure
过程本身可能期望自己作为参数,因此我们可以假设某种 omega 或 z 组合子。
我们有高阶过程,您可以将函数作为操作数位置的值传递,并使用它们,只需将 then 放在运算符位置即可:
(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
并非只有 Scheme 拥有此功能。与上面相同的代码可以在 JavaScript 中同样容易地表达,因为它也只有一个命名空间,并且 parseInt(x)
将变量 parseInt
计算为一个值,该值将应用您从中获得的参数评估变量 x
。它们只是两个变量,没什么特别的。
编辑
这是一个示例,其中 (lambda (y) (y y))
用于一些有用的地方。
;; the Z combinator
(define Z
(lambda (f)
((lambda (y)
(y y))
(lambda (g)
(f (lambda args (apply (g g) args)))))))
(define (fib n)
((Z (lambda (helper)
(lambda (n a b)
(if (zero? n)
a
(helper (- n 1) b (+ a b))))))
n 0 1))
(fib 10) ; ==> 55
Z 组合子是 eager 语言的 Y 组合子。它可以在不改变环境的情况下进行自我引用。
是的,
(define (foobar n)
((foo6
(lambda (u) (u (lambda (y)
(lambda (n)
(if (zero? n)
1
(* n ((y y) (- n 1)))))))))
n))
是吗?我的意思是,为什么?因为
(foo6 x)
=
(x (lambda (y) (y y))
=
(x u) where u = (lambda (y) (y y))
i.e. (u y) = (y y)
所以 foo6
的参数应该是一个函数 x
期望 u
使得 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)
及以后,当/如果((y y) (- n 1))
需要计算时,相同的(lambda (n) ...)
函数作为(y y)
应用的结果再次到达,并在/时再次使用如果 ((y y) (- (- n 1) 1))
需要评估。
试试吧! (foobar 5)
评估的是什么? (ʎʇuǝʍʇpuɐpǝɹpunɥǝuo)
所以,一切都合适。你看到了吗?
(lambda (y) (y y))
其实有一个名字:它是“U组合子”。
对于函数 foo6,给出计算结果为 3 的过程的 Curried 应用程序。
(define foo6
(lambda (x)
(x (lambda (y) (y y)))))
我已经定义了一个 foo7 来查看最后一行是如何工作的
(define foo7 (lambda (y) (y y)))
是否有一些"y"既可以是操作符又可以是操作数?
编辑:问题应为:
有没有一些"y"既可以是运算符又可以是操作数而不会导致错误或无限循环的?
问题取自计算机程序的结构和解释 (SICP) 示例编程作业: https://mitpress.mit.edu/sicp/psets/index.html
来自 "Introductory assignment," 练习 11:
是的。 Scheme 和 Racket 都是 Lisp1,这意味着它们只有一个命名空间,因此。变量 v
可以是任何值,包括过程。
第二次您看到类似 (lambda (y) (y y))
的内容时,很明显 y
是一种类型的过程,因为它正在被应用。对于过程之外的任何其他值,它将以应用程序错误结束:
((lambda (y) (y y)) 5)
; ERROR: application: 5 is not a procedure
过程本身可能期望自己作为参数,因此我们可以假设某种 omega 或 z 组合子。
我们有高阶过程,您可以将函数作为操作数位置的值传递,并使用它们,只需将 then 放在运算符位置即可:
(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
并非只有 Scheme 拥有此功能。与上面相同的代码可以在 JavaScript 中同样容易地表达,因为它也只有一个命名空间,并且 parseInt(x)
将变量 parseInt
计算为一个值,该值将应用您从中获得的参数评估变量 x
。它们只是两个变量,没什么特别的。
编辑
这是一个示例,其中 (lambda (y) (y y))
用于一些有用的地方。
;; the Z combinator
(define Z
(lambda (f)
((lambda (y)
(y y))
(lambda (g)
(f (lambda args (apply (g g) args)))))))
(define (fib n)
((Z (lambda (helper)
(lambda (n a b)
(if (zero? n)
a
(helper (- n 1) b (+ a b))))))
n 0 1))
(fib 10) ; ==> 55
Z 组合子是 eager 语言的 Y 组合子。它可以在不改变环境的情况下进行自我引用。
是的,
(define (foobar n)
((foo6
(lambda (u) (u (lambda (y)
(lambda (n)
(if (zero? n)
1
(* n ((y y) (- n 1)))))))))
n))
是吗?我的意思是,为什么?因为
(foo6 x)
=
(x (lambda (y) (y y))
=
(x u) where u = (lambda (y) (y y))
i.e. (u y) = (y y)
所以 foo6
的参数应该是一个函数 x
期望 u
使得 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)
及以后,当/如果((y y) (- n 1))
需要计算时,相同的(lambda (n) ...)
函数作为(y y)
应用的结果再次到达,并在/时再次使用如果 ((y y) (- (- n 1) 1))
需要评估。
试试吧! (foobar 5)
评估的是什么? (ʎʇuǝʍʇpuɐpǝɹpunɥǝuo)
所以,一切都合适。你看到了吗?
(lambda (y) (y y))
其实有一个名字:它是“U组合子”。