Spec-Zone.ru › Elisp

Создание ячеек 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API