Soy nuevo en Clojure, soy nuevo en Macros y no tengo experiencia previa en Lisp. Pasé a crear mi propia forma de caja de interruptor y terminé con esto:
(defmacro switch-case [v cases default] (if (cases v) (cases v) default ))
e intenté hacer una función y terminé con esto:
(defn fn-switch-case [v cases default] (if (cases v) (cases v) default ))
Ambos
(switch-case 5 {6 "six" 7 "seven"} "not there")
y
(fn-switch-case 5 {6 "six" 7 "seven"} "not there")
Trabaja bien.
¿Cuál podría ser el escenario donde necesitaría una macro y una función no funcionará? ¿Hay algún inconveniente en mi función o en las implementaciones de macros?
Respuestas:
Una ventaja de las macros es que no siguen las mismas reglas de evaluación que las funciones, ya que solo están realizando transformaciones en el código.
Un ejemplo de una construcción que no podría crear simplemente usando funciones es la macro de subprocesos de Clojure .
Le permite insertar una expresión como primer argumento en una secuencia de formas:
es equivalente a
Usted no será capaz de crear este tipo de constructo utilizando sólo las funciones, ya que antes de que el
->
se evaluó la expresión, el interior(+ 3)
y(* 4)
sería, por lo->
recibiríay necesita ver las funciones reales que se utilizan para funcionar.
En su ejemplo, considere si el resultado para algún caso fue tener efectos secundarios o llamar a alguna otra función. Una versión de función no podría evitar que ese código se ejecute en una situación en la que no se selecciona ese resultado, mientras que una macro podría evitar que se evalúe ese código a menos que sea la opción tomada.
fuente
Un aspecto divertido de las macros es que le brindan la posibilidad de expandir la sintaxis de su lisp y agregarle nuevas características sintácticas, y esto sucede solo porque los argumentos pasados a una macro se evaluarán solo en tiempo de ejecución, y no en el momento de la ejecución. compilando tu macro. Como ejemplo, las macros de primer / último hilo en clojure
-> ->>
no evalúan sus argumentos de expresión, de lo contrario, estos resultados evaluados no podrían aceptar nada más (por ejemplo,(+ 3) => 3
y3
no es una función que podría aceptar su primer argumento principal en algo así(-> 4 (+ 3))
).Ahora, si me gusta esta sintaxis y quiero agregarla a mi implementación de Common Lisp (que no la tiene), puedo agregarla definiendo una macro yo mismo. Algo como esto:
Ahora podría usarlos en Common Lisp de la misma manera que en Clojure:
Además, quizás desee tener una nueva sintaxis para la
range
función de clojure con sus propias palabras clave para su sintaxis, algo así como:se puede definir como esta macro:
o agregue algo similar a Common Lisp (¡es solo por ejemplo, ya que todo esto ya se puede hacer en los idiomas, por supuesto!):
fuente
No estoy exactamente seguro de qué quiere que haga su función de cambio de mayúsculas y minúsculas. ¿Cuál debería ser el valor de:
Puede ser útil si vio la fuente de las funciones / macros centrales relacionadas mediante el uso de la respuesta
Pero, en general, una razón por la que puede desear una macro en lugar de una función es que usar la
case
macro núcleono imprimirá hola Sin embargo, si
case
se define como una función, imprime "hola" en la pantalla y la expresión completa se evaluaría"not there"
. Esto se debe a que las funciones evalúan sus argumentos antes de cada llamada a la función.fuente