我不完全了解 append-map 命令在球拍中的作用,也不了解如何使用它,而且我很难在网上找到一些可以理解的文档。有人可以演示该命令的确切作用以及它是如何工作的吗?
问问题
7796 次
2 回答
11
该过程对于在将过程应用于每个子列表后append-map
从子列表列表中创建单个列表很有用。换句话说,这段代码:
(append-map proc lst)
...在语义上等同于:
(apply append (map proc lst))
... 或这个:
(append* (map proc lst))
Applying-append-to-a-list-of-sublists 习惯用法有时被称为展平子列表列表。让我们看一些例子,这个就在文档中:
(append-map vector->list '(#(1) #(2 3) #(4)))
'(1 2 3 4)
对于更有趣的示例,请查看 Rosetta Code 中的此代码,以查找列表的所有排列:
(define (insert l n e)
(if (= 0 n)
(cons e l)
(cons (car l)
(insert (cdr l) (- n 1) e))))
(define (seq start end)
(if (= start end)
(list end)
(cons start (seq (+ start 1) end))))
(define (permute l)
(if (null? l)
'(())
(apply append (map (lambda (p)
(map (lambda (n)
(insert p n (car l)))
(seq 0 (length p))))
(permute (cdr l))))))
最后一个过程可以用 更简洁地表示append-map
:
(define (permute l)
(if (null? l)
'(())
(append-map (lambda (p)
(map (lambda (n)
(insert p n (car l)))
(seq 0 (length p))))
(permute (cdr l)))))
无论哪种方式,结果都符合预期:
(permute '(1 2 3))
=> '((1 2 3) (2 1 3) (2 3 1) (1 3 2) (3 1 2) (3 2 1))
于 2013-01-31T02:10:45.493 回答
4
在 Common Lisp 中,该函数被命名为“mapcan”,它有时用于将过滤与映射结合起来:
* (mapcan (lambda (n) (if (oddp n) (list (* n n)) '()))
'(0 1 2 3 4 5 6 7))
(1 9 25 49)
在球拍中,这将是:
> (append-map (lambda (n) (if (odd? n) (list (* n n)) '()))
(range 8))
'(1 9 25 49)
但最好这样做:
> (filter-map (lambda (n) (and (odd? n) (* n n))) (range 8))
'(1 9 25 49)
于 2013-01-31T06:36:04.693 回答