在 SICP 1.2.1 中有一个生成有理数的函数,如下所示:
(define (make-rat n d)
(let ((g (gcd n d)))
(cons (/ n g) (/ d g))))
我只是好奇如何使用 lambda 而不是 let 来实现相同的功能,而无需两次调用 GCD。我自己想不通。
(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)))
这两件事是一样的:
((lambda (p1 p2...) body) v1 v2...)
和
(let ((p1 v1) (p2 v2)...) body)
(define-syntax let-as-lambda
(syntax-rules ()
((_ (x value) body)
(let ((x value))
body))))
(printf "~s~n" (let-as-lambda (x 1) (+ x 1)))
让我们检查两个简单的案例,以便我们了解如何重写任何使用 let 和 lambda 的函数:
在我们的第一个例子中,我们有一个 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。
我们的 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 表达式已分配的变量名来处理我们想要计算的内容。
希望这很清楚,可以帮助其他人看得更清楚!