6

我不完全了解 append-map 命令在球拍中的作用,也不了解如何使用它,而且我很难在网上找到一些可以理解的文档。有人可以演示该命令的确切作用以及它是如何工作的吗?

4

2 回答 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 回答