我不完全理解 append-map 命令在 racket 中的作用,也不知道如何使用它,我很难在网上找到一些体面可理解的文档。 有人可以演示该命令的确切功能及其工作原理吗?
append-map
过程对于在将过程应用于每个子列表后从子列表列表中创建单个列表非常有用。换句话说,此代码:
(append-map proc lst)
。在语义上等效于以下内容:
(apply append (map proc lst))
。或者这个:
(append* (map proc lst))
应用追加到子列表列表的习惯用法有时称为扁平化子列表列表。让我们看一些示例,这个示例就在文档中:
(append-map vector->list '(#(1) #(2 3) #(4)))
'(1 2 3 4)
对于一个更有趣的例子,看看罗塞塔代码中的这段代码,用于查找列表的所有排列:
(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))
在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)