Aquí podría ser tu PUBLICIDAD


¿Hasta dónde pueden llegar las macros LISP?

votos
43

He leído mucho que LISP puede redefinir la sintaxis sobre la marcha, presumiblemente con macros. Tengo curiosidad de cuánto va esto realmente? ¿Se puede redefinir la estructura del lenguaje tanto que se convierta en un compilador para otro idioma? Por ejemplo, ¿podría cambiar la naturaleza funcional de LISP en una sintaxis y semántica más orientadas a objetos, tal vez decir tener una sintaxis más cercana a algo como Ruby?

Especialmente, ¿es posible deshacerse del paréntesis infierno usando macros? Aprendí lo suficiente (Emacs-) LISP para personalizar Emacs con mis propias micro-características, pero estoy muy curioso de lo lejos que pueden llegar las macros en la personalización del lenguaje.

Publicado el 05/08/2008 a las 08:32
fuente por usuario Mike Stone
En otros idiomas...        العربية       

14 respuestas

votos
33

Esa es una muy buena pregunta.

Creo que es matizado, pero definitivamente responde:

Las macros no están atrapadas en s-expressions. Vea la macro LOOP para un lenguaje muy complejo escrito usando palabras clave (símbolos). Entonces, aunque puede comenzar y terminar el ciclo con paréntesis, dentro tiene su propia sintaxis.

Ejemplo:

(loop for x from 0 below 100
      when (even x)
      collect x)

Dicho esto, la mayoría de las macros simples simplemente usan s-expressions. Y estarías "atrapado" usándolos.

Pero las expresiones s, como Sergio ha respondido, comienzan a sentirse bien. La sintaxis se quita del camino y comienzas a codificar en el árbol de sintaxis.

En cuanto a las macros del lector, sí, podría concebiblemente escribir algo como esto:

#R{
      ruby.code.goes.here
  }

Pero necesitarías escribir tu propio analizador de sintaxis Ruby.

También puede imitar algunas de las construcciones Ruby, como bloques, con macros que compilan las construcciones Lisp existentes.

#B(some lisp (code goes here))

se traduciría a

(lambda () (some lisp (code goes here)))

Vea esta página para saber cómo hacerlo.

Respondida el 15/09/2008 a las 04:07
fuente por usuario Eric Normand


Aquí podría ser tu PUBLICIDAD


votos
20

Sí, puede redefinir la sintaxis para que Lisp se convierta en un compilador. Lo hace utilizando "Macros de lector", que son diferentes de las "Macros de compilador" normales en las que probablemente esté pensando.

Common Lisp tiene la función incorporada para definir una nueva sintaxis para que las macros del lector y lector procesen esa sintaxis. Este procesamiento se realiza en tiempo de lectura (que viene antes del tiempo de compilación o evaluación). Para obtener más información sobre la definición de macros de lector en Common Lisp, consulte Common Lisp Hyperspec: querrá leer Ch. 2, "Sintaxis" y Ch. 23, "Lector" . (Creo que Scheme tiene las mismas facilidades, pero no estoy tan familiarizado con eso - vea las fuentes de Scheme para el lenguaje de programación Arc ).

Como un simple ejemplo, supongamos que quieres que Lisp use llaves en vez de paréntesis. Esto requiere algo así como las siguientes definiciones de lector:

