6

OK, entiendo muy bien cómo usar funciones y macros.Haga que las macros y las funciones se integren más fácilmente

Lo que me llama la atención es por qué el compilador no puede ser un poco más inteligente al integrar los dos, p. considerar el código de Clojure:

(defmacro wonky-add [a b] `(+ ~a (* 2 ~b))) 

(defn wonky-increment [a] (apply wonky-add a 1)) 
=> Error: can't take value of a macro 

Sí, sé que puedo hacer este trabajo mediante la adopción de la "aplicar" - pero ¿por qué es que el compilador no puede encontrar la manera de hacer esto en sí?

¿Sería posible en Clojure/otros LISP crear una versión de aplicación u otras funciones de orden superior que funcionen igual de bien con las funciones y las macros como parámetros?

Respuesta

11

Esta respuesta no se trata tanto de Clojure, sino de Lisp y macros en general.

Recuerde:

APLICAR está ahí para ser capaz de llamar a las funciones con las listas de argumentos que se crean en tiempo de ejecución.

Las macros están ahí para generar un nuevo código fuente a partir de algún código fuente, y se ejecutará el código fuente generado.

Ahora:

Si permite que aplicará a los piensos diferente código fuente en una macro en tiempo de ejecución, uno tiene que ser capaz de generar el código de resultado en tiempo de ejecución y también para ejecutar el código generado.

Por lo tanto, en un sistema Lisp compilado, cada llamada de APLICAR con una macro crea potencialmente un nuevo código que debe compilarse en tiempo de ejecución para poder ejecutarlo. Esto significa también que puede obtener nuevos errores de compilación en tiempo de ejecución, cuando su código se está ejecutando y el código tiene algún problema. Entonces, para APLICAR macros en tiempo de ejecución, necesita un compilador y toda la información necesaria (por ejemplo, otras macros) para poder expandir y compilar el código.

Esto también significa que, en el caso general, no se puede compilar APLICAR con una macro antes del tiempo de ejecución, ya que no se sabe qué argumentos de ejecución se aplicarán.

En un Lisp basado en intérprete, puede haber más información y se pueden aplicar macros todo el tiempo.

En los primeros Lisp había funciones normales y los llamados FEXPR. Los FEXPR permitieron llamadas flexibles y manipulación del código de tiempo de ejecución. Más adelante en la historia de Lisp se han reemplazado con macros, ya que las macros permiten una compilación eficiente y, en los sistemas basados ​​en el compilador, permiten que los errores de sintaxis se manejen antes del tiempo de ejecución.

2

Lo que está describiendo suena como una macro de primera clase (es decir, una macro que puede manipular como una función). Algunos cepos tienen estos (Arc por ejemplo), pero apply, a causa de no ser una macro en sí misma, probablemente todavía no funcionaría.

Cuestiones relacionadas