Emacs Lisp - Emacs Lisp

Emacs Lisp
EmacsIcon.svg
Логотип Emacs
ПарадигмаФункциональный, мета, отражающий
СемьяЛисп
РазработаноРичард Столмен,
Гай Л. Стил-младший.
РазработчикПроект GNU
Впервые появился1985; 35 лет назад (1985)
Стабильный выпуск
26.2 / 12 апреля 2019; 19 месяцев назад (2019-04-12)
Печатная дисциплинаДинамический, сильный
ОбъемДинамический, необязательно лексический
ПлатформаEmacs
Операционные системыКроссплатформенность
ЛицензияGPLv3
Расширения имени файла.el, .elc
Под влиянием
Common Lisp, Маклисп

Emacs Lisp это диалект из Язык программирования Лисп используется как язык сценариев к EmacsТекстовый редактор семья, чаще всего связанная с GNU Emacs и XEmacs ). Он используется для реализации большинства функций редактирования, встроенных в Emacs, остальная часть написана на C, как и Лисп устный переводчик. Emacs Lisp также называется Элисп, хотя есть также более старый, не связанный с этим диалект Лиспа.[1]

Пользователи Emacs обычно пишут код Emacs Lisp для настройки и расширения Emacs. Другие варианты включают Настроить функция, которая присутствует в GNU Emacs с версии 20. Сама написанная на Emacs Lisp, Customize предоставляет набор предпочтения страницы, позволяющие пользователю устанавливать параметры и просматривать их эффект в текущем сеансе Emacs. Когда пользователь сохраняет свои изменения, Customize просто записывает необходимый код Emacs Lisp пользователю. файл конфигурации, который может быть установлен в специальный файл, который использует только Customize, чтобы избежать возможности изменения собственного файла пользователя.

Emacs Lisp также может функционировать как язык сценариев, как и Unix Оболочка Борна или же Perl, вызвав Emacs в пакетный режим. Таким образом, он может быть вызван из командной строки или через исполняемый файл, а его функции редактирования, такие как буферы и команды перемещения, доступны программе так же, как и в обычном режиме. Нет пользовательский интерфейс отображается при запуске Emacs в пакетном режиме; он просто выполняет переданный сценарий и завершает работу, отображая любой вывод сценария.

По сравнению с другими диалектами Лиспа

Emacs Lisp наиболее тесно связан с Маклисп, с некоторым более поздним влиянием Common Lisp.[2] Он поддерживает императив и функциональное программирование методы. Ричард Столмен выбрал Lisp в качестве языка расширения для его переписывания Emacs (в оригинале использовался Текстовый редактор и корректор (TECO) в качестве языка расширения) из-за его мощных функций, включая способность обрабатывать функции как данные. Хотя стандарт Common Lisp еще не был сформулирован, Схема существовало в то время, когда Столлман переписывал Гослинг Emacs в GNU Emacs. Он решил не использовать его из-за его сравнительно низкой производительности на рабочих станциях (в отличие от миникомпьютеры это был традиционный дом Emacs), и он хотел разработать диалект, который, по его мнению, было бы легче оптимизировать.[3]

Диалект Лиспа, используемый в Emacs, существенно отличается от более современного Common Lisp и Схема диалекты, используемые для программирования приложений. Отличительной чертой Emacs Lisp является использование динамических, а не лексических объем по умолчанию (см. ниже). То есть функция может ссылаться на локальные переменные в той области видимости, из которой она вызывается, но не в той области, где она была определена.

Пример

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

Далее следует простой пример расширения Emacs, написанного на Emacs Lisp. В Emacs область редактирования можно разделить на отдельные области, называемые окна, каждый из которых отображает свой буфер. Буфер - это область текста, загруженная в память Emacs (возможно, из файла), которую можно сохранить в текстовый документ.

Пользователи могут нажать по умолчанию C-x 2 привязка клавиш чтобы открыть новое окно. Это запускает функцию Emacs Lisp разделенное окно-ниже. Обычно, когда появляется новое окно, оно отображает тот же буфер, что и предыдущее. Предположим, мы хотим, чтобы он отображал следующий доступный буфер. Для этого пользователь записывает следующий код Emacs Lisp либо в существующий исходный файл Emacs Lisp, либо в пустой буфер Emacs:

