Scheme 本地vs lambda的惯用用法?

Scheme 本地vs lambda的惯用用法?,scheme,racket,htdp,Scheme,Racket,Htdp,在中,我开始使用local,然后将其修改为使用lambda,以回答问题 (define (add-to-each2 accu a-list) (cond [(empty? a-list) empty] [else (local ((define s (+ accu (first a-list)))) (cons s (add-to-each2 s (rest a-list))))])) 及 在这个特殊的例子中,对我来说,local版本更容易阅读。是否

在中,我开始使用
local
,然后将其修改为使用
lambda
,以回答问题

(define (add-to-each2 accu a-list)
  (cond
    [(empty? a-list) empty]
    [else (local ((define s (+ accu (first a-list))))
            (cons s (add-to-each2 s (rest a-list))))]))


在这个特殊的例子中,对我来说,
local
版本更容易阅读。是否存在首选
lambda
版本的情况?谢谢。

首先,我认为您可能会将
相对-2绝对
添加到每个
混淆,因为
添加到每个
只是将相同的数字添加到列表的每个元素,而不是增加累加器。这篇文章的其余部分假设情况就是这样,只是去掉了增量

我想这将是我在本地绑定的第一选择。您的
lambda
示例使用一个通用模式,该模式使用
lambda
和应用程序模拟
let

(let ([x e]) body)
相当于:

((lambda (x) body) e)
如果在您的示例中使用从
lambda
let
的转换,您将得到:

(define (add-to-each5 n a-list)
  (cond
    [(empty? a-list) empty]
    [else (cons (let ([x n] [y a-list])
                  (first (map + (list (first y))
                              (list x))))
                (add-to-each5 n (rest a-list)))]))
一个好的编译器很可能会为这两个示例生成相同的代码,因此主要归结为风格。正如您所注意到的,“left-left
lambda
”模式可能更难阅读,因此我更喜欢
let

但是,练习30.1.1试图让您使用
map
替换每个示例中出现的显式递归。您在示例中使用的是
map
,但一次只用于一个添加,这使得
map
有点痛苦:当您只想
(+(第一个y)x)
时,为什么还要费事将
(第一个y))和
(列表x)
打包

让我们看一下
map
的一个简单定义,看看它对这个问题的帮助,而不是痛苦:

(define (map f ls)
  (cond
    [(empty? ls) empty]
    [else (cons (f (first ls)) (map f (rest ls)))]))
马上,您应该注意到
add to each
的一些相似之处:
cond
的第一行检查是否为空,第二行
cons
rest
上递归调用
map
first
元素有关。然后,关键是传递
map
一个
f
,它对每个元素执行您想要执行的操作

在向每个元素添加
的情况下,您需要向每个元素添加特定的数字。下面是添加
2
的示例:

> (map (lambda (n) (+ 2 n)) (list 1 2 3 4 5))
(3 4 5 6 7)
请注意,
map
lambda
在这里都是30.1.1请求,它们作用于一个完整的列表,而不需要将原始的
添加到每个
:递归都在
map
中抽象出来


这应该足以让你找到解决方案;不过,我不想透露最后的答案:)

谢谢你,亚当,这很有见地。我还没有谈到引入
let
的部分,但我知道这是怎么回事。祝福你,不客气。如果我把材料弄坏了,我向你道歉<如果你有
local
,那么code>let
应该很容易理解,但是在处理递归函数时有一些细微的差别;如果你遇到麻烦,再发一个问题。
> (map (lambda (n) (+ 2 n)) (list 1 2 3 4 5))
(3 4 5 6 7)