Глава 14
Последовательности

 14.1 Простые функции для последовательностей
 14.2 Объединение, отображение и приведение последовательностей
 14.3 Модификация последовательностей
 14.4 Поиск элементов последовательностей
 14.5 Сортировка и слияние

Тип sequence объединяет списки и вектора (одномерные массивы). Хотя это две различные структуры данных с различными структурными свойствами, приводящими к алгоритмически различному использованию, они имеют общее свойство: каждая хранит упорядоченное множество элементов.

Некоторые операции полезны и для списков и для массивов, потому что они взаимодействуют с упорядоченными множествами элементов. Можно запросить количество элементов, изменить порядок элементов на противоположный, извлечь подмножество (подпоследовательность) и так далее. Для таких целей Common Lisp предлагает ряд общих для всех типов последовательностей функций.

elt  reverse map remove
length  nreverse some remove-duplicates
subseq  concatenateevery delete
copy-seq position notany delete-duplicates
fill  find noteverysubstitute
replace  sort reduce nsubstitute
count  merge search mismatch

Некоторые из этих операций имеют более одной версии. Такие версии отличаются суффиксом (или префиксом) от имени базовой функции. Кроме того, многие операции принимают один или более необязательных именованных аргументов, которые могут изменить поведение операции.

Если операция требует проверки элементов последовательности на совпадение с некоторым условием, тогда это условие может быть указано одним из двух способов. Основная операция принимает объект и сравнивает с ним каждый элемент последовательности на равенство eql. (Операция сравнения может быть задана в именованном параметре :test или :test-not. Использование обоих параметров одновременно является ошибкой.) Другие варианты операции образуются с добавлением префиксов -if и -if-not. Эти операции, в отличие от базовой, принимают не объект, а предикат с одним аргументом. В этом случае проверяется истинность или ложность предиката для каждого элемента последовательности. В качестве примера,

(remove item sequence)

возвращает копию последовательности sequence, в которой удалены все элементы равные eql объекту emph.

(remove item sequence :test #’equal)

возвращает копию последовательности sequence, в которой удалены все элементы равные equal объекту emph.

(remove-if #’numberp sequence)

возвращает копию последовательности sequence, в которой удалены все числа.

Если операция любым методом проверяет элементы последовательности, то если именованный параметр :key не равняется nil, то он должен быть функцией одного аргумента, которая будет извлекать из элемента необходимую для проверки часть. Например,

(find item sequence :test #’eq :key #’car)

Это выражение ищет первый элемент последовательности sequence, car элемент которого равен eq объекту item.

X3J13 voted in June 1988 to allow the :key function to be only of type symbol or function; a lambda-expression is no longer acceptable as a functional argument. One must use the function special operator or the abbreviation #’ before a lambda-expression that appears as an explicit argument form.

Для некоторых операций было бы удобно указать направление обработки последовательности. В этом случае базовые операции обычно обрабатывают последовательность в прямом направлении. Обратное направление обработки указывается с помощью не-nil значения для именованного параметра :from-end. (Порядок обработки указываемый в :from-end чисто концептуальный. В зависимости от обрабатываемого объекта и реализации, действительный порядок обработки может отличаться. Поэтому пользовательские функции test не должны иметь побочных эффектов.)

Много операций позволяют указать подпоследовательность для обработки. Такие операции имеют именованные параметры :start и :end. Эти аргумент должны быть индексами внутри последовательности, и startend. Ситуация start > end является ошибкой. Эти параметры указывают подпоследовательность начиная с позиции start включительно и заканчивая позицией end невключительно. Таким образом длина подпоследовательности равна endstart. Если параметр start опущен, используется значение по-умолчанию ноль. Если параметр end опущен, используется значение по-умолчанию длина последовательности. В большинстве случаев, указание подпоследовательности допускается исключительно ради эффективности. Вместо этого можно было бы просто вызвать subseq. Однако, следует отметить, что операция, которая вычисляет индексы для подпоследовательности, возвращает индексы исходной последовательности, а не подпоследовательности:

(position #\b "foobar" :start 2 :end 5)  3
(position #\b (subseq "foobar" 2 5))  1

Если в операции участвует две последовательности, тогда ключевые параметры :start1, :end1, start2 и :end2 используются для указания отдельных подпоследовательностей для каждой последовательности.

X3J13 voted in June 1988 (and further clarification was voted in January 1989 ) to specify that these rules apply not only to all built-in functions that have keyword parameters named :start, :start1, :start2, :end, :end1, or :end2 but also to functions such as subseq that take required or optional parameters that are documented as being named start or end.

This may be summarized as follows. Let x be the sequence within which indices are to be considered. Let s be the “start” argument for that sequence of any standard function, whether explicitly specified or defaulted, through omission, to zero. Let e be the “end” argument for that sequence of any standard function, whether explicitly specified or defaulted, through omission or an explicitly passed nil value, to the active length of x, as returned by length. Then it is an error if the test (<= 0 s e (length x)) is not true.

Для некоторых функций, в частности remove и delete, ключевой параметр :count используется для указания, как много подходящих элементов должны обрабатываться. Если он равен nil или не указан, обрабатываются все подходящие элементы.

В следующих описаниях функций, элемент x последовательности «удовлетворяет условию», если любое из следующих выражений верно:

В каждом случае, функция keyfn является значением параметра :key (по-умолчанию функцией эквивалентности). Для примера, смотрите remove.

В следующих описаниях функций два элемента x и y, взятых из последовательности, «эквивалентны», если одно из следующих выражений верно:

Для примера, смотрите search.

X3J13 voted in June 1988 to allow the testfn or predicate to be only of type symbol or function; a lambda-expression is no longer acceptable as a functional argument. One must use the function special operator or the abbreviation #’ before a lambda-expression that appears as an explicit argument form.

Вы можете рассчитывать на порядок передачи аргументов в функцию testfn. Это позволяет использовать некоммутативную функцию проверки в стиле предиката. Порядок аргументов в функцию testfn соответствует порядку, в котором эти аргументы (или последовательности их содержащие) были переданы в рассматриваемую функцию. Если рассматриваемая функция передаёт два элемента из одной последовательности в функцию testfn, то аргументы передаются в том же порядке, в котором были в последовательности.

Если функция должна создать и вернуть новый вектор, то она всегда возвращает простой вектор (смотрите раздел 2.5). Таким же образом, любые создаваемые строки будут простыми строками.

[Function] complement fn

Returns a function whose value is the same as that of not applied to the result of applying the function fn to the same arguments. One could define complement as follows:

Данная функция возвращает другую функцию, значение которой является отрицанием функции fn. Функцию complement можно было определить так:

(defun complement (fn)
  #’(lambda (&rest arguments)
      (not (apply fn arguments))))

One intended use of complement is to supplant the use of :test-not arguments and -if-not functions.

Можно использовать функцию complement для эмуляции -if-not функций или аргумента :test-not.

(remove-if-not #’virtuous senators)
   (remove-if (complement #’virtuous) senators)

(remove-duplicates telephone-book
                   :test-not #’mismatch)
   (remove-duplicates telephone-book
                      :test (complement #’mismatch))