Создание ячеек cons и списков
Многие функции создают списки, поскольку списки лежат в основе Lisp. cons — это фундаментальная функция создания списков; однако интересно отметить, что list используется чаще в исходном коде Emacs, чем cons.
- Функция: cons объект1 объект2
-
Эта функция является наиболее базовая функцией для создания новой структуры списка. Она создаёт новую ячейку cons, делая объект1 значением CAR, а объект2 — значением CDR. Затем она возвращает новую ячейку cons. Аргументы объект1 и объект2 могут быть любыми объектами Lisp, но чаще объект2 является списком.
(cons 1 '(2)) ⇒ (1 2)(cons 1 '()) ⇒ (1)(cons 1 2) ⇒ (1 . 2)consчасто используется для добавления одного элемента в начало списка. Это называется *добавлением элемента в список*. 5 Например:(setq list (cons newelt list))
Обратите внимание, что нет конфликта между переменной с именем
list, используемой в этом примере, и функцией с именемlist, описанной ниже; любое имя символа может служить для обеих целей.
- Функция: list &rest объекты
-
Эта функция создаёт список с объектами в качестве элементов. Результирующий список всегда заканчивается
nil. Если объектов не задано, возвращается пустой список.(list 1 2 3 4 5) ⇒ (1 2 3 4 5)(list 1 2 '(3 4 5) 'foo) ⇒ (1 2 (3 4 5) foo)(list) ⇒ nil
- Функция: make-list длина объект
-
Эта функция создаёт список из длины элементов, в котором каждый элемент равен объекту. Сравните
make-listсmake-string(см. Создание строк).(make-list 3 'pigs) ⇒ (pigs pigs pigs)(make-list 0 'pigs) ⇒ nil(setq l (make-list 3 '(a b))) ⇒ ((a b) (a b) (a b)) (eq (car l) (cadr l)) ⇒ t
- Функция: append &rest последовательности
-
Эта функция возвращает список, содержащий все элементы последовательностей. Последовательности могут быть списками, векторами, булевыми векторами или строками, но последний обычно должен быть списком. Все аргументы, кроме последнего, копируются, поэтому ни один из аргументов не изменяется. (См.
nconcв Переупорядочение для способа объединения списков без копирования.)В более общем случае, последний аргумент к
appendможет быть любым объектом Lisp. Последний аргумент не копируется и не преобразуется; он становится значением CDR последней ячейки cons в новом списке. Если последний аргумент сам по себе является списком, то его элементы фактически становятся элементами результирующего списка. Если последний элемент не является списком, результат является точечным списком, поскольку его последнее CDR неnilв соответствии с требованиями к правильному списку (см. Ячейки cons).
Вот пример использования append:
(setq trees '(pine oak))
⇒ (pine oak)
(setq more-trees (append '(maple birch) trees))
⇒ (maple birch pine oak)
trees
⇒ (pine oak)
more-trees
⇒ (maple birch pine oak)
(eq trees (cdr (cdr more-trees)))
⇒ t
Вы можете увидеть, как работает append, изучив диаграмму ячеек. Переменная trees устанавливается в список (pine oak), а затем переменная more-trees устанавливается в список (maple birch pine
oak). Однако переменная trees продолжает ссылаться на исходный список:
more-trees trees
| |
| --- --- --- --- -> --- --- --- ---
--> | | |--> | | |--> | | |--> | | |--> nil
--- --- --- --- --- --- --- ---
| | | |
| | | |
--> maple -->birch --> pine --> oak
Пустая последовательность не вносит вклад в значение, возвращаемое append. Вследствие этого, аргумент nil вынуждает копию предыдущего аргумента:
trees
⇒ (pine oak)
(setq wood (append trees nil))
⇒ (pine oak)
wood
⇒ (pine oak)
(eq wood trees)
⇒ nil
Это раньше было обычным способом копирования списка, до изобретения функции copy-sequence. См. Последовательности Массивы Векторы.
Здесь показано использование векторов и строк в качестве аргументов для append:
(append [a b] "cd" nil)
⇒ (a b 99 100)
С помощью apply (см. Вызов функций) можно добавить все списки в списке списков:
(apply 'append '((a b c) nil (x y z) nil))
⇒ (a b c x y z)
Если последовательностей не задано, возвращается nil:
(append)
⇒ nil
Вот несколько примеров, где последний аргумент не является списком:
(append '(x y) 'z)
⇒ (x y . z)
(append '(x y) [z])
⇒ (x y . [z])
Второй пример показывает, что когда последний аргумент является последовательностью, но не списком, элементы последовательности не становятся элементами результирующего списка. Вместо этого последовательность становится последним CDR, как и любой другой последний аргумент, не являющийся списком.
- Функция: copy-tree дерево &optional vecp
-
Эта функция возвращает копию дерева дерево. Если дерево является ячейкой cons, это создаёт новую ячейку cons с тем же CAR и CDR, затем рекурсивно копирует CAR и CDR аналогичным образом.
Обычно, когда дерево является чем-то другим, кроме ячейки cons,
copy-treeпросто возвращает дерево. Однако, если vecp неnil, она копирует векторы тоже (и работает рекурсивно с их элементами).
- Функция: flatten-tree дерево
Эта функция возвращает "распакованную" копию дерево, то есть список, содержащий все не-
nilконечные узлы или листья дерева ячеек cons, укоренённого в дерево. Листья в возвращаемом списке находятся в том же порядке, что и в дерево.
(flatten-tree '(1 (2 . 3) nil (4 5 (6)) 7))
⇒(1 2 3 4 5 6 7)
- Функция: ensure-list объект
-
Эта функция возвращает объект в виде списка. Если объект уже является списком, функция возвращает его; в противном случае функция возвращает список из одного элемента, содержащего объект.
Это обычно полезно, если у вас есть переменная, которая может быть или не быть списком, и вы можете сказать, например:
(dolist (elem (ensure-list foo)) (princ elem))
- Функция: number-sequence от &optional до разделения
-
Эта функция возвращает список чисел, начиная с от и увеличивая на разделение, и заканчивая на или немного перед до. разделение может быть положительным или отрицательным и по умолчанию равно 1. Если до равно
nilили численно равно от, значением является список из одного элемента(from). Если до меньше от с положительным разделением или больше от с отрицательным разделением, значением являетсяnil, потому что эти аргументы задают пустую последовательность.Если разделение равно 0 и до ни
nil, ни численно равно от,number-sequenceсигнализирует об ошибке, так как эти аргументы задают бесконечную последовательность.Все аргументы являются числами. Числа с плавающей точкой могут быть сложными, потому что арифметика с плавающей точкой неточна. Например, в зависимости от машины вполне может случиться, что
(number-sequence 0.4 0.6 0.2)возвращает список из одного элемента(0.4), а(number-sequence 0.4 0.8 0.2)возвращает список из трёх элементов. n-й элемент списка вычисляется по точной формуле(+ from (* n separation)). Таким образом, если нужно убедиться, что до включено в список, можно передать выражение этого точного типа для до. В качестве альтернативы можно заменить до несколько большим значением (или несколько более отрицательным значением, если разделение отрицательное).Примеры:
(number-sequence 4 9) ⇒ (4 5 6 7 8 9) (number-sequence 9 4 -1) ⇒ (9 8 7 6 5 4) (number-sequence 9 4 -2) ⇒ (9 7 5) (number-sequence 8) ⇒ (8) (number-sequence 8 5) ⇒ nil (number-sequence 5 8 -1) ⇒ nil (number-sequence 1.5 6 2) ⇒ (1.5 3.5 5.5)
Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Building-Lists.html