首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Scheme中使用Y-组合器,使用惰性评估?

在Scheme中使用Y-组合器,使用惰性评估?
EN

Stack Overflow用户
提问于 2019-05-04 02:37:53
回答 2查看 331关注 0票数 3

是否有人知道如何在Scheme中实现Y-组合器,特别是使用惰性评估和附加参数?我的理解是这个计划(保证?)(延迟)和(强制)提供懒惰的评估支持。

根据我的理解,Y与应用程序如下所示,但是由于默认的应用顺序评估,将无法在Scheme中工作。

代码语言:javascript
复制
((lambda (f)
   ((lambda (x) (f (x x)))
    (lambda (x) (f (x x)))))
 (lambda (r) (r)))

这是一个建议的解决方案(),但是它使用另一个带有参数的lambda函数作为解决方案:

代码语言:javascript
复制
;; 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-组合器如下:

代码语言:javascript
复制
;; 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

感谢你的指导!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-05-04 09:33:54

是的,通过严格的评估,自应用程序( x )会导致无限循环发生。如果您延迟这一点,您可以使用y-组合器,只要您在它的使用站点“强制”该延迟对象:

代码语言:javascript
复制
(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-扩展自应用程序,这是延迟它的另一种方法,但不需要显式地施加力。相反,强制是由函数应用程序完成的。

票数 2
EN

Stack Overflow用户

发布于 2019-05-04 22:35:59

普通的Y级组合器,在这里计算拉兹球拍的(ack 3 6)

代码语言:javascript
复制
#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组合器:

代码语言:javascript
复制
#!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

使用delayforce并不能使它变得更好:

代码语言:javascript
复制
#!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

通常,YZ允许我们命名递归过程,但在最后一个过程中,我们得到了需要解决的承诺,从而泄漏了实现细节,使用起来变得更加困难。通常,当涉及到承诺时,我们希望避免不必要的执行,但是调用应该返回承诺。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55979015

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档