Spec-Zone.ru › Elisp

Составные типы

Когда ни один из простых типов не подходит, вы можете использовать составные типы, которые строят новые типы из других типов или из указанных данных. Указанные типы или данные называются аргументами составного типа. Составной тип обычно выглядит так:

(constructor arguments…)

но вы также можете добавить пары ключ-значение перед аргументами, например так:

(constructor {keyword value}… arguments…)

Вот таблица конструкторов и как их использовать для записи составных типов:

(cons car-type cdr-type)

Значение должно быть ячейкой со списком, её CAR должен соответствовать car-type, а CDR — cdr-type. Например, (cons string symbol) — это тип настройки, который соответствует таким значениям, как ("foo" . foo).

В буфере настройки CAR и CDR отображаются и редактируются отдельно, каждый согласно своему указанному типу.

(list element-types…)

Значение должно быть списком с ровно таким количеством элементов, как указано в element-types; и каждый элемент должен соответствовать соответствующему element-type.

Например, (list integer string function) описывает список из трёх элементов; первый элемент должен быть целым числом, второй — строкой, а третий — функцией.

В буфере настройки каждый элемент отображается и редактируется отдельно, согласно указанному для него типу.

(group element-types…)

Это работает так же, как list, за исключением форматирования текста в буфере настроек. list помещает метку каждого значения элемента; group — нет.

(vector element-types…)

Подобно list, за исключением того, что значение должно быть вектором, а не списком. Элементы работают так же, как в list.

(alist :key-type key-type :value-type value-type)

Значение должно быть списком ячеек со списком, CAR каждой ячейки представляющий ключ типа настройки key-type, а CDR той же ячейки представляющий значение типа настройки value-type. Пользователь может добавлять и удалять пары ключ/значение и редактировать как ключ, так и значение каждой пары.

Если опущен, key-type и value-type по умолчанию равны sexp.

Пользователь может добавить любой ключ, соответствующий указанному типу ключа, но вы можете предоставить некоторым ключам предпочтительное обращение, указав их с помощью ключевого аргумента :options (см. Определения переменных). Указанные ключи всегда будут отображаться в буфере настроек (вместе с подходящим значением) с флажком, чтобы включить или исключить или отключить пару ключ/значение из списка. Пользователь не сможет редактировать ключи, указанные ключевым аргументом :options.

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

:options '("foo" "bar" "baz")

указывает, что существует три известных ключа, а именно "foo", "bar" и "baz", которые всегда будут отображаться первыми.

Возможно, вы захотите ограничить тип значения для определенных ключей, например, значение, связанное с ключом "bar", может быть только целым числом. Вы можете указать это, используя список вместо атома в списке. Первый элемент будет указывать ключ, как и раньше, а второй элемент — тип значения. Например:

:options '("foo" ("bar" integer) "baz")

Наконец, вы можете изменить способ отображения ключа. По умолчанию ключ просто отображается как const, так как пользователь не может изменить специальные ключи, указанные ключевым словом :options. Однако вы можете использовать более специализированный тип для отображения ключа, например function-item, если вы знаете, что это символ со связыванием функции. Это делается с использованием спецификации типа настройки вместо символа для ключа.

:options '("foo"
           ((function-item some-function) integer)
           "baz")

Многие списки используют списки из двух элементов вместо ячеек со списком. Например,

(defcustom list-alist
  '(("foo" 1) ("bar" 2) ("baz" 3))
  "Each element is a list of the form (KEY VALUE).")

вместо

(defcustom cons-alist
  '(("foo" . 1) ("bar" . 2) ("baz" . 3))
  "Each element is a cons-cell (KEY . VALUE).")

Из-за того, как списки реализованы на основе ячеек со списком, вы можете рассматривать list-alist в приведённом выше примере как список ячеек со списком, где тип значения — список с единственным элементом, содержащим фактическое значение.

