如何在Racket中使用append-map(Scheme)

时间:2013-01-31 01:40:32

标签: scheme racket procedural-programming procedures

我不完全理解append-map命令在球拍中的作用,也不了解如何使用它,我很难在线找到一些体面可理解的文档。有人可能会证明命令究竟是什么以及它是如何工作的吗?

2 个答案:

答案 0 :(得分:10)

在将过程应用于每个子列表之后,append-map过程对于从子列表列表中创建单个列表非常有用。换句话说,这段代码:

(append-map proc lst)

......在语义上等同于:

(apply append (map proc lst))

......或者这个:

(append* (map proc lst))

应用附加到子列表的成语列表有时被称为展平一个子列表列表。让我们看一些例子,这个例子在文档中是正确的here

(append-map vector->list '(#(1) #(2 3) #(4)))
'(1 2 3 4)

有关更有趣的示例,请查看Rosetta Code中的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))

答案 1 :(得分: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)

在Racket中:

> (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)