为什么Scheme需要应用于Y-combinator实现,但是Racket没有?

时间:2014-09-30 09:32:01

标签: scheme lisp racket apply y-combinator

以下是the Y-combinator in Racket

#lang lazy

(define Y (λ(f)((λ(x)(f (x x)))(λ(x)(f (x x))))))

(define Fact
  (Y (λ(fact) (λ(n) (if (zero? n) 1 (* n (fact (- n 1))))))))
(define Fib
  (Y (λ(fib) (λ(n) (if (<= n 1) n (+ (fib (- n 1)) (fib (- n 2))))))))

以下是the Y-combinator in Scheme

(define Y
  (lambda (f)
    ((lambda (x) (x x))
     (lambda (g)
       (f (lambda args (apply (g g) args)))))))

(define fac
  (Y
    (lambda (f)
      (lambda (x)
        (if (< x 2)
            1
            (* x (f (- x 1))))))))

(define fib
  (Y
    (lambda (f)
      (lambda (x)
        (if (< x 2)
            x
            (+ (f (- x 1)) (f (- x 2))))))))

(display (fac 6))
(newline)

(display (fib 6))
(newline)

我的问题是:为什么Scheme需要apply功能但Racket没有?

2 个答案:

答案 0 :(得分:11)

对于大多数用途,球拍非常接近普通方案,对于这个例子,它们是相同的。但是这两个版本之间的真正区别在于需要一个延迟的包装器,它需要严格的语言(Scheme和Racket),而不是懒惰的(Lazy Racket,一种不同的语言)。

那个包装器放在(x x)(g g)周围 - 我们对这个东西的了解是评估它会让你进入一个无限循环,我们也知道它会是结果(递归)函数。因为它是一个函数,我们可以使用lambda延迟其评估:而不是(x x)使用(lambda (a) ((x x) a))。这工作正常,但它有另一个假设 - 包装函数只需一个参数。我们也可以用两个参数的函数来包装它:(lambda (a b) ((x x) a b))但是在其他情况下也不行。解决方案是使用rest参数(args)并使用apply,因此使包装器接受任意数量的参数并将它们传递给递归函数。严格地说,它并不总是必需的,如果你想要能够产生任何arity的递归函数,它是“唯一的”。

另一方面,你有Lazy Racket代码,正如我上面所说,它是一种不同的语言 - 一种是需要语义调用的语言。由于这种语言是惰性的,因此不需要包装无限循环的(x x)表达式,它是按原样使用的。由于不需要包装器,因此不需要处理参数的数量,因此不需要apply。实际上,懒惰版本甚至不需要假设您正在生成函数值 - 它可以生成任何值。例如,这个:

(Y (lambda (ones) (cons 1 ones)))

工作正常并返回1 s的无限列表。要查看此内容,请尝试

(!! (take 20 (Y (lambda (ones) (cons 1 ones)))))

(注意,需要!!来递归“强制”结果值,因为Lazy Racket默认情况下不会递归计算。另外,请注意使用take - 没有它, Racket将尝试创建无限列表,这将无处可去。)

答案 1 :(得分:0)

Scheme不需要apply功能。你使用apply来接受多个参数。

在阶乘案例中,这是我的实现,不需要apply

;;2013/11/29

(define (Fact-maker f)
  (lambda (n)
    (cond ((= n 0) 1)
          (else (* n (f (- n 1)))))))

(define (fib-maker f)
  (lambda (n)
    (cond ((or (= n 0) (= n 1)) 1)
          (else
            (+ (f (- n 1))
               (f (- n 2)))))))
(define (Y F)
  ((lambda (procedure)
     (F (lambda (x) ((procedure procedure) x))))
   (lambda (procedure)
     (F (lambda (x) ((procedure procedure) x))))))