(defun моя функция разделения окна ()  (интерактивный)  (разделенное окно-ниже)  (установить-окно-буфер (следующее окно) (другой буфер)))(глобальный набор-ключ "C-x2" 'моя функция-разделенное окно )

Первое заявление, (определение ...), определяет новую функцию, моя функция разделения окна, который вызывает разделенное окно-ниже (старая функция разделения окон), затем сообщает новому окну отображать другой (новый) буфер. Второе утверждение, (глобальный набор-ключ ...) повторно связывает последовательность клавиш "C-x 2" с новой функцией.

Это также можно записать с помощью функции, называемой совет, что позволяет пользователю создавать обертки вокруг существующих функций вместо определения своих собственных. Это имеет то преимущество, что не требует изменения привязок клавиш и работает везде, где вызывается исходная функция, а также его проще писать, но недостатком является усложнение отладки. По этой причине, совет не допускается в исходном коде GNU Emacs,[4] но, если пользователь желает, функцию совета можно использовать в его коде для повторной реализации вышеуказанного кода следующим образом:

(дефект разделенное окно-ниже  (после мой-совет-разделение-окно первый () активировать)  (установить буфер окна (следующее окно) (другой буфер)))

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

Emacs 24.4 заменяет[5] это дефект механизм с совет-добавить, который считается более гибким и простым.[6] Приведенный выше совет можно было бы повторно реализовать, используя новую систему, как:

(defun переключиться на следующее окно в разделении ()  (установить-окно-буфер (следующее окно) (другой буфер)))(совет-добавить 'разделенное окно-ниже :перед #'переключиться на следующее окно в разделении)

Эти изменения вступают в силу, как только код оценен. Нет необходимости перекомпилировать, перезапускать 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. Это примитивы, также называемый встроенные функции или же 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" реализует довольно большое подмножество Common Lisp.

Emacs Lisp (в отличие от некоторых других реализаций Lisp) не делает оптимизация хвостового вызова.[7] Без этого хвостовые рекурсии может в конечном итоге привести к переполнение стека.

В обезьяна Библиотека помогает в написании переносимого кода Emacs Lisp с помощью моста платформы polysylabi.

Emacs Lisp - это Лисп-2 Это означает, что у него есть пространство имен функции, которое отделено от пространства имен, которое оно использует для других переменных.[8]

От динамического к лексическому обзору

Как и MacLisp, Emacs Lisp использует динамические объем, предлагая статические (или лексические) в качестве опции, начиная с версии 24.[9] Его можно активировать, установив локальную переменную файла лексическая привязка.[10][11]

В динамической области видимости, если программист объявляет переменную в рамках функции, она доступна для подпрограмм, вызываемых из этой функции. Первоначально это было задумано как оптимизация; лексическая область видимости по-прежнему была редкостью и имела неопределенную эффективность. «Я спросил RMS, когда он реализовывал emacs lisp, почему у него динамическая область видимости, и его точный ответ заключался в том, что лексическая область видимости была слишком неэффективной».[12] Динамическое определение также предназначено для обеспечения большей гибкости для пользовательских настроек. Однако динамическое определение области имеет несколько недостатков. Во-первых, это может легко привести к ошибкам в больших программах из-за непреднамеренного взаимодействия между переменными в различных функциях. Во-вторых, доступ к переменным при динамической области видимости обычно медленнее, чем при лексической области видимости.[нужна цитата ]

Так же лексический Макрос в пакете "cl" действительно обеспечивает эффективную лексическую область видимости для программистов Emacs Lisp, но хотя "cl" широко используется, лексический используется редко.

Рекомендации

  1. ^ "HEDRICK в RUTGERS (Mngr DEC-20's / Dir LCSR Comp Facility" (1981-12-18). ""информация о реализации Common Lisp"". Письмо в "RPG в SU-AI, младший в MIT-AI". В архиве из оригинала от 20.09.2016. Получено 2019-07-28. У нас есть некоторый опыт реализации Lisp, поскольку Elisp (расширенная реализация Rutgers / UCI Lisp) по существу закончен.
  2. ^ "GNU Emacs Lisp во многом вдохновлен Маклисп, и немного Common Lisp. Если вы знаете Common Lisp, вы заметите много общего. Однако многие функции Common Lisp были опущены или упрощены, чтобы уменьшить требования к памяти для GNU Emacs. Иногда упрощения настолько радикальны, что пользователь Common Lisp может сильно запутаться. Время от времени мы будем указывать, чем GNU Emacs Lisp отличается от Common Lisp. »- из раздела« История »« Введение »к Руководству по Emacs Lisp, начиная с Emacs 21
  3. ^ «Итак, разработка этой операционной системы, операционной системы GNU, привела меня к написанию GNU Emacs. Делая это, я стремился сделать минимально возможную реализацию Lisp. Размер программ вызывал огромную озабоченность. В те дни, в 1985 году, были люди, у которых были машины размером в один мегабайт без виртуальной памяти. Они хотели иметь возможность использовать GNU Emacs. Это означало, что я должен был сохранить программу как можно меньше ". - из «Мои впечатления от Lisp и разработка GNU Emacs»
  4. ^ "Re: [Emacs-diffs] / srv / bzr / emacs / trunk r111086: gmm-utils.el (gmm-flet". Lists.gnu.org. 2012-12-05. Получено 2013-08-18.
  5. ^ «НОВОСТИ.24.4».
  6. ^ «Перенос старых советов».
  7. ^ "Приложение C Перенос Common Lisp". Gnu.org. Получено 2019-10-28. Программисты Lisp захотят отметить, что текущий компилятор Emacs Lisp не оптимизирует хвостовую рекурсию.
  8. ^ "Группы Google". groups.google.com.
  9. ^ "Выпущен Emacs 24.1". Lists.gnu.org. Получено 2013-08-18.
  10. ^ «Лексическая привязка». Lists.gnu.org. 2011-04-01. Получено 2013-08-18.
  11. ^ «Динамическое связывание против лексического связывания». EmacsWiki. 2013-05-17. Получено 2013-08-18.
  12. ^ "Т". People.csail.mit.edu. Получено 2013-08-18.

внешняя ссылка