5.3 Доступ к элементам списков

Функция: car cons-cell

Эта функция возвращает значение, на которое указывает первый слот ячейки cons cons-cell. Иными словами, она возвращает CAR ячейки cons-cell.

В особом случае, если cons-cell равен nil, эта функция возвращает nil. Таким образом, любой список является допустимым аргументом. Сигнализируется ошибка, если аргумент не является ячейкой cons или nil.

(car '(a b c))
     ⇒ a
(car '())
     ⇒ nil
Функция: cdr cons-cell

Эта функция возвращает значение, на которое указывает второй слот ячейки cons cons-cell. Иными словами, она возвращает CDR ячейки cons-cell.

В особом случае, если cons-cell равен nil, эта функция возвращает nil; следовательно, любой список является допустимым аргументом. Сигнализируется ошибка, если аргумент не является ячейкой cons или nil.

(cdr '(a b c))
     ⇒ (b c)
(cdr '())
     ⇒ nil
Функция: car-safe object

Эта функция позволяет извлечь CAR ячейки cons, избегая ошибок для других типов данных. Она возвращает CAR от object, если object является ячейкой cons, в противном случае — nil. Это отличается от car, которая сигнализирует ошибку, если object не является списком.

(car-safe object)
≡
(let ((x object))
  (if (consp x)
      (car x)
    nil))
Функция: cdr-safe object

Эта функция позволяет извлечь CDR ячейки cons, избегая ошибок для других типов данных. Она возвращает CDR от object, если object является ячейкой cons, в противном случае — nil. Это отличается от cdr, которая сигнализирует ошибку, если object не является списком.

(cdr-safe object)
≡
(let ((x object))
  (if (consp x)
      (cdr x)
    nil))
Макрос: pop listname

Этот макрос предоставляет удобный способ извлечь CAR списка и одновременно удалить его из списка. Он действует на список, хранящийся в listname. Он удаляет первый элемент из списка, сохраняет CDR в listname, а затем возвращает удалённый элемент.

В простейшем случае listname — это символ (без кавычек), именующий список; в этом случае данный макрос эквивалентен (prog1 (car listname) (setq listname (cdr listname))).

x
     ⇒ (a b c)
(pop x)
     ⇒ a
x
     ⇒ (b c)

В более общем случае listname может быть обобщённой переменной. В этом случае данный макрос сохраняет значение в listname с помощью setf. См. Обобщённые переменные.

О макросе push, который добавляет элемент в список, см. Изменение переменных-списков.

Функция: nth n list

Эта функция возвращает n-й элемент списка list. Элементы нумеруются начиная с нуля, поэтому CAR списка list является элементом с номером ноль. Если длина списка list меньше или равна n, возвращается nil.

(nth 2 '(1 2 3 4))
     ⇒ 3
(nth 10 '(1 2 3 4))
     ⇒ nil

(nth n x) ≡ (car (nthcdr n x))

Функция elt аналогична, но применима к любому типу последовательностей. По историческим причинам она принимает свои аргументы в обратном порядке. См. Последовательности.

Функция: nthcdr n list

Эта функция возвращает n-й CDR списка list. Иными словами, она пропускает первые n звеньев списка list и возвращает то, что следует за ними.

Если n равно нулю, nthcdr возвращает весь список list. Если длина списка list меньше или равна n, nthcdr возвращает nil.

Псевдонимом для nthcdr является drop.

(nthcdr 1 '(1 2 3 4))
     ⇒ (2 3 4)
(nthcdr 10 '(1 2 3 4))
     ⇒ nil
(nthcdr 0 '(1 2 3 4))
     ⇒ (1 2 3 4)
Функция: take n list

Эта функция возвращает первые n элементов списка list. По сути, она возвращает ту часть списка list, которую пропускает nthcdr.

take возвращает list без изменений, если он короче n элементов; возвращает nil, если n равно нулю или отрицательно.

В общем случае (append (take n list) (drop n list)) вернёт список, равный list.

(take 3 '(a b c d))
     ⇒ (a b c)
(take 10 '(a b c d))
     ⇒ (a b c d)
(take 0 '(a b c d))
     ⇒ nil
Функция: ntake n list

Это версия take, которая работает путём деструктивного изменения структуры списка-аргумента. Это делает её быстрее, но исходное значение list может быть утеряно.

ntake возвращает list без изменений, если он короче n элементов; возвращает nil, если n равно нулю или отрицательно. В противном случае она возвращает list, усечённый до первых n элементов.

Это означает, что обычно рекомендуется использовать возвращаемое значение, а не полагаться только на эффект усечения, если только n не заведомо положительно.

Функция: last list &optional n

Эта функция возвращает последнее звено списка list. car этого звена является последним элементом списка. Если list равен nil, возвращается nil. Если n не равен nil, возвращается n-е звено с конца, либо весь список list, если n больше длины list.

Функция: safe-length list

Эта функция возвращает длину списка list без риска ошибки или бесконечного цикла. Обычно она возвращает количество различных ячеек cons в списке. Однако для циклических списков возвращаемое значение является лишь верхней границей; оно часто слишком велико.

Если list не является nil или ячейкой cons, safe-length возвращает 0.

Наиболее распространённый способ вычисления длины списка, когда вы не опасаетесь, что он может быть циклическим, — использование length. См. Последовательности.

Функция: caar cons-cell

Это то же самое, что и (car (car cons-cell)).

Функция: cadr cons-cell

Это то же самое, что и (car (cdr cons-cell)) или (nth 1 cons-cell).

Функция: cdar cons-cell

Это то же самое, что и (cdr (car cons-cell)).

Функция: cddr cons-cell

Это то же самое, что и (cdr (cdr cons-cell)) или (nthcdr 2 cons-cell).

В дополнение к вышеперечисленным, определены ещё 24 комбинации car и cdr как cxxxr и cxxxxr, где каждый x — это либо a, либо d. cadr, caddr и cadddr извлекают соответственно второй, третий или четвёртый элементы списка. Пакет cl-lib предоставляет те же функции под именами cl-second, cl-third и cl-fourth. См. Функции для списков в Расширениях Common Lisp.

Функция: butlast x &optional n

Эта функция возвращает список x с удалённым последним элементом или последними n элементами. Если n больше нуля, она создаёт копию списка, чтобы не повредить исходный список. В общем случае (append (butlast x n) (last x n)) вернёт список, равный x.

Функция: nbutlast x &optional n

Это версия butlast, которая работает путём деструктивного изменения cdr соответствующего элемента, а не создания копии списка.