Следующие функции выполняет различные операции над списками.
Список является одним из первых Lisp’овых типов данных. Имя «Lisp» расшифровывается как «LISt Processing».
Предикат endp используется для проверки конца списка. Возвращает ложь для cons-ячеек, истину для nil, и генерирует ошибку для всех остальных объектов других типов. _______________________________________
Заметка для реализации: Implementations are encouraged to signal an error, especially in the interpreter, for a non-list argument. The endp function is defined so as to allow compiled code to perform simply an atom check or a null check if speed is more important than safety.
list-length возвращает длину списка list. list-length отличается от length при использовании с циклическим списком. В таком случае length может не вернуть управление, тогда как list-length вернёт nil. Например:
list-length может быть реализован так:
Смотрите length, которая возвращает длину любой последовательности.
(nth n list) возвращает n-нный элемент списка list. car элемент списка принимается за «нулевой» элемент. Аргумент n должен быть неотрицательным целым числом. Если длина списка не больше чем n, тогда результат (), или другими словами nil. (Это согласовывается с концепцией того, что car и cdr от () являются ().) Например:
nth может быть использован в связке с setf для изменения элемента списка. В этом случае, аргумент n должен быть меньше чем длина списка list.
Следует отметить, что порядок аргументов в nth обратный в отличие от большинства других функций селекторов для последовательностей, таких ка elt.
[Функция]
first listИногда эти функции удобно использовать для доступа к определёнными элементам списка. first то же, что и car, second то же, что и cadr, third то же, что и caddr, и так далее. Следует отметить, что нумерация начинается с единицы (first) в отличие от нумерации, которая начинается с нуля и используется в nth.
Каждая из этих функций может быть использована в связке setf для изменения элемента массива.
rest означает то же, что и cdr, но мнемонически согласуется с first. rest может использоваться в связке с setf для изменения элементов массива.
(nthcdr n list) выполняет для списка lisp операцию cdr n раз, и возвращает результат. Например:
Другими словами, она возвращает n-нную cdr часть списка.
Аргумент n должен быть неотрицательным целым числом.
last возвращает последние n cons-ячеек списка lisp. Список list может быть списком с точкой. Передача зацикленного списка является ошибкой.
Аргумент n должен быть неотрицательным целым числом. Если n равен нулю, тогда возвращается последний атом списка list. Если n не меньше чем количество cons-ячеек, то возвращается весь список.
Например:
list создаёт и возвращает список, составленный из аргументов. Например:
list* похожа на list за исключением того, что последняя cons-ячейка создаваемого списка будет «с точкой». Последний аргумент используется как последний элемент списка, а именно в последней cons-ячейки в cdr элементе. Данный аргумент необязательно должен быть атомом, и если он не атом, то в результате список будет иметь большую длину чем количество аргументов. Например:
Это то же, что и
А также:
Функция создаёт и возвращает список содержащий количество size элементов, каждый из которых будет инициализирован значением аргумента :initial-element (который по-умолчанию nil). size должен быть неотрицательным целым числом. Например:
Функция возвращает список содержащий все элементы указанных в аргументах списков. Аргументы не разрушаются. Например:
Следует отметить, что append копирует верхний уровень всех переданных списков за исключением последнего. Функция concatenate выполняет похожую операцию, но всегда копирует все аргументы. Смотрите также nconc, которая похожа на append, но разрушает все аргументы кроме последнего.
Последний аргумент может быть любым Lisp объектом, и в этом случае этот объект становится последним элементов итогового списка. Например, (append ’(a b c) ’d) ⇒ (a b c . d).
(append x ’()) может быть использовано для копирования списка x, однако для этого больше подходит функция copy-list.
Функция возвращает список, который равен equal и в то же время не равен eq списку list, Копируется только верхний уровень списка, то есть copy-list копирует только в направлении cdr элементов, но не в направлении car элементов. Если список «с точкой», то есть (cdr (last list)) является не-nil атомом, тогда итоговый список также будет «с точкой». Смотрите также copy-seq и copy-tree.
copy-alist копирует ассоциативные списки. При этом, также как и в copy-list, копируется только верхний уровень списка lisp. Кроме того, каждый элемент списка list, являющийся в свою очередь cons-ячейкой, заменяется новой cons-ячейкой с теми же car и cons элементами.
copy-tree копирует древовидно организованные cons-ячейки. Аргумент object может быть любым Lisp’овым объектом. Если он не является cons-ячейкой, то ничего не произойдёт и данный объект будет возвращён в качестве результата. В противном случае будет возвращена новая cons-ячейка, в которой car и cons элементы будут результатами рекурсивных вызовов copy-tree. Другими словами, все cons-ячейки будут рекурсивно скопированы, и рекурсия будет останавливаться только на атомах.
(revappend x y) похожа на (append (reverse x) y) за исключением того, что она потенциально более производительна. Аргументы x и y должны быть списками. Аргумент x копируется (не разрушается) в отличие от nreconc, которая разрушает первый аргумент.
В качестве аргументов nconc принимает списки. Функция соединяет списки и возвращает результат. При этом аргументы изменяются, а не копируются. (В сравнении с append, которая копирует аргументы, а не разрушает их.) Например:
Следует отметить, что в примере, значение x отличается от первоначального, так как последняя cons-ячейка была изменена с помощью rplacd значением y. Если сейчас выполнить (nconc x y) ещё раз, тогда часть списка зациклится: (a b c d e f d e f d e f ...), и так до бесконечности. Если *print-circle* не равен nil, тогда вывод списка будет таким: (a b c . #1=(d e f . #1#)).
Вызов nconc, совпадающий с наиболее близким шаблоном выражения в левой части приводит к эквивалентным побочным действиям, как в правой части таблицы.
(nconc) | nil ;Нет побочных эффектов |
(nconc nil . r) | (nconc . r) |
(nconc x) | x |
(nconc x y) | (let ((p x) (q y)) |
(rplacd (last p) q) | |
p) | |
(nconc x y . r) | (nconc (nconc x y) . r) |
(nreconc x y) похожа на (nconc (nreverse x) y) за исключением того, что она потенциально эффективнее. Оба аргумента должны быть списками. Аргумент x разрушается. Сравните с revappend.
Поведение (nreconc x y) совпадает с поведением (nconc (nreverse x) y) в части побочных эффектов.
Форма place должна быть именем обобщённое переменной, содержащей список. item может указывать на любой Lisp’овый объект. item вставляется в начало списка и данный список возвращается в качестве результата. Форма place может быть любой формой, которая подходит для setf. Если рассматривать список как стек, тогда push добавляет элемент на вершину стека. Например:
Действие от
эквивалентно действию
за исключением того, что push выполняет форму place только один раз, а не три. Более того, в для некоторых форм place push может быть эффективнее чем версия с setf.
Следует отметить, что item вычисляется прежде чем вычисляется place.
Форма place должна быть именем обобщённое переменной, содержащей список. item может указывать на любой Lisp’овый объект. Если item не содержится в списке (этот факт устанавливается с помощью предиката переданного в :test, который по-умолчанию eql), тогда item вставляется в начало списка и данный список возвращается в качестве результата. В противном случае возвращается исходный список. Форма place может быть любой формой, которая подходит для setf. Если рассматривать список как множество, тогда pushnew добавляет элемент в множество. Смотрите adjoin.
Именованные параметры pushnew имеют тот же смысл, что и в функциях для последовательностей. Смотрите главу 14. По сути, данные аргументы идентичны аргументам adjoin.
pushnew возвращает модифицированное содержимое переменной place. Например:
Действие от
эквивалентно действию
за исключением того, что pushnew выполняет форму place только один раз, а не три. Более того, в для некоторых форм place pushnew может быть эффективнее чем версия с setf.
Следует отметить, что item вычисляется прежде чем вычисляется place.
Форма place должна быть именем обобщённое переменной, содержащей список. Результатом pop является результат car функции для переданного списка, и побочным эффектом является то, что в обобщённую переменную сохраняется результат cdr для списка. Форма place может быть любой формой, которая подходит для setf. Если рассматривать исходный список как стек, то pop достаёт элемент из вершины стека и возвращает его. Например:
Действия от (pop place) эквивалентно
за исключением того, что pop выполняет форму place только один раз, а не три. Более того, в для некоторых форм place pop может быть эффективнее чем версия с setf.
Функция создаёт и возвращает список с такими же элементами кроме n последних, что и в списке list. n по-умолчанию равно 1. Аргумент не разрушается. Если длина списка list меньше чем n, тогда возвращается (). Например:
Имя функции образовано от фразы «all elements but the last» («все элементы кроме последних»).
Это деструктивная версия butlast. Данная функция изменяет cdr элемент cons-ячейки на nil. Искомая cons-ячейка находится на позиции n+1 с конца списка. Если длина списка list меньше чем n, тогда возвращается (), и аргумент не модифицируется. (Таким образом можно написать (setq a (nbutlast a)), а не (nbutlast a).) Например:
Аргумент list должен быть списком, и sublist должен быть подсписком list. ldiff (означает «list difference») возвращает новый список, элементы которого содержат все элементы списка list до подсписка sublist. Если sublist не является частью list (или в частности равен nil), тогда возвращается копия всего списка list. Аргумент list не разрушается. Например:
так как подсписок не равен eq ни одной части списка.