7

在 SICP 1.2.1 中有一个生成有理数的函数,如下所示:

(define (make-rat n d)
  (let ((g (gcd n d)))
    (cons (/ n g) (/ d g))))

我只是好奇如何使用 lambda 而不是 let 来实现相同的功能,而无需两次调用 GCD。我自己想不通。

4

4 回答 4

14

查看SICP 第 1.3.2 节

(let ((<var1> <exp1>)
      (<var2> <exp2>)
      ...
      (<varn> <expn>))
   <body>)

相当于

((lambda (<var1> ...<varn>)
    <body>)
 <exp1>
 ...
 <expn>)

所以你的程序,

(define (make-rat n d)
  (let ((g (gcd n d)))
    (cons (/ n g) (/ d g))))

应该相当于

(define (make-rat n d)
  ((lambda (g)
    (cons (/ n g) (/ d g)))
  (gcd n d)))
于 2010-05-25T16:55:10.100 回答
11

这两件事是一样的:

((lambda (p1 p2...) body) v1 v2...)

(let ((p1 v1) (p2 v2)...) body)
于 2010-05-25T16:45:12.963 回答
1
(define-syntax let-as-lambda
  (syntax-rules ()
        ((_ (x value) body)
            (let ((x value))
              body))))

(printf "~s~n" (let-as-lambda (x 1) (+ x 1)))
于 2011-02-22T15:49:46.537 回答
1

让我们检查两个简单的案例,以便我们了解如何重写任何使用 let 和 lambda 的函数:

  1. 在我们的第一个例子中,我们有一个 let。这个函数非常简单,它通过添加 10 来返回给定的输入:

    (define (test x)
      (let ((b 10))
        (+ x b)))
    

现在让我们使用 lambda 将其转换为表达式:

    (define (test-lambda x)
      ((lambda (b)
         (+ x b))
       10))

如您所见,test-lambda 返回一个 lambda 评估,其评估值为 10。测试这个我们可以说:

    (test-lambda 10)

这将返回 20。

  1. 现在不止一个 let,我们将 lambda 表达式嵌套在 lambda 表达式中。

我们的 let 案例有两个 let 语句:

    (define (lets x)
      (let ((a 10)
            (b 20))
        (+ x a b)))

我们可以像这样用 lambda 写这个:

    (define (lets-lambda x)
      ((lambda (a)
         ((lambda (b)
            (+ x a b))
          20))
       10))

所以现在我们正在评估每个 lambda 表达式,给它们一个值,最里面的 lambda 表达式使用每个 lambda 表达式已分配的变量名来处理我们想要计算的内容。

希望这很清楚,可以帮助其他人看得更清楚!

于 2013-06-03T19:24:56.267 回答