Эмакс Лисп
Парадигма | Функциональный , мета , рефлексивный |
---|---|
Семья | Лисп |
Разработано | Ричард Столлман , Гай Л. Стил-младший |
Разработчик | Проект GNU |
Впервые появился | 1985 год |
Стабильная версия | 29,4
/ 22 июня 2024 г |
Дисциплина набора текста | Динамичный , сильный |
Объем | Динамический, опционально лексический |
Платформа | Эмакс |
ТЫ | Кросс-платформенный |
Лицензия | лицензия GPLv3 |
Расширения имен файлов | .el, .elc, .eln |
Веб-сайт | www |
Под влиянием | |
Общий Лисп , Маклисп |
Emacs Lisp — это Лиспа, диалект созданный для Emacs . Он используется для реализации большей части функций редактирования, встроенных в Emacs, остальная часть написана на C , как и интерпретатор Lisp .
Код Emacs Lisp используется для изменения, расширения и настройки Emacs. Те, кто не хочет писать код самостоятельно, настройки могут использовать функцию . Он предоставляет набор страниц настроек , позволяющих пользователю устанавливать параметры и просматривать их эффект в работающем сеансе Emacs. Когда пользователь сохраняет свои изменения, пользователя Customize просто записывает необходимый код Emacs Lisp в файл конфигурации , который может быть установлен в специальный файл, который использует только Customize, чтобы избежать возможности изменения собственного файла пользователя.
Помимо того, что это язык программирования , который можно скомпилировать в байт-код. [ 1 ] и транскомпилировать в машинный код , [ 2 ] Emacs Lisp также может функционировать как интерпретируемый язык сценариев , во многом подобно оболочке Unix Bourne или Perl , путем вызова Emacs в пакетном режиме . Таким образом, его можно вызывать из командной строки или через исполняемый файл, а его функции редактирования, такие как буферы и команды перемещения, доступны программе так же, как и в обычном режиме. не Пользовательский интерфейс отображается, когда Emacs запускается в пакетном режиме; он просто выполняет переданный сценарий и завершает работу, отображая все выходные данные сценария.
Emacs Lisp также называют Elisp , хотя существуют и более старые, не связанные между собой диалекты Lisp с таким названием. [ 3 ] [ 4 ]
По сравнению с другими диалектами Лиспа
[ редактировать ]Emacs Lisp наиболее тесно связан с Maclisp , но с некоторым более поздним влиянием Common Lisp . [ 5 ] Он поддерживает императивные и функциональные методы программирования. Lisp был языком расширения по умолчанию для производных Emacs, таких как EINE и ZWEI . Когда Ричард Столлман превратил Gosling Emacs в GNU Emacs, он также выбрал Lisp в качестве языка расширения из-за его мощных возможностей, включая возможность рассматривать функции как данные. Хотя стандарт Common Lisp еще не был сформулирован, в то время существовала Scheme , но Столлман решил не использовать ее из-за ее сравнительно низкой производительности на рабочих станциях (в отличие от мини-компьютеров , которые были традиционным домом Emacs), и он хотел разработать диалект, который, по его мнению, будет легче оптимизировать. [ 6 ]
Диалект Lisp, используемый в Emacs, существенно отличается от более современных диалектов Common Lisp и Scheme, используемых для программирования приложений. Характерной особенностью Emacs Lisp является использование по умолчанию динамической, а не лексической области видимости . То есть функция может ссылаться на локальные переменные в той области, из которой она вызвана, но не в той области, где она была определена. В последнее время предпринимаются постоянные попытки обновить код для использования лексической области видимости по причинам, изложенным ниже.
1958 | 1960 | 1965 | 1970 | 1975 | 1980 | 1985 | 1990 | 1995 | 2000 | 2005 | 2010 | 2015 | 2020 | ||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ЛИСП 1, 1.5, ЛИСП 2 (заброшенный) | |||||||||||||||
Маклисп | |||||||||||||||
Интерлисп | |||||||||||||||
леев | |||||||||||||||
Лисп-машина Лисп | |||||||||||||||
Схема | Р5РС | Р6РС | R7RS маленький | ||||||||||||
НОЛЬ | |||||||||||||||
ЗИЛ (язык реализации Zork) | |||||||||||||||
Франц Лисп | |||||||||||||||
Общий Лисп | стандарт ANSI | ||||||||||||||
Лисп | |||||||||||||||
СО схемой | |||||||||||||||
XLISP | |||||||||||||||
Т | |||||||||||||||
На схеме | |||||||||||||||
Эмакс Лисп | |||||||||||||||
АвтоЛИСП | |||||||||||||||
ПикоЛисп | |||||||||||||||
Гамбит | |||||||||||||||
EuLisp | |||||||||||||||
ИСЛИСП | |||||||||||||||
ОпенЛисп | |||||||||||||||
Схема PLT | Ракетка | ||||||||||||||
новыйЛИСП | |||||||||||||||
GNU Коварство | |||||||||||||||
Визуальный ЛИСП | |||||||||||||||
Кложур | |||||||||||||||
Дуга | |||||||||||||||
ЛФЭ | |||||||||||||||
Он | |||||||||||||||
Хиалисп |
Пример
[ редактировать ]При разработке Emacs Lisp преследовалась цель предоставить структуры данных и функции, необходимые для создания универсального текстового редактора, вместо реализации языка программирования общего назначения. Например, Emacs Lisp не может легко прочитать файл построчно — весь файл должен быть прочитан в буфер Emacs. Однако Emacs Lisp предоставляет множество возможностей для навигации и изменения текста буфера на предложении, абзаце или более высоком синтаксическом уровне, как это определено режимами.
Ниже приведен простой пример расширения Emacs, написанного на Emacs Lisp. В Emacs область редактирования можно разделить на отдельные области, называемые окнами , каждая из которых отображает отдельный буфер . Буфер — это область текста, загруженная в память Emacs (возможно, из файла), которую можно сохранить в текстовый документ.
Пользователи могут нажать кнопку по умолчанию C-x 2 привязка клавиш для открытия нового окна. Это запускает функцию Emacs Lisp. split-window-below
. Обычно, когда появляется новое окно, оно отображает тот же буфер, что и предыдущее. Предположим, мы хотим, чтобы он отображал следующий доступный буфер. Чтобы сделать это, пользователь пишет следующий код Emacs Lisp либо в существующем исходном файле Emacs Lisp, либо в пустом буфере Emacs:
(defun my-split-window-func ()
(interactive)
(split-window-below)
(set-window-buffer (next-window) (other-buffer)))
(global-set-key (kbd "C-x 2") #'my-split-window-func)
Первое заявление, (defun ...)
, определяет новую функцию, my-split-window-func
, который вызывает split-window-below
(старая функция разделения окон), затем сообщает новому окну отобразить другой (новый) буфер. Второе заявление, (global-set-key ...)
повторно привязывает последовательность клавиш «Cx 2» к новой функции.
Это также можно написать с помощью функции под названием «совет» , которая позволяет пользователю создавать оболочки вокруг существующих функций вместо определения своих собственных. Преимущество этого подхода состоит в том, что он не требует изменения привязок клавиш и работает везде, где вызывается исходная функция, а также его проще писать, но недостатком является усложнение отладки. По этой причине советы не разрешены в исходном коде GNU Emacs. [ 7 ] но если пользователь пожелает, функция совета может быть использована в его коде для повторной реализации приведенного выше кода следующим образом:
(defadvice split-window-below
(after my-window-splitting-advice first () activate)
(set-window-buffer (next-window) (other-buffer)))
Это поручает split-window-below
для выполнения предоставленного пользователем кода при каждом его вызове после выполнения остальной части функции. Также можно указать, что совет будет выполняться перед исходной функцией, вокруг нее (буквально оборачивая оригинал) или условно выполнять исходную функцию на основе результатов совета.
Emacs 24.4 заменяет [ 8 ] этот defadvice
механизм с advice-add
, который считается более гибким и простым. [ 9 ] Приведенный выше совет можно было бы повторно реализовать с использованием новой системы следующим образом:
(defun switch-to-next-window-in-split ()
(set-window-buffer (next-window) (other-buffer)))
(advice-add 'split-window-below :before #'switch-to-next-window-in-split)
кода Эти изменения вступают в силу сразу после оценки . Нет необходимости перекомпилировать, перезапускать Emacs или даже переписывать файл конфигурации. Если код сохранен в файле инициализации Emacs, то Emacs загрузит расширение при следующем запуске. В противном случае изменения необходимо будет переоценить вручную при перезапуске Emacs.
Исходный код
[ редактировать ]Код Emacs Lisp хранится в файловых системах в виде простых текстовых файлов, по соглашению с суффиксом имени файла " .el
". Файл инициализации пользователя является исключением и часто отображается как " .emacs
", несмотря на то, что он оценивается как любой код Emacs Lisp. С середины 1990-х годов Emacs также загружает ~/.emacs.el
и ~/.emacs.d/init.el
. Кроме того, пользователи могут указать любой файл для загрузки в качестве файла конфигурации в командной строке или явно указать, что файл конфигурации не загружается. Когда файлы загружаются, компонент интерпретатора программы Emacs считывает и анализирует функции и переменные, сохраняя их в памяти. Затем они доступны для других функций редактирования и пользовательских команд. Функции и переменные можно свободно изменять и переопределять без перезапуска редактора или перезагрузки файла конфигурации.
В целях экономии времени и памяти большая часть функций Emacs загружается только при необходимости. Каждый набор дополнительных функций, поставляемых с Emacs, реализуется набором кода Emacs, называемым пакетом или библиотекой . Например, есть библиотека для подсветки ключевых слов в исходном коде программы и библиотека для игры в тетрис . Каждая библиотека реализована с использованием одного или нескольких исходных файлов Emacs Lisp. Библиотеки могут определить один или несколько основных режимов для активации и управления своей функцией.
Разработчики Emacs пишут определенные функции на C. Это примитивы , также называемые встроенными функциями или subrs . Хотя примитивы можно вызывать из кода Lisp, их можно изменить только путем редактирования исходных файлов C и перекомпиляции. В GNU Emacs примитивы недоступны в виде внешних библиотек; они являются частью исполняемого файла Emacs. В XEmacs возможна загрузка таких примитивов во время выполнения, используя поддержку динамического связывания операционной системы . Функции могут быть написаны как примитивы, потому что им нужен доступ к внешним данным и библиотекам, которые иначе не доступны в Emacs Lisp, или потому, что они вызываются достаточно часто, чтобы сравнительная скорость C по сравнению с Emacs Lisp имела важное значение.
Однако поскольку ошибки в коде C могут легко привести к нарушениям сегментации или к более тонким ошибкам, которые приводят к сбою редактора, а также поскольку написание кода C, который правильно взаимодействует со сборщиком мусора Emacs Lisp , подвержено ошибкам, количество функций, реализованных как примитивы сведено к необходимому минимуму.
Байт-код
[ редактировать ]Байт-компиляция может ускорить выполнение кода Emacs Lisp. Emacs содержит компилятор , который может транслировать исходные файлы Emacs Lisp в специальное представление, называемое байт-кодом . Файлы байт-кода Emacs Lisp имеют суффикс имени файла " .elc
«. По сравнению с исходными файлами файлы байт-кода загружаются и работают быстрее, занимают меньше места на диске и используют меньше памяти при загрузке.
Байт-код по-прежнему работает медленнее, чем примитивы, но функции, загруженные как байт-код, можно легко изменить и повторно загрузить. Кроме того, файлы байт-кода не зависят от платформы. Стандартный код Emacs Lisp, распространяемый вместе с Emacs, загружается как байт-код, хотя соответствующие исходные файлы обычно также предоставляются для справки пользователю. Расширения, предоставляемые пользователем, обычно не компилируются побайтно, поскольку они не такие большие и не требуют больших вычислительных ресурсов.
Особенности языка
[ редактировать ]Примечательно, что пакет «cl-lib» реализует довольно большое подмножество Common Lisp . Этот пакет заменяет более ранний пакет «cl», который перезаписывал существующие определения функций Emacs Lisp определениями, более похожими на те, которые находятся в Common Lisp. Пакет «cl-lib», с другой стороны, более точно следует рекомендациям по стилю Emacs Lisp и ставит перед каждой функцией и макросом префикс «cl-» (например, cl-defun
, который не конфликтует с именем встроенного defun
), избегая неожиданных изменений в поведении, которые могут произойти при загрузке пакета «cl».
Emacs Lisp (в отличие от некоторых других реализаций Lisp) не выполняет оптимизацию хвостовых вызовов . [ 10 ] Без этого хвостовая рекурсия может в конечном итоге привести к переполнению стека .
Библиотека apel помогает писать переносимый код Emacs Lisp с помощью моста платформы Polysylabi.
Emacs Lisp — это Lisp-2, подобный Common Lisp, что означает, что у него есть пространство имен функций, отдельное от пространства имен, которое он использует для других переменных. [ 11 ]
От динамического к лексическому обзору
[ редактировать ]Как и MacLisp, Emacs Lisp использует динамическую область видимости , предлагая в качестве опции статическую (или лексическую), начиная с версии 24. [ 12 ] Его можно активировать, установив локальную переменную файла. lexical-binding
. [ 13 ] [ 14 ] До того, как эта опция была добавлена, можно было использовать lexical-let
макрос из пакета «cl» (ныне устаревшего) для обеспечения эффективной лексической области видимости. [ 15 ]
При динамической области видимости, если программист объявляет переменную в области действия функции, она доступна подпрограммам, вызываемым из этой функции. Первоначально это было задумано как оптимизация ; лексическое определение все еще было редкостью и имело неопределенную эффективность. По воспоминаниям ученого-компьютерщика Олина Шиверса: «Я спросил RMS, когда он реализовал emacs lisp, почему он имеет динамическую область видимости, и его точный ответ заключался в том, что лексическая область видимости слишком неэффективна». [ 16 ] Динамическая область видимости также была предназначена для обеспечения большей гибкости пользовательской настройки. Однако динамическая область видимости имеет ряд недостатков. Во-первых, это может легко привести к ошибкам в больших программах из-за непреднамеренного взаимодействия переменных в разных функциях. Во-вторых, доступ к переменным при динамической области видимости обычно происходит медленнее, чем при лексической области видимости. [ 17 ]
См. также
[ редактировать ]Ссылки
[ редактировать ]- ^ «Байт-компиляция Emacs Lisp» . Руководство по GNU Emacs . Проверено 14 июня 2024 г.
- ^ «Компиляция Emacs Lisp в собственный код» . Руководство по GNU Emacs . Проверено 14 июня 2024 г.
- ^ «ХЕДРИК в РУТГЕРСЕ (руководитель DEC-20/Dir LCSR Comp Facility» (1981-12-18). « Информация о реализации Common Lisp» » . Письмо «rpg в SU-AI, jonl в MIT-AI». Архивировано . из оригинала 20 сентября 2016 г. Проверено 28 июля 2019 г. Сейчас
у нас есть некоторый опыт реализации Lisp, поскольку Elisp (расширенная реализация Rutgers/UCI Lisp) по существу завершена.
{{cite press release}}
: CS1 maint: числовые имена: список авторов ( ссылка ) - ^ «Реклама CCA EMACS». Обзор Юникс . Декабрь 1984 г. с. 16.
CCA EMACS и Elisp являются товарными знаками CCA Uniworks, Inc.
- ^ «GNU Emacs Lisp во многом вдохновлен Maclisp и немного Common Lisp. Если вы знаете Common Lisp, вы заметите много общего. Однако многие функции Common Lisp были опущены или упрощены, чтобы уменьшить требования к памяти. GNU Emacs Иногда упрощения настолько радикальны, что пользователь Common Lisp может прийти в замешательство. Время от времени мы будем указывать, чем GNU Emacs Lisp отличается от Common Lisp». – из раздела «История» «Введения» в руководство по Emacs Lisp, начиная с Emacs 21.
- ^ «Итак, разработка этой операционной системы, операционной системы GNU, побудила меня написать GNU Emacs. При этом я стремился создать абсолютно минимально возможную реализацию Lisp. Размер программ вызывал огромную озабоченность. В те времена, в 1985 году, были люди, у которых были машины с объемом памяти в один мегабайт и без виртуальной памяти. Они хотели иметь возможность использовать GNU Emacs. Это означало, что мне приходилось делать программу как можно меньше». – из «Мой опыт работы с Lisp и разработка GNU Emacs»
- ^ «Re: [Emacs-diffs] /srv/bzr/emacs/trunk r111086: gmm-utils.el (gmm-flet» . Lists.gnu.org. 05 декабря 2012 г. Проверено 18 августа 2013 г. .
- ^ «ВЕСТИ.24.4» .
- ^ «Портирование старых советов» .
- ^ «Приложение C. Портирование Common Lisp» . Gnu.org . Проверено 28 октября 2019 г.
Программистам Lisp следует отметить, что текущий компилятор Emacs Lisp не оптимизирует хвостовую рекурсию.
- ^ «Группы Google» . groups.google.com .
- ^ «Выпущен Emacs 24.1» . Lists.gnu.org . Проверено 18 августа 2013 г.
- ^ «Лексическая привязка» . Lists.gnu.org. 01 апреля 2011 г. Проверено 18 августа 2013 г.
- ^ «Динамическая привязка против лексической привязки» . ЭмаксВики. 17 мая 2013 г. Проверено 18 августа 2013 г.
- ^ «Устаревшая лексическая привязка» . Эмуляция GNU Emacs Common Lisp . ГНУ Пресс . Проверено 27 мая 2021 г.
- ^ «Т» . People.csail.mit.edu . Проверено 18 августа 2013 г.
- ^ Фезерстон, Сэм; Винклер, Сюзанна (2 июня 2009 г.). Процесс . Вальтер де Грютер. ISBN 978-3-11-021614-1 .
Внешние ссылки
[ редактировать ]- Официальный сайт проекта GNU