(defcustom list-alist '(("foo" 1) ("bar" 2) ("baz" 3))
  "Each element is a list of the form (KEY VALUE)."
  :type '(alist :value-type (group integer)))

Здесь используется виджет group, а не list, только потому, что форматирование лучше подходит для этой цели.

Аналогично, вы можете иметь списки с несколькими значениями, связанными с каждым ключом, используя различные варианты этого приёма:

(defcustom person-data '(("brian"  50 t)
                         ("dorith" 55 nil)
                         ("ken"    52 t))
  "Alist of basic info about people.
Each element has the form (NAME AGE MALE-FLAG)."
  :type '(alist :value-type (group integer boolean)))
(plist :key-type key-type :value-type value-type)

Этот тип настройки похож на alist (см. выше), за исключением того, что (i) информация хранится в виде списка свойств (см. Списки свойств) и (ii) key-type, если опущен, по умолчанию равен symbol вместо sexp.

(choice alternative-types…)

Значение должно соответствовать одному из alternative-types. Например, (choice integer string) допускает либо целое число, либо строку.

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

Обычно строки в этом меню определяются автоматически по выбранным вариантам; однако вы можете указать различные строки для меню, включив ключевое слово :tag в альтернативы. Например, если целое число представляет количество пробелов, а строка — текст для буквального использования, вы можете записать тип настройки таким образом:

(choice (integer :tag "Number of spaces")
        (string :tag "Literal text"))

чтобы меню предлагало «Количество пробелов» и «Литеральный текст».

В любой альтернативе, для которой nil не является допустимым значением, отличным от const, вы должны указать допустимое значение по умолчанию для этой альтернативы, используя ключевое слово :value. См. Ключевые слова типов.

Если некоторые значения охватываются более чем одной из альтернатив, customize выберет первую альтернативу, которой значение подходит. Это означает, что вы всегда должны перечислять наиболее конкретные типы сначала, а наиболее общие — последними. Вот пример правильного использования:

(choice (const :tag "Off" nil)
        symbol (sexp :tag "Other"))

Таким образом, специальное значение nil не обрабатывается как другие символы, и символы не обрабатываются как другие выражения Lisp.

(radio element-types…)

Это похоже на choice, за исключением того, что варианты отображаются с помощью радиокнопок, а не меню. Это имеет преимущество в отображении документации для вариантов, когда это применимо, и поэтому часто является хорошим выбором для выбора между постоянными функциями (function-item типы настроек).

(const value)

Значение должно быть value — ничего другого не допускается.

Основное применение const — внутри choice. Например, (choice integer (const nil)) допускает либо целое число, либо nil.

:tag часто используется с const, внутри choice. Например,

(choice (const :tag "Yes" t)
        (const :tag "No" nil)
        (const :tag "Ask" foo))

описывает переменную, для которой t означает да, nil — нет, а foo — «спросить».

(other value)

Эта альтернатива может соответствовать любому значению Lisp, но если пользователь выберет эту альтернативу, это выберет значение value.

Основное применение other — в качестве последнего элемента choice. Например,

(choice (const :tag "Yes" t)
        (const :tag "No" nil)
        (other :tag "Ask" foo))

описывает переменную, для которой t означает да, nil — нет, а всё остальное — «спросить». Если пользователь выбирает «Спросить» из меню альтернатив, это задаёт значение foo; но любое другое значение (не t, nil или foo) отображается как «Спросить», точно так же, как foo.

(function-item function)

Подобно const, но используется для значений, которые являются функциями. Это отображает строку документации, а также имя функции. Строка документации — это либо та, которую вы указали с помощью :doc, либо собственная строка документации function.

(variable-item variable)

Подобно const, но используется для значений, которые являются именами переменных. Это отображает строку документации, а также имя переменной. Строка документации — это либо та, которую вы указали с помощью :doc, либо собственная строка документации variable.

(set types…)

Значение должно быть списком, и каждый элемент списка должен соответствовать одному из указанных types.

В буфере настроек это отображается как список, так что каждый из types может иметь либо один соответствующий элемент, либо нет. Невозможно указать два разных элемента, которые соответствуют одному и тому же types. Например, (set integer symbol) допускает одно целое число и/или один символ в списке; он не допускает нескольких целых чисел или нескольких символов. В результате редко используется неспецифические типы, такие как integer в set.

Чаще всего types в set являются типами const, как показано здесь:

(set (const :bold) (const :italic))

Иногда они описывают возможные элементы в списке:

(set (cons :tag "Height" (const height) integer)
     (cons :tag "Width" (const width) integer))

Это позволяет пользователю указать значение высоты необязательно и значение ширины необязательно.

(repeat element-type)

Значение должно быть списком, и каждый элемент списка должен соответствовать типу element-type. Это отображается в буфере настроек как список элементов, с кнопками «[INS]» и «[DEL]» для добавления или удаления элементов.

(restricted-sexp :match-alternatives criteria)

Это наиболее общий конструктор составных типов. Значение может быть любым объектом Lisp, который удовлетворяет одному из criteria. criteria должен быть списком, и каждый элемент должен быть одним из этих вариантов:

  • Предикат — это функция от одного аргумента, которая возвращает либо nil, либо не-nil в зависимости от аргумента. Использование предиката в списке означает, что объекты, для которых предикат возвращает не-nil, допустимы.
  • Записанная константа — это 'object. Этот вид элемента в списке означает, что само object является допустимым значением.

Например,

(restricted-sexp :match-alternatives
                 (integerp 't 'nil))

допускает целые числа, t и nil в качестве допустимых значений.

Буфер настроек отображает все допустимые значения с использованием их синтаксиса чтения, и пользователь редактирует их текстово.

Вот таблица ключевых слов, которые можно использовать в парах ключ-значение в составном типе:

:tag tag

Используйте tag в качестве названия этой альтернативы для целей взаимодействия с пользователем. Это полезно для типа, который появляется внутри choice.

:match-alternatives criteria

Используйте criteria для сопоставления возможных значений. Это используется только в restricted-sexp.

:args argument-list

Используйте элементы argument-list в качестве аргументов конструкции типа. Например, (const :args (foo)) эквивалентно (const foo). Вам редко нужно писать :args явно, так как обычно аргументы распознаются автоматически как всё, что следует после последней пары ключевое слово-значение.

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/Composite-Types.html

Spec-Zone.ru

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