9.5 Сокращения

Символы shorthands, иногда называемые «переименованные символы», являются символьными формами, встречающимися в исходном коде Lisp. Они ничем не отличаются от обычных символьных форм, за исключением того, что когда парсер Lisp встречает их, он создает символы, которые имеют другое и обычно более длинное имя вывода (print name) (см. Компоненты символов).

Полезно рассматривать сокращения как сокращение полных названий предполагаемых символов. Несмотря на это, не путайте сокращения с системой Abbrev (см. Abbrevs и расширение Abbrev).

Сокращения облегчают работу с правилами именования (namespacing etiquette) Emacs Lisp. Поскольку все символы хранятся в одном obarray (см. Создание и интернирование символов), программисты обычно префиксуют имя каждого символа именем библиотеки, из которой он происходит. Например, функции text-property-search-forward и text-property-search-backward принадлежат библиотеке text-property-search.el (см. Загрузка). Правильно префиксируя имена символов, можно эффективно предотвратить конфликты между символами с похожими именами, принадлежащими к разным библиотекам и, следовательно, выполняющими разные действия. Однако эта практика часто приводит к очень длинным именам символов, которые неудобно набирать и читать со временем. Сокращения решают эти проблемы чистым способом.

Переменная: read-symbol-shorthands

Значение этой переменной представляет собой alist, элементы которого имеют вид (shorthand-prefix . longhand-prefix). Каждый элемент инструктирует парсер Lisp читать каждую символьную форму, начинающуюся с shorthand-prefix, как если бы она начиналась с longhand-prefix.

Эту переменную можно установить только в файловых переменных (см. Локальные переменные в файлах в Руководство GNU Emacs).

Вот пример использования сокращений в гипотетической библиотеке для манипулирования строками some-nice-string-utils.el.

(defun some-nice-string-utils-split (separator s &optional omit-nulls)
  "A match-data saving variant of `split-string'."
  (save-match-data (split-string s separator omit-nulls)))

(defun some-nice-string-utils-lines (s)
  "Split string S at newline characters into a list of strings."
  (some-nice-string-utils-split "\(\r\n\|\[\n\r\]\)" s))

Как видно, читать или разрабатывать этот код довольно утомительно, поскольку имена символов для набора очень длинные. Мы можем использовать сокращения, чтобы смягчить эту проблему.

(defun snu-split (separator s &optional omit-nulls)
  "A match-data saving variation on `split-string'."
  (save-match-data (split-string s separator omit-nulls)))

(defun snu-lines (s)
  "Split string S into a list of strings on newline characters."
  (snu-split "\(\r\n\|\[\n\r\]\)" s))

;; Local Variables:
;; read-symbol-shorthands: (("snu-" . "some-nice-string-utils-"))
;; End:

Хотя два фрагмента выглядят по-разному, после обработки парсером Lisp они очень похожи. Оба приведут к интернированию абсолютно одинаковых символов (см. Создание и интернирование символов). Таким образом, загрузка или байт-компиляция любого из двух файлов дает эквивалентные результаты. Сокращения snu-split и snu-lines, используемые во второй версии, не интернируются в obarray. Это легко увидеть, переместив курсор в место, где используются сокращения, и дождавшись подсказки ElDoc (см. Локальные переменные в файлах в Руководство GNU Emacs), чтобы увидеть истинное полное имя символа под курсором в области вывода.

Поскольку read-symbol-shorthands является файловой переменной, возможно, что несколько библиотек, зависящих от some-nice-string-utils-lines.el, ссылаются на одни и те же символы под разными сокращениями или вообще не используют сокращения. В следующем примере библиотека my-tricks.el ссылается на символ some-nice-string-utils-lines, используя префикс sns- вместо snu-.

(defun t-reverse-lines (s) (string-join (reverse (sns-lines s)) "\n")

;; Local Variables:
;; read-symbol-shorthands: (("t-" . "my-tricks-")
;;                          ("sns-" . "some-nice-string-utils-"))
;; End:

Обратите внимание, что если у вас есть два сокращения в одном файле, где одно является префиксом другого, будет предпринята попытка использовать более длинное сокращение. Это происходит независимо от порядка, в котором вы указываете сокращения в разделе локальных переменных вашего файла.

'(
  t//foo ; читается как 'my-tricks--foo', а не 'my-tricks-/foo'
  t/foo  ; читается как 'my-tricks-foo'
  )

;; Local Variables:
;; read-symbol-shorthands: (("t/" . "my-tricks-")
;;                          ("t//" . "my-tricks--"))
;; End:

9.5.1 Исключения

Существуют два исключения из правил, управляющих преобразованиями сокращений: