stringtranslate.com

Emacs Lisp

Emacs Lisp es un dialecto de Lisp creado para Emacs . Se utiliza para implementar la mayor parte de la funcionalidad de edición integrada en Emacs; el resto está escrito en C , al igual que el intérprete de Lisp .

El código Lisp de Emacs se utiliza para modificar, ampliar y personalizar Emacs. Aquellos que no quieran escribir el código ellos mismos pueden utilizar la función Customize. Proporciona un conjunto de páginas de preferencias que permiten al usuario configurar opciones y obtener una vista previa de su efecto en la sesión de Emacs en ejecución. Cuando el usuario guarda sus cambios, Customize simplemente escribe el código Lisp de Emacs necesario en el archivo de configuración del usuario , que puede configurarse en un archivo especial que solo utiliza Customize, para evitar la posibilidad de alterar el archivo propio del usuario.

Además de ser un lenguaje de programación que puede compilarse en bytecode [1] y transcompilarse en código nativo , [2] Emacs Lisp también puede funcionar como un lenguaje de script interpretado , al igual que el shell Bourne de Unix o Perl , al llamar a Emacs en modo por lotes . De esta manera, se puede llamar desde la línea de comandos o mediante un archivo ejecutable, y sus funciones de edición, como los búferes y los comandos de movimiento, están disponibles para el programa al igual que en el modo normal. No se presenta ninguna interfaz de usuario cuando Emacs se inicia en modo por lotes; simplemente ejecuta el script pasado y sale, mostrando cualquier salida del script.

Emacs Lisp también se denomina Elisp , aunque también existen dialectos Lisp más antiguos y no relacionados con ese nombre. [3] [4]

En comparación con otros dialectos de Lisp

Emacs Lisp está más estrechamente relacionado con Maclisp , con alguna influencia posterior de Common Lisp . [5] Admite métodos de programación imperativos y funcionales . Lisp fue el lenguaje de extensión predeterminado para los derivados de Emacs como EINE y ZWEI . Cuando Richard Stallman bifurcó Gosling Emacs en GNU Emacs, también eligió Lisp como lenguaje de extensión, debido a sus potentes características, incluida la capacidad de tratar las funciones como datos. Aunque el estándar Common Lisp aún no se había formulado, Scheme existía en ese momento, pero Stallman decidió no usarlo debido a su rendimiento comparativamente pobre en estaciones de trabajo (a diferencia de las minicomputadoras que eran el hogar tradicional de Emacs), y quería desarrollar un dialecto que pensaba que se optimizaría más fácilmente. [6]

El dialecto Lisp utilizado en Emacs difiere sustancialmente de los dialectos más modernos Common Lisp y Scheme utilizados para la programación de aplicaciones. Una característica destacada de Emacs Lisp es el uso de un ámbito dinámico en lugar de léxico por defecto. Es decir, una función puede hacer referencia a variables locales en el ámbito desde el que se llama, pero no en el ámbito en el que se definió. Recientemente, se ha realizado un esfuerzo continuo para actualizar el código para utilizar el ámbito léxico, por las razones que se describen a continuación.

Ejemplo

El desarrollo de Emacs Lisp se guió por el objetivo de proporcionar estructuras de datos y características específicas para crear un editor de texto versátil en lugar de implementar un lenguaje de programación de propósito general. Por ejemplo, Emacs Lisp no puede leer fácilmente un archivo línea por línea; se debe leer el archivo completo en un búfer de Emacs. Sin embargo, Emacs Lisp proporciona muchas características para navegar y modificar el texto del búfer en una oración, párrafo o nivel sintáctico superior, según lo definido por los modos.

A continuación se muestra un ejemplo sencillo de una extensión de Emacs escrita en Emacs Lisp. En Emacs, el área de edición se puede dividir en áreas independientes llamadas ventanas , cada una de las cuales muestra un búfer diferente . Un búfer es una región de texto cargada en la memoria de Emacs (posiblemente desde un archivo) que se puede guardar en un documento de texto.

Los usuarios pueden presionar la C-x 2 combinación de teclas predeterminada para abrir una nueva ventana. Esto ejecuta la función Emacs Lisp split-window-below. Normalmente, cuando aparece la nueva ventana, muestra el mismo búfer que la anterior. Supongamos que deseamos que muestre el siguiente búfer disponible. Para hacer esto, el usuario escribe el siguiente código Emacs Lisp, ya sea en un archivo fuente de Emacs Lisp existente o en un búfer de Emacs vacío:

