【发布时间】:2020-12-19 22:46:56
【问题描述】:
在 SICP 练习 2.41 中,作者要求您设计一个程序,该程序列出三个小于某个数字的不同数字,然后“过滤”总和等于另一个任意数字的三元组。
这是我的程序:
(define (unique-pair-sum n s)
(define (unique-triplet a)
(flatmap (lambda (i)
(flatmap (lambda (j)
(map (lambda (k) (list i j k))
(enumerate-interval 1 (- j 1))))
(enumerate-interval 1 (- i 1))))
(enumerate-interval 1 a)))
(filter (lambda (x) (= (+ (car x) (cadr x) (caddr x)) s))
(unique-triplet n)))
这是本书中描述的flatmap 过程:
(define (flatmap proc seq) (accumulate append nil (map proc seq)))
和一个例子的结果:
(unique-pair-sum 6 9) ; ((4 3 2) (5 3 1) (6 2 1))
正如您所看到的,这段代码没有任何问题,但是当我将 (lambda (j)...) 之前的“flatmap”更改为简单的“map”时,会发生一些奇怪的事情:
(unique-triplet 6) ; (() () ((3 2 1)) () ((4 2 1)) ((4 3 1) (4 3 2)) () ((5 2 1)) ((5 3 1) (5 3 2)) ((5 4 1) (5 4 2) (5 4 3)) () ((6 2 1)) ((6 3 1) (6 3 2)) ((6 4 1) (6 4 2) (6 4 3)) ((6 5 1) (6 5 2) (6 5 3) (6 5 4)))
但原始代码可以正常工作:
(unique-triplet 6) ; ((3 2 1) (4 2 1) (4 3 1) (4 3 2) (5 2 1) (5 3 1) (5 3 2) (5 4 1) (5 4 2) (5 4 3) (6 2 1) (6 3 1) (6 3 2) (6 4 1) (6 4 2) (6 4 3) (6 5 1) (6 5 2) (6 5 3) (6 5 4))
我知道这不是一个真正的“问题”,因为我已经设法解决了它(通过一些外部帮助)。我只是好奇这种差异背后的原因。
【问题讨论】:
-
map只是在列表中的每个元素上映射一个函数,结果返回一个新列表。flatmap做同样的事情,但另外扁平化列表,即:如果结果是列表列表,它将所有子列表合并到一个列表中。 -
此外,如果您可以在每个使用站点简单地将
flatmap替换为map并获得相同的结果,那么没有人会费心去发明flatmap。
标签: scheme filtering sicp map-function flatmap