tutorial resueltos recursivas principiantes para listas funciones ejercicios ejemplos datos lisp

resueltos - En Lisp, el código es datos. ¿Qué beneficio proporciona eso?



lisp tutorial (4)

Lisp ha sido desarrollado para la manipulación de datos simbólicos de todo tipo. Resulta que también se puede ver cualquier programa Lisp como datos simbólicos. Así que puedes aplicar las capacidades de manipulación de Lisp a sí mismo.

Si desea calcular con programas (para crear nuevos programas, compilar programas a código de máquina, traducir programas de Lisp a otros idiomas), tiene básicamente tres opciones:

  • usar cuerdas. Esto se vuelve tedioso al analizar y desentrañar cadenas todo el tiempo.

  • utilizar árboles de análisis. Útil pero se vuelve complejo.

  • Usa expresiones simbólicas como en Lisp. Los programas se preparan previamente en estructuras de datos familiares (listas, símbolos, cadenas, números, ...) y las rutinas de manipulación se escriben en la funcionalidad de lenguaje habitual proporcionada.

Entonces, ¿qué obtienes con Lisp? Una forma relativamente simple de escribir programas que manipulan otros programas. De macros a compiladores hay muchos ejemplos de esto. También obtienes que puedes incrustar idiomas en Lisp fácilmente.

En Lisp, el código de cualquier programa es en realidad una estructura de datos válida. Por ejemplo, esto agrega uno y dos juntos, pero también es una lista de tres elementos.

(+ 1 2)

¿Qué beneficio proporciona eso? ¿Qué le permite hacer eso que es imposible y / o menos elegante en otros idiomas?


Mi ejemplo favorito ... En la universidad, algunos amigos míos estaban escribiendo un compilador en Lisp. Así que todas sus estructuras de datos, incluido el árbol de análisis, eran expresiones-s lisp. Cuando llegó el momento de implementar la fase de generación de código, simplemente ejecutaron su árbol de análisis.


Para aclarar un poco más las cosas con respecto a la representación de códigos, tenga en cuenta que en todos los idiomas, los códigos son datos: todo lo que necesita son cadenas. (Y quizás algunas operaciones de archivo). Contemplar cómo eso te ayuda a imitar los beneficios de Lisp de tener un sistema macro es una buena manera de iluminarte. Aún mejor si intentas implementar un sistema macro similar. Se encontrará con las ventajas de tener una representación estructurada frente a la planeidad de las cadenas, la necesidad de ejecutar primero las transformaciones y definir "ganchos sintácticos" para decirle dónde aplicarlos, etc.

Pero lo principal que verá en todo esto es que las macros son esencialmente una instalación conveniente para los ganchos del compilador, que están enganchados a palabras clave recién creadas. Como tal, lo único que realmente se necesita es alguna forma de que el código de usuario interactúe con el código del compilador. Las cadenas planas son una forma de hacerlo, pero proporcionan tan poca información que el escritor de macros se queda con la tarea de implementar un analizador desde cero. Por otro lado, podría exponer alguna estructura interna del compilador como los árboles AST pre-analizados, pero tienden a exponer demasiada información para que sea conveniente y significa que el compilador debe poder analizar de alguna manera la nueva extensión sintáctica que usted desea. intención de implementar. Las expresiones S son una buena solución para este último: el compilador puede analizar cualquier cosa ya que la sintaxis es uniforme. También son una solución a la anterior, ya que son estructuras simples con un amplio respaldo por parte del lenguaje para separarlas y combinarlas de nuevas maneras.

Pero claro que ese no es el final de la historia. Por ejemplo, es interesante comparar macros simbólicas simples como en CL y macros higiénicas como en implementaciones de Esquemas: generalmente se implementan agregando más información a los datos representados, lo que significa que puede hacer más con esos sistemas de macros. (También puede hacer más con las macros CL ya que la información adicional también está disponible, pero en lugar de hacerlo parte de la representación de la sintaxis, se pasa como un argumento de entorno adicional a las macros).


Te permite escribir macros que simplemente transforman un árbol de listas en otro. Ejemplo simple (esquema):

(define-syntax and (syntax-rules () ((and) #t) ((and thing) thing) ((and thing rest ...) (if thing (and rest ...) #f))))

Observe cómo las invocaciones de macros simplemente se combinan con las cláusulas (and) , (and thing) y (and thing rest ...) (dependiendo de la aridad de la invocación), y se manejan de manera apropiada.

Con otros lenguajes, las macros tendrían que lidiar con algún tipo de AST interno del código que se está transformando; de lo contrario, no habría una manera fácil de "ver" su código en un formato programático, y eso aumentaría el La fricción de escribir macros.

En los programas Lisp, las macros generalmente se usan con bastante frecuencia, precisamente debido a la baja fricción de escribirlas.