¿Cómo implementar lambda como una función llamada "lambda" en Clojure?
macros (1)
Me gustaría poder definir lambdas usando la sintaxis de Lisp común, en Clojure. Por ejemplo:
(lambda (myarg)
(some-functions-that-refer-to myarg))
Esto debe dar como resultado lo mismo que:
#(some-functions-that-refer-to %)
En mi caso, sé que siempre tendré exactamente un arg, así que quizás eso simplifique las cosas. (Pero se puede llamar cualquier cosa - "myarg" o lo que sea).
Sospecho que una solución viable es "(defmacro lambda ...". Si es así, no estoy seguro de la mejor manera de proceder. Cómo traducir limpiamente el nombre arg a%? Y cómo terminar con la función correcta ?
O, ¿hay una solución más simple que escribir mi propia macro que en realidad implementa nuevamente ... la lambda de Clojure?
#(foo %)
es solo una abreviatura del lector para (fn [arg] (foo arg))
. No hay razón para escribir una macro que se expande en #(...)
. Todos los %
''s en un #(...)
constructo se expanden en gensyms de inmediato de todos modos.
user> `#(foo % %1 %2)
(fn* [user/p1__1877 user/p2__1878]
(user/foo user/p1__1877 user/p1__1877 user/p2__1878))
Si alguna vez escribe una macro que se expande para crear funciones anónimas, también puede expandirlas a formularios fn
usted mismo. En su caso, probablemente debería usar fn
directamente y omitir las macros. fn
es la lambda
de Clojure.
La diferencia entre (fn [] ...)
y (lambda () ...)
en este caso es que "fn" es más corto de escribir que "lambda", y fn
toma un vector para sus enlaces mientras que lambda
toma una lista . Si está utilizando Clojure, tendrá que acostumbrarse a esto con el tiempo, porque los vectores siempre se usan para colecciones de enlaces, en todas las formas do
y for
y binding
etc. El razonamiento detrás de esto, como yo lo entiendo, es que las listas se usan para llamadas a funciones o macro llamadas, y los vectores se usan para cosas que no son llamadas (listas de símbolos para vincular, por ejemplo). Podría decirse que hace que sea más fácil escanear el código visualmente que listas-todo-el-camino-abajo. Clojure no es Common Lisp, y experimentarás dolor si tratas de forzarlo.
Si realmente deseabas hacer esto, solo para decir que lo hiciste:
user> (defmacro lambda [args & body]
`(fn ~(vec args) ~@body))
user> ((lambda (x) (println x)) "foo")
foo
nil
Esto no le permite poner una docstring o metadata en su función, entre otras cosas. No creo que quieras utilizar esto en un programa Clojure real.