2009-03-24 18 views
15

Me gustaría hacer esto (en REPL o en cualquier lugar)Cómo defnir una función de una cadena en Clojure?

(defn (symbol "print-string") [k] (println k)) 

y luego ser capaz de hacer

(print-string "lol") 

O, si hay alguna otra manera de crear defn de cadenas personalizadas de macroses, ¿podría empujarme en la dirección correcta, por favor?

Respuesta

21
(defmacro defn-with-str [string args & body] 
`(defn ~(symbol string) ~args [email protected])) 

(defn-with-str "print-string" [k] (println k)) 

(print-string "lol") 
+0

1. ¿cuál es el ~ delante de argumentos? 2. ¿Cuál es el ~ @ frente al cuerpo? – Belun

+1

@Belun 1. ~ = unquote 2. ~ @ = expande la secuencia – Surya

+0

¿por qué es que si lo hago? Defn defns [] (doall (map (fn [s]) (defn-with-str s [k] (println k))) ["print-string"]))) Recibo un fn llamado 's'? – Hendekagon

14

de Me gusta dnolen respuesta mejor, pero se puede hacer esto también:

(defn #=(symbol "print-string") [k] (println k))

#=() se evalúa en tiempo de lectura. No sé cuán estable es esta característica de Clojure, no confiaría en que no cambie en el futuro. Las macros son cómo lo haría.

17

La solución de dnolen funciona en el tiempo de expansión de macro, Brian Carper en tiempo de lectura. Ahora, aquí está uno para el tiempo de ejecución:

(intern *ns* (symbol "a") (fn [k] (println k))) 
+0

Cool no lo sabía. Una advertencia es que a la var a le faltarán los metadatos de función que se obtiene al usar defn. – dnolen

7

FYI - La respuesta de dnolen sólo funcionará para las cadenas literales, y no para las cadenas en def'd o variables de let'd.

(defmacro defn-con-str [args de cadena & cuerpo] `(defn ~ (cadena de símbolos) ~ ~ @ args cuerpo))

(def hisym "Hola") (defn-con- str hisym [] (pRINTLN "Hola"))

ahora tiene una función llamada "hisym"

(hi) -> java.lang.Exception: No se puede resolver símbolo: hola en este contexto (NO_SOURCE_FILE : 6) (hisym) -> imprime "hola"

Para evitar esto, la cadena eval nombre de función en la macro

(defmacro defn-with-str [string args & body]
`(defn ~(symbol (eval string)) ~args [email protected]))

Cuestiones relacionadas