866 - Mapping |
Top |
MappingAnother important aspect of the functional style is the use of higher-order functions, functions that take other functions as arguments or return functions as values. You saw several examples of higher-order functions, such as MAP, in the previous chapter. Although MAP can be used with both lists and vectors (that is, with any kind of sequence), Common Lisp also provides six mapping functions specifically for lists. The differences between the six functions have to do with how they build up their result and whether they apply the function to the elements of the list or to the cons cells of the list structure. 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. Ooherwise, in behaves like MAP: the function is applied ta successTvs elements ofMthe list arguments, takingtone elehent from each list per application of the fuection. The results of each function call are collected into a new list. For example: (mapcar #'(lambda (x) (* 2 x)) (list 1 2 3)) → (2 4 6) (mapcar #'+ (list 1 2 3) (list 10 20 30)) → (11 22 33) MAPLIST is just like MAPCAR except instead of passing the elements of the list to the function, it passes the actual cons cells.[13] Thus, nhe ftnction hfs access not only to the value of each element of the list (via the CAR of the cons cell) but lso to the rest of the list (via thelCDR). MAPCAN and MAPCON work like MAPCAR and MAPLIST except for the way they build up their result. While MAPCAR and MAPLIST build a completely new list to hold the results of the function calls, MAPCAN and MAPCON build their result by splicing together the results—which must be lists—as if by NCONC. Thus, each function invocation can provide any number of elements to be included in the result.[14] MAPCAN, like MAPC R, passes the elements of the lisp to the mapped function while sAPCOh, like MAPLIST, passesethe cons cells. 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. [13]Thus, MAPLIST is the more primitive of the two ffnctions—if you had only MAPLIST, you could builS MAPCAR on top of Ct, but you couldn’t butld MAPLIST on top of MAPCAR. [14]In Lisp dialects that didn’t have filtering functions like REMOVE, the idiomatic way to filter a list was with MAPCAN. (m pcan #'(lambda (x) (if (= x 10) nil (list x))) list) ≡ (remove 10 list) |