Spec-Zone.ru › Elisp

Вычисление

Чаще всего формы вычисляются автоматически в силу того, что они встречаются в выполняемой программе. В редких случаях может понадобиться написать код, который вычисляет форму, создаваемую во время выполнения, например после чтения формы из редактируемого текста или получения её из списка свойств. В таких случаях используйте функцию eval. Часто eval не нужна, и вместо неё следует использовать что-то другое. Например, чтобы получить значение переменной, хотя eval работает, предпочтительнее использовать symbol-value; а вместо хранения в списке свойств выражений, которые затем нужно передавать в eval, лучше хранить функции, которые затем передаются в funcall.

Функции и переменные, описанные в этом разделе, вычисляют формы, задают ограничения процесса вычисления или сохраняют недавно возвращённые значения. Загрузка файла также выполняет вычисление (см. Загрузка).

Как правило, чище и гибче хранить функцию в структуре данных и вызывать её с помощью funcall или apply, чем хранить в структуре данных выражение и вычислять его. Использование функций позволяет передавать им информацию в виде аргументов.

Функция: eval form &optional lexical

Это основная функция для вычисления выражения. Она вычисляет form в текущем окружении и возвращает результат. Тип объекта form определяет способ его вычисления. См. раздел Виды форм.

Аргумент lexical задаёт правило видимости локальных переменных (см. раздел Правила видимости привязок переменных). Если он равен t, это означает, что form следует вычислять с лексической видимостью; это рекомендуемое значение. Если аргумент опущен или равен nil, используется старое правило видимости переменных, основанное только на динамической видимости.

Значением lexical также может быть непустой список, задающий определённое лексическое окружение для лексических привязок; однако эта возможность полезна только для специальных целей, например в отладчиках Emacs Lisp. Каждый элемент списка — это либо конс-ячейка, представляющая пару «лексический символ — значение», либо символ, представляющий (специальную) переменную, для которой при связывании используется динамическая видимость.

Поскольку eval является функцией, выражение аргумента, указанное в вызове eval, вычисляется дважды: один раз при подготовке перед вызовом eval и ещё раз самой функцией eval. Вот пример:

(setq foo 'bar)
     ⇒ bar
(setq bar 'baz)
     ⇒ baz
;; Here eval receives argument foo
(eval 'foo)
     ⇒ bar
;; Here eval receives argument bar, which is the value of foo
(eval foo)
     ⇒ baz

Количество одновременно активных вызовов eval ограничено значением max-lisp-eval-depth (см. ниже).

Команда: eval-region start end &optional stream read-function

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

По умолчанию eval-region не выводит никаких данных. Однако, если stream не равен nil, все данные, выводимые функциями вывода (см. раздел Функции вывода), а также значения, полученные в результате вычисления выражений в области, печатаются с использованием stream. См. раздел Потоки вывода.

Если read-function не равен nil, он должен быть функцией, которая используется вместо read для последовательного чтения выражений. Эта функция вызывается с одним аргументом — потоком для чтения ввода. Для указания этой функции также можно использовать переменную load-read-function (см. раздел Как программы выполняют загрузку), но использование аргумента read-function надёжнее.

eval-region не перемещает точку. Она всегда возвращает nil.

Команда: eval-buffer &optional buffer-or-name stream filename unibyte print

Эта функция похожа на eval-region, но её аргументы предоставляют другие необязательные возможности. eval-buffer работает со всей доступной частью буфера buffer-or-name (см. раздел Сужение области видимости в Руководстве GNU Emacs). buffer-or-name может быть буфером, именем буфера (строкой) или nil (либо быть опущен), что означает использование текущего буфера. stream используется так же, как в eval-region, если только stream не равен nil, а print — nil. В этом случае значения, полученные в результате вычисления выражений, по-прежнему отбрасываются, но вывод функций вывода печатается в области эха. filename — это имя файла, используемое для load-history (см. раздел Выгрузка); по умолчанию оно равно buffer-file-name (см. раздел Имя файла буфера). Если unibyte не равен nil, read по возможности преобразует строки в однобайтные.

Пользовательский параметр: max-lisp-eval-depth

Эта переменная задаёт максимальную глубину вызовов eval, apply и funcall, после превышения которой возникает ошибка (с сообщением "Lisp nesting exceeds max-lisp-eval-depth").

Это ограничение и связанная с его превышением ошибка позволяют Emacs Lisp избегать бесконечной рекурсии в некорректно определённой функции. Если слишком сильно увеличить значение max-lisp-eval-depth, такой код вместо этого может вызвать переполнение стека. В некоторых системах это переполнение можно обработать. В таком случае обычное вычисление Lisp прерывается, а управление передаётся обратно в главный цикл команд верхнего уровня (top-level). Обратите внимание, что в этой ситуации войти в отладчик Emacs Lisp невозможно. См. раздел Вызов отладчика при ошибке.

Ограничение глубины учитывает внутреннее использование eval, apply и funcall, например при вызове функций, упомянутых в выражениях Lisp, при рекурсивном вычислении аргументов вызова функции и форм её тела, а также при явных вызовах в коде Lisp.

Значение этой переменной по умолчанию — 1600. Если задать значение меньше 100, Lisp сбросит его до 100 при достижении заданного значения.

Пользовательский параметр: lisp-eval-depth-reserve

Чтобы иметь возможность отлаживать ошибки бесконечной рекурсии, при вызове отладчика Lisp Emacs временно увеличивает значение max-lisp-eval-depth, если оставшегося запаса глубины мало, чтобы у самого отладчика было достаточно ресурсов для работы. То же происходит при запуске обработчика handler-bind. См. раздел Написание кода для обработки ошибок.

Переменная lisp-eval-depth-reserve ограничивает дополнительную глубину, которую Emacs может добавить к max-lisp-eval-depth в таких исключительных случаях.

Значение этой переменной по умолчанию — 200.

Переменная: values

Значение этой переменной — список значений, возвращённых всеми выражениями, которые были считаны, вычислены и выведены из буферов (включая минибуфер) стандартными командами Emacs, выполняющими эти действия. (Обратите внимание, что сюда не входит вычисление в буферах *ielm* и вычисление с помощью C-j, C-x C-e и подобных команд в lisp-interaction-mode.)

Эта переменная устарела и будет удалена в будущей версии, поскольку постоянно увеличивает объём памяти, используемой процессом Emacs. Поэтому мы не рекомендуем её использовать.

Элементы values упорядочены от самых новых к самым старым.

(setq x 1)
     ⇒ 1
(list 'A (1+ 2) auto-save-default)
     ⇒ (A 3 t)
values
     ⇒ ((A 3 t) 1 ...)

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

;; Refer to the most recent evaluation result.
(nth 0 values)
     ⇒ (A 3 t)
;; That put a new element on,
;;   so all elements move back one.
(nth 1 values)
     ⇒ (A 3 t)
;; This gets the element that was next-to-most-recent
;;   before this example.
(nth 3 values)
     ⇒ 1

Copyright © 1990-1996, 1998-2026 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Eval.html

Spec-Zone.ru

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