是否有人知道如何在Scheme中实现Y-组合器,特别是使用惰性评估和附加参数?我的理解是这个计划(保证?)(延迟)和(强制)提供懒惰的评估支持。
根据我的理解,Y与应用程序如下所示,但是由于默认的应用顺序评估,将无法在Scheme中工作。
((lambda (f)
((lambda (x) (f (x x)))
(lambda (x) (f (x x)))))
(lambda (r) (r)))这是一个建议的解决方案(),但是它使用另一个带有参数的lambda函数作为解决方案:
;; Z-combinator
(define Z
(lambda (f)
((lambda (g) (f (g g)))
(lambda (g) (f (lambda args (apply (g g)
args)))))))
;Value: z
((Z (lambda (r)
(lambda (x)
(if (< x 2)
1
(* x (r (- x 1))))))) 5)
;Value: 120
;; end Z-combinator基于解决方案的更新
Y-组合器如下:
;; Y-combinator
(define Y
(lambda (f)
((lambda (x) (f (delay (x x))))
(lambda (x) (f (delay (x x)))))))
;Value: y
;; end Y-combinator
;; Non tail recursive
((Y (lambda (r)
(lambda (x)
(if (< x 2)
1
(* x ((force r) (- x 1)))))))
5)
;Value: 120
;; Tail - recursive
((Y (lambda (r)
(lambda (x acc)
(if (< x 2)
acc
((force r) (- x 1) (* x acc))))))
5 1)
;Value: 120感谢你的指导!
发布于 2019-05-04 09:33:54
是的,通过严格的评估,自应用程序( x )会导致无限循环发生。如果您延迟这一点,您可以使用y-组合器,只要您在它的使用站点“强制”该延迟对象:
(define (test)
(((lambda (f)
((lambda (x) (f (delay (x x))))
(lambda (x) (f (delay (x x))))))
(lambda (r)
(lambda (x)
(if (< x 2)
1
(* x ((force r) (- x 1)))))))
5))使y-组合器在严格设置下工作的正常方法是eta-扩展自应用程序,这是延迟它的另一种方法,但不需要显式地施加力。相反,强制是由函数应用程序完成的。
发布于 2019-05-04 22:35:59
普通的Y级组合器,在这里计算拉兹球拍的(ack 3 6):
#lang lazy
(define Y
(lambda (f)
((lambda (g) (g g))
(lambda (g) (f (g g))))))
((Y (lambda (ackermann)
(lambda (m n)
(cond
((= m 0) (+ n 1))
((= n 0) (ackermann (- m 1) 1))
(else (ackermann (- m 1) (ackermann m (- n 1))))))))
3
6) ; ==> 509计划不是一种懒惰的语言,像懒散的球拍,所以Y需要有一点不同。它现在被称为Z组合器:
#!r6rs
(import (rnrs base))
(define Z
(lambda (f)
((lambda (g)
(f (g g)))
(lambda (g)
(f (lambda args (apply (g g) args)))))))
((Z (lambda (ackermann)
(lambda (m n)
(cond
((= m 0) (+ n 1))
((= n 0) (ackermann (- m 1) 1))
(else (ackermann (- m 1) (ackermann m (- n 1))))))))
3
6) ; ==> 509使用delay和force并不能使它变得更好:
#!r6rs
(import (rnrs base)
(rnrs r5rs))
(define DY
(lambda (f)
((lambda (g) (g g))
(lambda (g) (f (delay (g g)))))))
((DY (lambda (d-ackermann)
(lambda (m n)
(cond
((= m 0) (+ n 1))
((= n 0) ((force d-ackermann) (- m 1) 1))
(else ((force d-ackermann) (- m 1) ((force d-ackermann) m (- n 1))))))))
3
6) ; ==> 509通常,Y和Z允许我们命名递归过程,但在最后一个过程中,我们得到了需要解决的承诺,从而泄漏了实现细节,使用起来变得更加困难。通常,当涉及到承诺时,我们希望避免不必要的执行,但是调用应该返回承诺。
https://stackoverflow.com/questions/55979015
复制相似问题