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-leftlambda
”模式可能更难阅读,因此我更喜欢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)