( defun my-split-window-func () ( interactivo ) ( dividir-ventana-abajo ) ( establecer-buffer-de-ventana ( siguiente-ventana ) ( otro-buffer )))       ( clave-conjunto-global ( kbd "Cx 2" ) #' mi-función-ventana-dividida )   

La primera instrucción, (defun ...), define una nueva función, my-split-window-func, que llama split-window-below(a la antigua función de división de ventanas) y luego le indica a la nueva ventana que muestre otro (nuevo) búfer. La segunda instrucción, (global-set-key ...)vuelve a vincular la secuencia de teclas "Cx 2" a la nueva función.

Esto también se puede escribir utilizando la característica llamada advice , que permite al usuario crear contenedores alrededor de funciones existentes en lugar de definir las suyas propias. Esto tiene la ventaja de no requerir que se cambien las combinaciones de teclas y de funcionar donde sea que se llame a la función original, además de ser más simple de escribir, pero tiene la desventaja de hacer que la depuración sea más complicada. Por esta razón, advice no está permitido en el código fuente de GNU Emacs, [7] pero si un usuario lo desea, la característica advice se puede utilizar en su código para reimplementar el código anterior de la siguiente manera:

( defadvice split-window-below ( después de mi-consejo-de-división-de-ventana primero () activar ) ( set-window-buffer ( siguiente-ventana ) ( otro-buffer )))         

Esto indica split-window-belowque se debe ejecutar el código proporcionado por el usuario cada vez que se lo llama, después de ejecutar el resto de la función. También se puede especificar que el consejo se ejecute antes de la función original, alrededor de ella (literalmente envolviendo la original) o que se ejecute condicionalmente la función original en función de los resultados del consejo.

Emacs 24.4 reemplaza [8] este defadvicemecanismo con advice-add, que se afirma que es más flexible y simple. [9] El consejo anterior podría volver a implementarse utilizando el nuevo sistema como:

( defun cambiar-a-la-siguiente-ventana-en-división () ( establecer-buffer-de-ventana ( siguiente-ventana ) ( otro-buffer )))     ( consejo-agregar 'ventana-dividida-abajo :antes #' cambiar-a-la-siguiente-ventana-en-la-división )   

Estos cambios surten efecto tan pronto como se evalúa el código . No es necesario volver a compilar, reiniciar Emacs o incluso volver a crear un archivo de configuración. Si el código se guarda en un archivo de inicio de Emacs, Emacs cargará la extensión la próxima vez que se inicie. De lo contrario, los cambios deben volver a evaluarse manualmente cuando se reinicie Emacs.

Código fuente

El código Emacs Lisp se almacena en sistemas de archivos como archivos de texto sin formato , por convención con el sufijo de nombre de archivo " .el". El archivo init del usuario es una excepción, que a menudo aparece como " .emacs" a pesar de que se evalúa como cualquier código Emacs Lisp. Desde mediados de la década de 1990, Emacs también carga ~/.emacs.ely ~/.emacs.d/init.el. Además, los usuarios pueden especificar cualquier archivo para cargar como archivo de configuración en la línea de comandos, o indicar explícitamente que no se cargará ningún archivo de configuración. Cuando se cargan los archivos, un componente intérprete del programa Emacs lee y analiza las funciones y variables, almacenándolas en la memoria. Luego están disponibles para otras funciones de edición y para los comandos del usuario. Las funciones y variables se pueden modificar y redefinir libremente sin reiniciar el editor o recargar el archivo de configuración.

Para ahorrar tiempo y espacio de memoria, gran parte de la funcionalidad de Emacs se carga solo cuando es necesario. Cada conjunto de características opcionales que se entregan con Emacs se implementa mediante una colección de código de Emacs llamada paquete o biblioteca . Por ejemplo, hay una biblioteca para resaltar palabras clave en el código fuente del programa y una biblioteca para jugar al juego de Tetris . Cada biblioteca se implementa utilizando uno o más archivos fuente de Emacs Lisp. Las bibliotecas pueden definir uno o más modos principales para activar y controlar su función.

Los desarrolladores de Emacs escriben ciertas funciones en C. Estas son primitivas , también llamadas funciones integradas o subrs . Aunque las primitivas se pueden llamar desde el código Lisp, solo se pueden modificar editando los archivos fuente de C y recompilando. En GNU Emacs , las primitivas no están disponibles como bibliotecas externas; son parte del ejecutable de Emacs. En XEmacs , es posible cargar en tiempo de ejecución dichas primitivas, utilizando el soporte del sistema operativo para el enlace dinámico . Las funciones se pueden escribir como primitivas porque necesitan acceso a datos externos y bibliotecas que de otra manera no están disponibles desde Emacs Lisp, o porque se las llama con la suficiente frecuencia como para que la velocidad comparativa de C frente a Emacs Lisp marque una diferencia que valga la pena.

Sin embargo, debido a que los errores en el código C pueden conducir fácilmente a violaciones de segmentación o a errores más sutiles que hacen que el editor se caiga, y debido a que escribir código C que interactúe correctamente con el recolector de basura Emacs Lisp es propenso a errores, la cantidad de funciones implementadas como primitivas se mantiene al mínimo necesario.

Código de bytes

La compilación de bytes puede hacer que el código de Emacs Lisp se ejecute más rápido. Emacs contiene un compilador que puede traducir los archivos fuente de Emacs Lisp a una representación especial denominada bytecode . Los archivos de bytecode de Emacs Lisp tienen el sufijo de nombre de archivo " .elc". En comparación con los archivos fuente, los archivos de bytecode se cargan y se ejecutan más rápido, ocupan menos espacio en disco y usan menos memoria cuando se cargan.

El código de bytes todavía se ejecuta más lentamente que los primitivos, pero las funciones cargadas como código de bytes se pueden modificar y volver a cargar fácilmente. Además, los archivos de código de bytes son independientes de la plataforma. El código estándar de Emacs Lisp distribuido con Emacs se carga como código de bytes, aunque los archivos fuente correspondientes generalmente también se proporcionan como referencia para el usuario. Las extensiones proporcionadas por el usuario generalmente no se compilan en bytes, ya que no son tan grandes ni requieren tantos cálculos.

Características del lenguaje

Cabe destacar que el paquete "cl-lib" implementa un subconjunto bastante grande de Common Lisp . Este paquete reemplaza un paquete "cl" anterior, que sobrescribía las definiciones de funciones de Emacs Lisp existentes con otras más similares a las que se encuentran en Common Lisp. El paquete "cl-lib", por otro lado, sigue las pautas de estilo de Emacs Lisp más de cerca y antepone "cl-" a cada función y macro que define (por ejemplo, cl-defun, que no entra en conflicto con el nombre de la función incorporada defun), evitando los cambios inesperados en el comportamiento que podrían ocurrir siempre que se cargara el paquete "cl".

Emacs Lisp (a diferencia de otras implementaciones de Lisp) no realiza optimización de llamadas de cola . [10] Sin esto, las recursiones de cola pueden eventualmente conducir a un desbordamiento de pila .

La biblioteca apel ayuda a escribir código Emacs Lisp portátil, con la ayuda del puente de plataforma polysylabi.

Emacs Lisp es un Common Lisp similar a Lisp-2 , lo que significa que tiene un espacio de nombres de funciones que está separado del espacio de nombres que utiliza para otras variables. [11]

Del alcance dinámico al léxico

Al igual que MacLisp, Emacs Lisp utiliza un alcance dinámico , ofreciendo un alcance estático (o léxico) como opción a partir de la versión 24. [12] Se puede activar configurando la variable local del archivo lexical-binding. [13] [14] Antes de que se añadiera esta opción, se podía usar la lexical-letmacro del paquete "cl" (ahora obsoleto) para proporcionar un alcance léxico efectivo. [15]

En el ámbito dinámico, si un programador declara una variable dentro del ámbito de una función, está disponible para las subrutinas llamadas desde dentro de esa función. Originalmente, esto fue pensado como una optimización ; el ámbito léxico todavía era poco común y de rendimiento incierto. En el recuerdo del científico informático Olin Shivers, "le pregunté a RMS cuando estaba implementando emacs lisp por qué tenía un ámbito dinámico y su respuesta exacta fue que el ámbito léxico era demasiado ineficiente". [16] El ámbito dinámico también fue pensado para proporcionar una mayor flexibilidad para las personalizaciones del usuario. Sin embargo, el ámbito dinámico tiene varias desventajas. En primer lugar, puede conducir fácilmente a errores en programas grandes, debido a interacciones no deseadas entre variables en diferentes funciones. En segundo lugar, acceder a las variables bajo el ámbito dinámico es generalmente más lento que bajo el ámbito léxico. [17]

Véase también

Referencias

  1. ^ "Compilación de bytes de Emacs Lisp". Manual de GNU Emacs . Consultado el 14 de junio de 2024 .
  2. ^ "Compilación de Emacs Lisp a código nativo". Manual de GNU Emacs . Consultado el 14 de junio de 2024 .
  3. ^ "HEDRICK en RUTGERS (Mngr DEC-20's/Dir LCSR Comp Facility" (1981-12-18). ""información sobre la implementación de Common Lisp"". Carta a "rpg en SU-AI, jonl en MIT-AI". Archivado desde el original el 2016-09-20 . Consultado el 28 de julio de 2019 . Ahora tenemos algo de experiencia en la implementación de Lisp, ya que Elisp (la implementación extendida de Rutgers/UCI Lisp) está esencialmente terminada.{{cite press release}}: CS1 maint: nombres numéricos: lista de autores ( enlace )
  4. ^ "Anuncio de CCA EMACS". Unix Review . Diciembre de 1984. pág. 16. CCA EMACS y Elisp son marcas comerciales de CCA Uniworks, Inc.
  5. ^ "GNU Emacs Lisp está inspirado en gran medida en Maclisp y un poco en Common Lisp. Si conoce Common Lisp, notará muchas similitudes. Sin embargo, se han omitido o simplificado muchas características de Common Lisp para reducir los requisitos de memoria de GNU Emacs. A veces, las simplificaciones son tan drásticas que un usuario de Common Lisp puede quedar muy confundido. Ocasionalmente señalaremos en qué se diferencia GNU Emacs Lisp de Common Lisp". – de la sección "Historia" de la "Introducción" al Manual de Emacs Lisp, a partir de Emacs 21
  6. ^ "Así que el desarrollo de ese sistema operativo, el sistema operativo GNU, es lo que me llevó a escribir GNU Emacs. Al hacerlo, mi objetivo era hacer la implementación de Lisp más mínima posible. El tamaño de los programas era una preocupación tremenda. Había gente en aquellos días, en 1985, que tenía máquinas de un megabyte sin memoria virtual. Querían poder usar GNU Emacs. Esto significaba que tenía que mantener el programa lo más pequeño posible". – de "Mis experiencias con Lisp y el desarrollo de GNU Emacs"
  7. ^ "Re: [Emacs-diffs] /srv/bzr/emacs/trunk r111086: gmm-utils.el (gmm-flet". Lists.gnu.org. 2012-12-05 . Consultado el 2013-08-18 .
  8. ^ "NOTICIAS.24.4".
  9. ^ "Portando viejos consejos".
  10. ^ "Apéndice C: Porting Common Lisp". Gnu.org . Consultado el 28 de octubre de 2019 . Los programadores de Lisp deben tener en cuenta que el compilador Emacs Lisp actual no optimiza la recursión de cola.
  11. ^ "Grupos de Google". groups.google.com .
  12. ^ "Emacs 24.1 publicado". Lists.gnu.org . Consultado el 18 de agosto de 2013 .
  13. ^ "Enlace léxico". Lists.gnu.org. 2011-04-01 . Consultado el 2013-08-18 .
  14. ^ "Enlace dinámico vs. enlace léxico". EmacsWiki. 2013-05-17 . Consultado el 2013-08-18 .
  15. ^ "Enlace léxico obsoleto". Emulación Common Lisp de GNU Emacs . GNU Press . Consultado el 27 de mayo de 2021 .
  16. ^ "T". People.csail.mit.edu . Consultado el 18 de agosto de 2013 .
  17. ^ Plumaston, Sam; Winkler, Susanne (2 de junio de 2009). Proceso. Walter de Gruyter. ISBN 978-3-11-021614-1.

Enlaces externos