Lisp映射函数MAP,MAPC, MAPCAR, MAPCAN, MAPL, MAPLIST, MAPCON对比

介绍之前有必要先介绍一个Lisp的集合数据类型,这样才能更容易的理解这几个的函数的区别和联系。任何语言对集合的分类可以分为两种类型,一种是以一个整数为索引的类数组类型 和 一个可以用key来访问值的表类型。在不同的语言中,前者一般叫做数组(array),列表(list)和元组(tuples)。后者一般叫做哈希表(hash table),关联数组 (associative arrays),  Map(maps),字典(dictonaries).

Lisp是以list起家的语言,所以列表广为所知。其实lisp包含了 array,vector,和list已经hash table等多种数据类型。Lisp把 array ,vector 和list统称为sequence (序列)。也就是集合分类的第一种类型。 如果区分更细致的话,其实array应该属于vector的子类型,但是一般没有必要。另外string类型也是属于序列(sequence),因为string可以看做字符的array。sequence抽象类型之上的操作对string,array,vector和list都是通用的。sequence的各个分类也有其特殊的操作。Lisp的List应为太灵活了,因此好多数据结构都可以使用List实现,例如alist plist就是在list之上实现类似 hash table的功能,导致List是Lisp中使用最广的数据类型。 理所当然List的操作函数也是相当的丰富。MAPC, MAPCAR, MAPCAN, MAPL, MAPLIST, MAPCON都是在List之上的操作函数。
 
于是乎引出了本文,先说MAP. MAP函数操作的对象是Sequence,所以map可以应用在vector string list等sequence的子类型。因为Map在Sequence抽象数据类型之上操作,所以必须指定Map的返回类型,这就是map函数的第一个参数。其他的MAPC, MAPCAR, MAPCAN, MAPL, MAPLIST, MAPCON在List之上的操作函数。

下面我来具体介绍各个函数的说明:首先是Map

