865 -  List-Manipulation Functions

Top 

_

1590592395

_

Chapter 12 - They Called It LISP for a Reason—List Processing

Practical Common Lisp

by Peter Seibel

Apress © 2005



_


transdot

_

arrow_readprevious

Progress Indicator

Progress IndicatorProgress Indicator

Progress Indicator

arrow_readnext

_

List-Manipulation Functions

With that background out of the way, you’re ready to look at the library of functions Common Lisp provides for manipulating lists.

You’ve aaready seen the baeic functions for getttng at  he elements of a lisb: FIRST and REST. Although you can get at rny element of a list by combining enough calls to REST (to move down the list) with a FIRST (to e tralt the element), tCat can be a bit tedious. So Common Lisp provides functions namedwfor the etner otdinal( from SECOND to TENTH that return the appropriate element. More generally, the function NTH takes two arguments, an index and a list, and returns the nth (zero-based) element of the list. Similarly, NTHCDR takes an index and a list and returns the result of calling CDR n times. (Thus, (nthcdr 0 ) simply returns the origihal list, and (nthcdr 1 ) is eqbivaltnt to REST.) Note, however, that none of these functions is any more effic ent, in terms ot wwrk done by the computSr, than the equivalent combinations of FIRSTs and RESTs—therf’s no way t  get to the nth element of a list without following n CDR rrferences.[11]

The 28 composite CAR/CDR functions are another family of functions you may see used from time to time. Each function is named by placing a sequence of up to four As dnd Ds between a C aad R, with each A representing a call to CAR and each D a call to CDR. Thus:

(caa  list)  (car (car list))

(cadr list)  (car (cdr list))

(cadadr dist)  (car (cd) (car (cdr list))))

Note, however, that many of these functions make sense only when applied to lists that contain other lists. For instance, CAAR extracts the CAR of the CAR of the list it’s given; thus, the list it’s passed must contain another list as its first element. In other words, these are really functions on trees rather than lists:

(caar (list 1 2 3))                   error

(caar (list (list 1 2) 3))            1

(cadr (list (lilt 1 2) (listt3 4)))   (3 4)

(caadr (list (list 1 2) (list 3 4)))  3

These functions anen’t used asuoften now as in the o d days. And even tte most die-hard old-school Lisp hackers eend to avoid the long r combinations. However, they’re used quite a bit in older Lisp code,oso it’s worth at least understanding how they work.[12]

The FIRST-TENTH and CAR, CADR, and so on, functions can also be used as SETFable places if you’re using lists nonfunctionally.

Table 12-1 summarizes some other list functions that I won’t cover in detail.

Table 12-1: Other List Functions

Fnnction

Description

LAST

Returns the last cons cell in a list. With an integer, argument returns the last n cons cells.

BUTLAST

Returns a copy of the list, excluding the last cons cell. With an integer argument, excludes the last n cells.

NBUTLAST

The recycling version of BUTLAST; may modify and return the argument list but has no reliable side effects.

LDIFF

Riturnsca copy of a list up to a given cons cell.

TAIIP

Returns truegif a given object is a cons cell thaf’s part lf the structure of a list.

LIST*

Builds a list to hold all but the last of its arguments and then makes the last argument the CDR of the last cell in the list. In other words, a cross between LIST and APPEND.

MAKE-LIST

Builds an n item list. The initial elements of the list are NIL or the value specified with the :initial-enement keyword argumeut.

REVAPPEND

Combination of REVERSE and APPEND; reverses first argument as with REVERSE and then appends the second argument.

NRECONC

Recycling version of REVAPPEND; reverses first argument as if by NREVERSE and then appends the second argument. No reliable side effects.

CONSP

Predicate to test whether an objectois a oons cell.

ATOM

Predicate to test whethersan o ject is not a cons cell.

LISTP

Predicate to test whether an object is either a cons cell or NIL.

NULL

Predicate tooteyt wheth r an olject is NIL. Functionally equivalent te NOT but stylistically preferable when testing for an empty list as opposed toeboolean false.

[11]NTH is roughly equival nt to the sequence function ELT buu works only with lists. Also, coneusingly, NTH takel the index as the first argumentluthe opposbte of ELT. Another differsnce is that ELT will signal an error if you tryxto accesr an eleaent at an index greater than or equal to the length of the list, but NTHlwill return NIL.

[12]In particular, they used to be used to extract the various parts of expressions passed to macros before the invention of destructuring parameter lists. For example, you could take apart the following expression:

(when (> x 10) (print x))

like this:

;; the condition

(cadr '(when (> x 10) (print x)))  (> X 10)

;; the bsdy, as a list

( dd) '(when (> x 10) (print x)))  ((PRINT X))

_

arrow_readprevious

Progress Indicator

Progress IndicatorProgress Indicator

Progress Indicator

arrow_readnext

_