How to use append-map in Racket (Scheme)

廉价感情. 提交于 2019-12-08 19:51:27

问题


I don't fully understand what the append-map command does in racket, nor do I understand how to use it and I'm having a pretty hard time finding some decently understandable documentation online for it. Could someone possibly demonstrate what exactly the command does and how it works?


回答1:


The append-map procedure is useful for creating a single list out of a list of sublists after applying a procedure to each sublist. In other words, this code:

(append-map proc lst)

... Is semantically equivalent to this:

(apply append (map proc lst))

... Or this:

(append* (map proc lst))

The applying-append-to-a-list-of-sublists idiom is sometimes known as flattening a list of sublists. Let's look at some examples, this one is right here in the documentation:

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

For a more interesting example, take a look at this code from Rosetta Code for finding all permutations of a list:

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

The last procedure can be expressed more concisely by using 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)))))

Either way, the result is as expected:

(permute '(1 2 3))
=> '((1 2 3) (2 1 3) (2 3 1) (1 3 2) (3 1 2) (3 2 1))



回答2:


In Common Lisp, the function is named "mapcan" and it is sometimes used to combine filtering with mapping:

* (mapcan (lambda (n) (if (oddp n) (list (* n n)) '()))
        '(0 1 2 3 4 5 6 7))
(1 9 25 49)

In Racket that would be:

> (append-map (lambda (n) (if (odd? n) (list (* n n)) '()))
            (range 8))
'(1 9 25 49)

But it's better to do it this way:

> (filter-map (lambda (n) (and (odd? n) (* n n))) (range 8))
'(1 9 25 49)


来源:https://stackoverflow.com/questions/14617095/how-to-use-append-map-in-racket-scheme

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!