Function MAPSyntax:
map result-type function &rest sequences+ => result
Arguments and Values:
result-type -- a sequence type specifier, or nil.
function---a function designator. function must take as many arguments as there are sequences.
sequence---a proper sequence.
result---if result-type is a type specifier other than nil, then a sequence of the type it denotes; otherwise (if the result-type is nil), nil.
Description:
Applies function to successive sets of arguments in which one argument is obtained from each sequence. The function is called first on all the elements with index 0, then on all those with index 1, and so on. The result-type specifies the type of the resulting sequence.
map returns nil if result-type is nil. Otherwise, map returns a sequence such that element j is the result of applying function to element j of each of the sequences. The result sequence is as long as the shortest of the sequences. The consequences are undefined if the result of applying function to the successive elements of the sequences cannot be contained in a sequence of the type given by result-type.
If the result-type is a subtype of list, the result will be a list.
If the result-type is a subtype of vector, then if the implementation can determine the element type specified for the result-type, the element type of the resulting array is the result of upgrading that element type; or, if the implementation can determine that the element type is unspecified (or *), the element type of the resulting array is t; otherwise, an error is signaled.
Examples:
 (map 'string #'(lambda (x y)
                  (char "01234567890ABCDEF" (mod (+ x y) 16)))
       '(1 2 3 4)
       '(10 9 8 7)) =>  "AAAA"
 (setq seq '("lower" "UPPER" "" "123")) =>  ("lower" "UPPER" "" "123")
 (map nil #'nstring-upcase seq) =>  NIL
 seq =>  ("LOWER" "UPPER" "" "123")
 (map 'list #'- '(1 2 3 4)) =>  (-1 -2 -3 -4)
 (map 'string
      #'(lambda (x) (if (oddp x) #\1 #\0))
      '(1 2 3 4)) =>  "1010"

 (map '(vector * 4) #'cons "abc" "de") should signal an error


Function 
MAPC, MAPCAR, MAPCAN, MAPL, MAPLIST, MAPCONSyntax:
mapc function &rest lists+ => list-1
mapcar function &rest lists+ => result-list
mapcan function &rest lists+ => concatenated-results
mapl function &rest lists+ => list-1
maplist function &rest lists+ => result-list
mapcon function &rest lists+ => concatenated-results
Arguments and Values:
function---a designator for a function that must take as many arguments as there are lists.
list---a proper list.
list-1---the first list (which must be a proper list).
result-list---a list.
concatenated-results---a list.
Description:
The mapping operation involves applying function to successive sets of arguments in which one argument is obtained from each sequence. Except for mapc and mapl, the result contains the results returned by function. In the cases of mapc and mapl, the resulting sequence is list.


function is called first on all the elements with index 0, then on all those with index 1, and so on. result-type specifies the type of the resulting sequence. If function is a symbol, it is coerced to a function as if by symbol-function.

 

mapcar operates on successive elements of the lists. function is applied to the first element of each list, then to the second element of each list, and so on. The iteration terminates when the shortest list runs out, and excess elements in other lists are ignored. The value returned by mapcar is a list of the results of successive calls to function.


mapcar 函数连续依次操作列表集合每个列表的元素。 mapcar 首先将函数apply到每个列表的第一个元素(也就是把每个列表的第一个元素当做fuction的形参),再将函数apply到每个列表的第二个元素。一直到最短的列表的最后一个元素。剩下的元素将被忽略。它的结果是返回一个list,这个list是参数list集合的元素依次应用于function的结果。例如:

CL-USER>  (mapcar #'(lambda (x ) (* 2 x)) '(1 2 3 ))
(2 4 6)
CL-USER> (mapcar #'(lambda (x ) (* 2 x)) '(1 2 3 ) '(12 12 12 ));;抛出异常,因为fuction只有一个形参,但是却传递两个list

CL-USER> (mapc #'(lambda (x ) (* 2 x)) '(1 2 3 ))
(1 2 3)


mapc is like mapcar except that the results of applying function are not accumulated. The list argument is returned.

 mapc 和 mapcar 类似。不过返回的是参数的第一个列表。并没有返回聚集的结果。所以它比Mapcar快。一般使用它的side effects。 例如:
(defun nodes->dot (nodes)
   (mapc (lambda (node)
                (fresh-line)
                (princ (dot-name (car node)))
                (princ "[label=\"")
                (princ (dot-label node))
                (princ "\"];"))
           nodes))


Although mapc  does not return the list,it still causes the code to iterate through the list and generate the same printed output that using mapcar would have, so it generates the same side effects asmapcar , a bit more quickly.

 


maplist is like mapcar except that function is applied to successive sublists of the lists. function is first applied to the lists themselves, and then to the cdr of each list, and then to the cdr of the cdr of each list, and so on.

maplist 和 mapcar 类似,不过首先将函数apply到每个列表参数的子列表。 函数首先应用于整个lists , 然后将函数apply到每个列表的cdr,然后将函数apply到每个列表的cddr。。直到最短的一个列表为空为止。

mapl is like maplist except that the results of applying function are not accumulated; list-1 is returned.

mapl 和maplist一样除了mapl返回第一个列表参数。mapl对于maplist正如mapc对应于mapcar。
mapcan and mapcon are like mapcar and maplist respectively, except that the results of applying function are combined into a list by the use of nconc rather than list. That is,
 (mapcon f x1 ... xn)
   ==  (apply #'nconc (maplist f x1 ... xn))

and similarly for the relationship between mapcan and mapcar.
Examples:
 (mapcar #'car '((1 a) (2 b) (3 c))) =>  (1 2 3)
 (mapcar #'abs '(3 -4 2 -5 -6)) =>  (3 4 2 5 6)
 (mapcar #'cons '(a b c) '(1 2 3)) =>  ((A . 1) (B . 2) (C . 3))

 (maplist #'append '(1 2 3 4) '(1 2) '(1 2 3))
=>  ((1 2 3 4 1 2 1 2 3) (2 3 4 2 2 3))
 (maplist #'(lambda (x) (cons 'foo x)) '(a b c d))
=>  ((FOO A B C D) (FOO B C D) (FOO C D) (FOO D))
 (maplist #'(lambda (x) (if (member (car x) (cdr x)) 0 1)) '(a b a c d b c))
=>  (0 0 1 0 1 1 1)
;An entry is 1 if the corresponding element of the input
;  list was the last instance of that element in the input list.

 (setq dummy nil) =>  NIL
 (mapc #'(lambda (&rest x) (setq dummy (append dummy x)))
        '(1 2 3 4)
        '(a b c d e)
        '(x y z)) =>  (1 2 3 4)
 dummy =>  (1 A X 2 B Y 3 C Z)                  

 (setq dummy nil) =>  NIL
 (mapl #'(lambda (x) (push x dummy)) '(1 2 3 4)) =>  (1 2 3 4)
 dummy =>  ((4) (3 4) (2 3 4) (1 2 3 4))

 (mapcan #'(lambda (x y) (if (null x) nil (list x y)))
          '(nil nil nil d e)
          '(1 2 3 4 5 6)) =>  (D 4 E 5)
 (mapcan #'(lambda (x) (and (numberp x) (list x)))
          '(a 1 b c 3 4 d 5))
=>  (1 3 4 5)

In this case the function serves as a filter; this is a standard Lisp idiom using mapcan.

 (mapcon #'list '(1 2 3 4)) =>  ((1 2 3 4) (2 3 4) (3 4) (4))


 

你可能感兴趣的:(function,list,vector,REST,lambda,lisp)