;; { and } become list delimiters, along with ( and ).
(set-syntax-from-char #\{ #\( )
(defun lcurly-brace-reader (stream inchar) ; this was way too easy to do.
  (declare (ignore inchar))
  (read-delimited-list #\} stream t))
(set-macro-character #\{ #'lcurly-brace-reader)

(set-macro-character #\} (get-macro-character #\) ))
(set-syntax-from-char #\} #\) )

;; un-lisp -- make parens meaningless
(set-syntax-from-char #\) #\] ) ; ( and ) become normal braces
(set-syntax-from-char #\( #\[ )

Le estás diciendo a Lisp que {es como a (y que} es como a). Luego, crea una función ( lcurly-brace-reader) a la que el lector llamará cada vez que vea un {, y usted utilizará set-macro-characterpara asignar esa función al {. Luego le dices a Lisp que (y) son como [y] (es decir, sin sintaxis significativa).

Otras cosas que podría hacer incluyen, por ejemplo, crear una nueva sintaxis de cadena o usar [y] para encerrar la notación in-fix y procesarla en S-expressions.

También puede ir más allá de esto, redefiniendo la sintaxis completa con sus propios macrocaracteres que desencadenarán acciones en el lector, por lo que el cielo realmente es el límite. Esta es solo una de las razones por las cuales Paul Graham y otros siguen diciendo que Lisp es un buen lenguaje para escribir un compilador.

Respondida el 16/09/2008 a las 08:28
fuente por usuario Sean Harrison

votos
16

No soy un experto Lisp, diablos, ni siquiera soy un programador de Lisp, pero después de un poco de experimentación con el lenguaje llegué a la conclusión de que después de un tiempo los paréntesis comienzan a ser 'invisibles' y comienzas a ver el código como tu quieres que sea Comienza a prestar más atención a las construcciones sintácticas que crea a través de s-exprs y macros, y menos a la forma léxica del texto de listas y paréntesis.

Esto es especialmente cierto si aprovecha un buen editor que ayuda con la indentación y la coloración de sintaxis (intente configurar los paréntesis en un color muy similar al fondo).

Es posible que no pueda reemplazar el idioma por completo y obtener la sintaxis 'Ruby', pero no lo necesita. Gracias a la flexibilidad del idioma, puede terminar teniendo un dialecto que parezca seguir el "estilo Ruby de programación" si lo desea, sea lo que sea que eso signifique para usted.

Sé que esto es solo una observación empírica, pero creo que tuve uno de esos momentos de iluminación Lisp cuando me di cuenta de esto.

Respondida el 26/08/2008 a las 10:49
fuente por usuario Sergio Acosta

votos
15

Una y otra vez, los recién llegados a Lisp quieren "deshacerse de todos los paréntesis". Dura unas pocas semanas. Ningún proyecto para construir una sintaxis seria de programación de propósito general sobre el analizador de expresiones S habitual llega a ninguna parte, porque invariablemente los programadores terminan prefiriendo lo que actualmente perciben como "infierno de paréntesis". ¡Lleva un tiempo acostumbrarse, pero no mucho! Una vez que te acostumbras, y realmente puedes apreciar la plasticidad de la sintaxis predeterminada, volviendo a los idiomas donde hay una sola forma de expresar cualquier construcción de programación en particular es realmente gratificante.

Dicho esto, Lisp es un excelente sustrato para construir idiomas específicos de dominio. Tan bueno como, si no mejor que, XML.

¡Buena suerte!

Respondida el 16/09/2008 a las 08:29
fuente por usuario jfm3

votos
12

La mejor explicación de las macros Lisp que he visto es en

https://www.youtube.com/watch?v=4NO83wZVT0A

comenzando aproximadamente a los 55 minutos. Este es un video de una charla dada por Peter Seibel, el autor de "Practical Common Lisp", que es el mejor libro de texto de Lisp que existe.

La motivación para las macros de Lisp suele ser difícil de explicar, porque realmente se desarrollan en situaciones que son demasiado largas para presentarse en un simple tutorial. Peter viene con un gran ejemplo; puedes agarrarlo por completo y hace un buen uso de las macros Lisp.

Usted preguntó: "podría cambiar la naturaleza funcional de LISP en una sintaxis y semántica más orientada a objetos". La respuesta es sí. De hecho, Lisp originalmente no tenía ninguna programación orientada a objetos en absoluto, ¡no es sorprendente ya que Lisp ha existido desde mucho antes de la programación orientada a objetos! Pero cuando descubrimos por primera vez acerca de OOP en 1978, pudimos agregarlo fácilmente a Lisp, usando, entre otras cosas, macros. Eventualmente se desarrolló el Sistema de Objetos Common Lisp (CLOS), un sistema de programación orientado a objetos muy poderoso que encaja elegantemente en Lisp. Todo se puede cargar como una extensión: ¡nada está incorporado! Todo está hecho con macros.

Lisp tiene una característica completamente diferente, llamada "macros de lector", que se puede usar para extender la sintaxis de la superficie del lenguaje. Usando macros de lector, puede hacer sublenguajes que tengan sintaxis similar a C o Ruby. Transforman el texto en Lisp, internamente. Estos no son ampliamente utilizados por la mayoría de los programadores reales de Lisp, principalmente porque es difícil ampliar el entorno de desarrollo interactivo para comprender la nueva sintaxis. Por ejemplo, los comandos de sangría de Emacs se confundirían con una nueva sintaxis. Sin embargo, si eres enérgico, Emacs también es extensible y podrías enseñarle acerca de tu nueva sintaxis léxica.

Respondida el 05/10/2008 a las 04:03
fuente por usuario Dan Weinreb

votos
11

Las macros regulares operan en listas de objetos. Más comúnmente, estos objetos son otras listas (formando así árboles) y símbolos, pero pueden ser otros objetos como cadenas, tablas hash, objetos definidos por el usuario, etc. Estas estructuras se llaman s-exps .

Entonces, cuando cargas un archivo fuente, tu compilador Lisp analizará el texto y producirá s-exps. Las macros operan en estos. Esto funciona muy bien y es una forma maravillosa de extender el lenguaje dentro del espíritu de s-exps.

Además, el proceso de análisis mencionado anteriormente puede extenderse a través de "macros de lector" que le permiten personalizar la forma en que su compilador convierte el texto en s-exps. Sugiero, sin embargo, que abracen la sintaxis de Lisp en lugar de doblarla en otra cosa.

Suena un poco confundido cuando menciona la "naturaleza funcional" de Lisp y la "sintaxis orientada a objetos" de Ruby. No estoy seguro de qué se supone que es la "sintaxis orientada a objetos", pero Lisp es un lenguaje multi-paradigma y soporta extremadamente bien la programación orientada a objetos .

Por cierto, cuando digo Lisp, me refiero a Common Lisp .

Sugiero que alejes tus prejuicios y le des a Lisp una respuesta honesta .

Respondida el 26/08/2008 a las 10:36
fuente por usuario Luís Oliveira

votos
9

Lo que estás preguntando es algo así como preguntar cómo convertirte en un chocolatero experto para que puedas eliminar todas esas cosas marrones infernales de tu pastel de chocolate favorito.

Respondida el 17/09/2008 a las 01:14
fuente por usuario user15700

votos
9

¿Paréntesis infierno? No veo más paréntesis en:

(function toto)

que en:

function(toto);

Y en

(if tata (toto)
  (titi)
  (tutu))

no más que en:

if (tata)
  toto();
else
{
  titi();
  tutu();
}

Veo menos corchetes y ';' aunque.

Respondida el 16/09/2008 a las 05:23
fuente por usuario Jerry Cornelius

votos
6

Sí, puedes cambiar fundamentalmente la sintaxis e incluso escapar de "el paréntesis del infierno". Para eso, necesitará definir una nueva sintaxis de lector. Mire las macros de los lectores.

Sin embargo, sospecho que para alcanzar el nivel de experiencia de Lisp para programar tales macros tendrá que sumergirse en el lenguaje a tal punto que ya no considerará parenthese "infierno". Es decir, cuando sepa cómo evitarlos, habrá aceptado que son buenos.

Respondida el 15/09/2008 a las 01:07
fuente por usuario HD.

votos
2

vea este ejemplo de cómo las macros de lector pueden extender el lector de lisp con tareas complejas como plantillas XML:

http://common-lisp.net/project/cl-quasi-quote/present-class.html

esta biblioteca de usuario compila las partes estáticas del XML en matrices de bytes literales codificadas en UTF-8 en tiempo de compilación que están listas para ser secuenciadas de escritura en el flujo de red. y son utilizables en macros de lisp normales, son ortogonales ... la ubicación del carácter de coma influye en qué partes son constantes y cuáles deben evaluarse en tiempo de ejecución.

más detalles disponibles en: http://common-lisp.net/project/cl-quasi-quote/

otro proyecto que para las extensiones de sintaxis de Common Lisp: http://common-lisp.net/project/cl-syntax-sugar/

Respondida el 17/09/2008 a las 01:30
fuente por usuario Attila Lendvai

votos
2

Si quieres que el ceceo se parezca a Ruby usa Ruby.

Es posible usar Ruby (y Python) de una manera muy ceceante, que es una de las razones principales por las que han ganado aceptación tan rápidamente.

Respondida el 05/08/2008 a las 08:40
fuente por usuario sparkes

votos
1

Uno de los usos de las macros que me voló la mente fue la verificación en tiempo de compilación de las solicitudes SQL contra DB.

Una vez que se da cuenta de que tiene todo el lenguaje disponible en el momento de la compilación, abre nuevas perspectivas interesantes. Lo que también significa que puede dispararse en el pie de maneras nuevas e interesantes (como la compilación de renderización no reproducible, que puede convertirse fácilmente en una pesadilla de depuración).

Respondida el 19/09/2008 a las 11:43
fuente por usuario Nowhere man

votos
1

Es una pregunta difícil. Como lisp ya está estructuralmente tan cerca de un árbol de análisis, la diferencia entre un gran número de macros y la implementación de su propio mini lenguaje en un generador de analizador no es muy clara. Pero, a excepción del paréntesis de apertura y cierre, podrías terminar fácilmente con algo que no se parece al ceceo.

Respondida el 06/08/2008 a las 01:14
fuente por usuario John with waffle

votos
1

@sparkes

En ocasiones, LISP es la opción de idioma más clara, a saber, las extensiones de Emacs. Estoy seguro de que podría usar Ruby para extender Emacs si quisiera, pero Emacs fue diseñado para ser extendido con LISP, por lo que parece tener sentido usarlo en esa situación.

Respondida el 05/08/2008 a las 08:45
fuente por usuario Mike Stone


Aquí podría ser tu PUBLICIDAD