Mapping(映射)

    函数式风格的另一个重要方面是对高阶函数的使用,即那些接受其他函数作为参数或将函数作为返回值的函数。前面章节里出现过几个高阶函数,例如 MAP。尽管MAP可被同时用于列表和向量(也就是说,任何类型的序列),但 Common Lisp 另外还提供了 6 个特定用于列表的映射函数。这 6 个函数之间的区别在于它们构造结果的方式,以及它们究竟会将函数应用到列表的元素还是列表结构的点对单元上。

    MAPCAR is the function most like MAP. Because it always returns a list, it doesn’t require the result-type argument MAP does. Instead, its first argument is the function to apply, and subsequent arguments are the lists whose elements will provide the arguments to the function. Otherwise, it behaves like MAP: the function is applied to successive elements of the list arguments, taking one element from each list per application of the function. The results of each function call are collected into a new list. For example:

    MAPLIST is just like MAPCAR except instead of passing the elements of the list to the function, it passes the actual cons cells. Thus, the function has access not only to the value of each element of the list (via the CAR of the cons cell) but also to the rest of the list (via the CDR).

    他们之间的区别在于 MAPLIST 传递给函数的不是列表元素而是实际的点对单元。这样,该函数不仅可以访问到列表中每个元素的值(通过点对单元的 CAR),还可以访问到列表的其余部分(通过 CDR)。

    除了构造结果的方式不同之外,MAPCANMAPCONMAPCARMAPLIST 的工作方式也很相似。MAPCARMAPLIST 会构造一个全新的列表来保存函数调用的结果,而 MAPCANMAPCON 则通过将结果(必须是列表)用 NCONC 拼接在一起来产生它们的结果。这样,每次函数调用都可以向结果中提供任意数量的元素。MAPCANMAPCAR 那样把列表的元素传递到映射函数中,而 MAPCON 则像 MAPLIST 那样来传递点对单元。

    Finally, the functions MAPC and MAPL are control constructs disguised as functions—they simply return their first list argument, so they’re useful only when the side effects of the mapped function do something interesting. MAPC is the cousin of MAPCAR and MAPCAN while MAPL is in the MAPLIST/MAPCON family.