Логотип Emacs | |
Парадигма | Функциональный , мета , рефлексивный |
---|---|
Семья | Лисп |
Разработано | Ричард Столмен , Гай Л. Стил-младший |
Разработчик | Проект GNU |
Впервые появился | 1985 |
Стабильный выпуск | 26.2 / 12 апреля 2019 |
Печатная дисциплина | Динамичный , сильный |
Объем | Динамический, необязательно лексический |
Платформа | Emacs |
Операционные системы | Кроссплатформенность |
Лицензия | GPLv3 |
Расширения имени файла | .el, .elc |
Под влиянием | |
Общий Лисп , Маклисп |
Emacs Lisp является диалектом из языка программирования Lisp , используемого в качестве языка сценариев по Emacs (в редакторе текста семье наиболее часто связанный с GNU Emacs и XEmacs ). Он используется для реализации большинства функций редактирования, встроенных в Emacs, остальная часть написана на C , как и интерпретатор Лиспа . Emacs Lisp также называется Elisp , хотя существует также более старый, не связанный с ним диалект Lisp с этим именем. [1]
Пользователи Emacs обычно пишут код Emacs Lisp для настройки и расширения Emacs. Другие опции включают в себя функцию Customize, которая присутствует в GNU Emacs с версии 20. Сама по себе, написанная на Emacs Lisp, Customize предоставляет набор страниц настроек, позволяющих пользователю устанавливать опции и просматривать их эффект в текущем сеансе Emacs. Когда пользователь сохраняет свои изменения, Customize просто записывает необходимый код Emacs Lisp в файл конфигурации пользователя , который может быть установлен в специальный файл, который использует только Customize, чтобы избежать возможности изменения собственного файла пользователя.
Emacs Lisp также может функционировать как язык сценариев , во многом как оболочка Unix Bourne или Perl , вызывая Emacs в пакетном режиме . Таким образом, он может быть вызван из командной строки или через исполняемый файл, а его функции редактирования, такие как буферы и команды перемещения, доступны программе так же, как и в нормальном режиме. Нет пользовательский интерфейс не будет представлен , когда Emacs запускается в пакетном режиме; он просто выполняет переданный сценарий и завершает работу, отображая любые выходные данные сценария.
По сравнению с другими диалектами Лиспа [ править ]
Emacs Lisp наиболее тесно связан с Maclisp с некоторым более поздним влиянием Common Lisp . [2] Он поддерживает императивные и функциональные методы программирования . Ричард Столмен выбрал Lisp в качестве языка расширения для своего переписывания Emacs (в оригинале использовался текстовый редактор и корректор (TECO) в качестве языка расширения) из-за его мощных функций, включая возможность обрабатывать функции как данные. Хотя стандарт Common Lisp еще не был сформулирован, Scheme существовала в то время, когда Столлман переписывал Gosling Emacs.в GNU Emacs. Он решил не использовать его из-за его сравнительно низкой производительности на рабочих станциях (в отличие от мини-компьютеров, которые были традиционным домом Emacs), и он хотел разработать диалект, который, по его мнению, было бы легче оптимизировать. [3]
Диалект Lisp, используемый в Emacs, существенно отличается от более современных диалектов Common Lisp и Scheme, используемых для программирования приложений. Отличительной особенностью Emacs Lisp является использование динамической, а не лексической области видимости по умолчанию (см. Ниже). То есть функция может ссылаться на локальные переменные в области, из которой она вызывается, но не в области, в которой она была определена.
1955 г. | 1960 г. | 1965 г. | 1970 г. | 1975 г. | 1980 г. | 1985 г. | 1990 г. | 1995 г. | 2000 г. | 2005 г. | 2010 г. | 2015 г. | 2020 г. | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
LISP 1, 1.5, LISP 2 (заброшен) | ||||||||||||||
Маклисп | ||||||||||||||
Интерлисп | ||||||||||||||
Лисп-машина Лисп | ||||||||||||||
Схема | R5RS | R6RS | R7RS маленький | |||||||||||
Ноль | ||||||||||||||
Ференц Лисп | ||||||||||||||
Common Lisp | ||||||||||||||
Le Lisp | ||||||||||||||
Т | ||||||||||||||
Chez Scheme | ||||||||||||||
Emacs Lisp | ||||||||||||||
AutoLISP | ||||||||||||||
ПикоЛисп | ||||||||||||||
EuLisp | ||||||||||||||
ISLISP | ||||||||||||||
OpenLisp | ||||||||||||||
Схема PLT | Ракетка | |||||||||||||
GNU Guile | ||||||||||||||
Визуальный LISP | ||||||||||||||
Clojure | ||||||||||||||
Дуга | ||||||||||||||
LFE | ||||||||||||||
Hy |
Пример [ править ]
Чтобы понять логику 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 () ( интерактивный ) ( разделить-окно-ниже ) ( установить-окно-буфер ( следующее-окно ) ( другой-буфер )))( global-set-key "\ C-x2" 'my-split-window-func )
Первый оператор (defun ...)
,, определяет новую функцию, my-split-window-func
которая вызывает split-window-below
(старую функцию разделения окон), а затем сообщает новому окну отображать другой (новый) буфер. Второй оператор (global-set-key ...)
повторно связывает последовательность клавиш «Cx 2» с новой функцией.
Это также можно написать с помощью функции, называемой advice , которая позволяет пользователю создавать оболочки для существующих функций вместо определения своих собственных. Это имеет то преимущество, что не требует изменения сочетаний клавиш и работает везде, где вызывается исходная функция, а также его проще писать, но недостатком является усложнение отладки. По этой причине совет не разрешен в исходном коде GNU Emacs [4], но, если пользователь желает, функция совета может быть использована в его коде для повторной реализации приведенного выше кода следующим образом:
( defadvice split-window-below ( после my-window-splitting-advice first () активировать ) ( set-window-buffer ( next-window ) ( other-buffer )))
Это дает указание split-window-below
выполнять предоставленный пользователем код всякий раз, когда он вызывается, перед выполнением остальной части функции. Совет также можно указать для выполнения после исходной функции, вокруг нее - буквально обертывая исходную функцию, или для условного выполнения исходной функции на основе результатов рекомендации.
Emacs 24.4 заменяет [5] этот defadvice
механизм advice-add
на более гибкий и простой. [6] Приведенный выше совет можно было бы повторно реализовать, используя новую систему, как:
( defun switch-to-next-window-in-split () ( установить-буфер -окно ( следующее-окно ) ( другой-буфер )))( advice-add 'split-window-below : before #' переключить-на-следующее-окно-в-разделении )
Эти изменения вступят в силу, как только код будет оценен . Нет необходимости перекомпилировать, перезапускать Emacs или даже повторно хэшировать файл конфигурации. Если код сохранен в файле инициализации Emacs, то Emacs загрузит расширение при следующем запуске. В противном случае изменения должны быть повторно оценены вручную при перезапуске Emacs.
Исходный код [ править ]
Код Emacs Lisp хранится в файловых системах в виде простых текстовых файлов, по соглашению с суффиксом имени файла " .el ". Файл инициализации пользователя является исключением, часто отображается как " .emacs ", несмотря на то, что он оценивается как любой код Emacs Lisp. Последние версии Emacs ( «недавно» в 40-летней программы означает примерно любой версии , выпущенной с середины 1990-х годов) также загрузить ~ / .emacs.el и ~ / .emacs.d / init.el . Кроме того, пользователи могут указать любой файл для загрузки в качестве файла конфигурации в командной строке или явно указать, что никакой файл конфигурации не должен загружаться. Когда файлы загружены, интерпретаторКомпонент программы Emacs читает и анализирует функции и переменные, сохраняя их в памяти. Затем они доступны для других функций редактирования и для пользовательских команд. Функции и переменные можно свободно изменять и переопределять без перезапуска редактора или перезагрузки файла конфигурации.
Для экономии времени и памяти большая часть функциональных возможностей Emacs загружается только при необходимости. Каждый набор дополнительных функций, поставляемых с Emacs, реализуется набором кода Emacs, который называется пакетом или библиотекой . Например, есть библиотека для выделения ключевых слов в исходном коде программы и библиотека для игры в тетрис . Каждая библиотека реализована с использованием одного или нескольких исходных файлов Emacs Lisp. Библиотеки могут определять один или несколько основных режимов для активации и управления их функциями.
Разработчики Emacs пишут определенные функции на C. Это примитивы , также называемые встроенными функциями или подгруппами . Хотя примитивы могут быть вызваны из кода 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" реализует довольно большое подмножество Common Lisp .
Emacs Lisp (в отличие от некоторых других реализаций Lisp) не выполняет оптимизацию хвостового вызова . [7] Без этого хвостовые рекурсии могут в конечном итоге привести к переполнению стека .
Библиотека apel помогает писать переносимый код Emacs Lisp с помощью моста платформы polysylabi.
Emacs Lisp - это Lisp-2, что означает, что у него есть пространство имен функций, которое отделено от пространства имен, которое он использует для других переменных. [8]
От динамической к лексической области видимости [ править ]
Как и MacLisp, Emacs Lisp использует динамическую область видимости , предлагая статическую (или лексическую) в качестве опции, начиная с версии 24. [9] Ее можно активировать, установив локальную переменную файла lexical-binding
. [10] [11]
В динамической области видимости, если программист объявляет переменную в рамках функции, она доступна для подпрограмм, вызываемых из этой функции. Первоначально это было задумано как оптимизация ; лексическая область видимости все еще была редкостью и неопределенной эффективностью. «Я спросил RMS, когда он реализовывал emacs lisp, почему у него динамическая область видимости, и он точно ответил, что лексическая область видимости слишком неэффективна». [12] Динамическое определение также должно было обеспечить большую гибкость для пользовательских настроек. Однако у динамической области видимости есть несколько недостатков. Во-первых, это может легко привести к ошибкам в больших программах из-за непреднамеренного взаимодействия между переменными в различных функциях. Во-вторых, доступ к переменным при динамической области видимости обычно медленнее, чем при лексической области видимости.[13]
Кроме того, lexical-let
макрос в пакете "cl" действительно обеспечивает эффективную лексическую область видимости для программистов Emacs Lisp, но, хотя "cl" широко используется, lexical-let
используется редко.
Ссылки [ править ]
- ^ "HEDRICK в RUTGERS (Mngr DEC-20's / Dir LCSR Comp Facility" (1981-12-18). " " Информация о реализации Common Lisp " " . Письмо "RPG в SU-AI, jonl в MIT-AI". Архивировано из оригинала на 2016-09-20 . Проверено 2019-07-28 . у
нас есть опыт реализации Лиспа в настоящее время, так как Elisp (расширенная реализация Рутгерса / UCI Лисп), по существу , закончена.
- ^ "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. Делая это, я стремился сделать абсолютно минимально возможную реализацию Лиспа. Размер программ вызывал огромную озабоченность. В те дни, в 1985 году, были люди, у которых были машины размером в один мегабайт без виртуальной памяти. Они хотели иметь возможность использовать GNU Emacs. Это означало, что я должен был сохранить программу как можно меньше ». - из "Мои впечатления от Lisp и разработка GNU Emacs"
- ^ "Re: [Emacs-дифференциалы] / SRV / BZR / Emacs / багажник r111086: гммы-utils.el (ГИМ-FLET" Lists.gnu.org 2012-12-05.. Проверено. 2013-08-18 .
- ^ «НОВОСТИ.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. 2011-04-01 . Проверено 18 августа 2013 .
- ^ «Динамическое связывание против лексического связывания» . EmacsWiki. 2013-05-17 . Проверено 18 августа 2013 .
- ^ "Т" . People.csail.mit.edu . Проверено 18 августа 2013 .
- ^ Featherston, Сэм; Винклер, Сюзанна (2009-06-02). Процесс . Вальтер де Грюйтер. ISBN 978-3-11-021614-1.
Внешние ссылки [ править ]
Викискладе есть медиафайлы по теме Emacs Lisp . |
- Официальный сайт , GNU Project