映射指的是把一個函式套用到序列中的每個元素,藉此產生一個新的序列。
mapcar可以用來把函式映射到一個裝著物件的陣列上
(mapcar #'double '(1 2 3 4)) ; => (2 4 6 8)
注意,第一個引數是要呼叫的函式。
#'是一種特殊的引用語法,用來指定函式。
(這裡也可以寫成'double,但使用#'是慣用寫法,而且可以說「更正確」。)
映射不限定只能把函式套用到單一序列,也可以用在多個序列上。
如果提供了N個序列,函式就必須接受N個引數。
(mapcar #'list '(1 2) '(a b) '("foo" "bar")) ; => ((1 a "foo") (2 b "bar"))
除了mapcar之外,還有其他可以對陣列做映射的函式。
mapcar無疑是最常用的,但認識其他函式也很有幫助。
maplist的運作方式類似mapcar,但它處理的是連續的子陣列,而不是個別元素。
首先處理整個陣列,接著處理它的cdr,再處理那個cdr的cdr,依此類推:
(maplist #'identity '(a b c)) ; => ((A B C) (B C) (C))
mapc和mapl分別類似mapcar和maplist,但它們不會收集結果,而是回傳第一個陣列。
這適合用在帶有副作用的操作上。
mapcan和mapcon類似mapcar和maplist,但結果會透過nconc攤平。nconc類似append,不過除了最後一個引數之外,它會破壞其他所有引數。
映射不只能用在陣列上。任何序列(另一個概念會介紹)都可以映射。
如果序列不是陣列,就要使用map函式。
map接受 3 個以上的引數:
(map 'list #'double '(1 2 3)) ; => (2 4 6)
(map 'string #'char-upcase "foobar") ; => "FOOBAR"
特殊情況是,如果結果序列的型別指定為nil,就會回傳nil。
這種用法(就像上面的mapc和mapl)是用來產生副作用的。