2009-04-04 14 views
51

En Common Lisp puede hacer esto:argumentos de palabras clave Clojure

(defun foo (bar &key baz quux) 
    (list bar baz quux)) 

(foo 1 :quux 3 :baz 2) ; => (1 2 3) 

Clojure no tiene argumentos de palabra clave. Una alternativa es esta:

(defn foo [bar {:keys [baz quux]}] 
    (list bar baz quux)) 

(foo 1 {:quux 3 :baz 2}) ; => (1 2 3) 

Son demasiados los paréntesis anidados que debe escribir y leer todo el tiempo. También requiere que se pase un hash-map explícito como un argumento en lugar de una lista plana.

¿Cuál es el equivalente idiomático de Clojure de los argumentos de palabra clave que no parece que alguien desactivó una bomba de puntuación?

+3

Dado que esta cuestión era la última palabra clave activa la desestructuración de unión ha sido añadido a Clojure. He proporcionado una respuesta para indicar esto. –

+1

@Brian, debería considerar actualizar la respuesta aceptada. –

Respuesta

39

Una forma sencilla de simular argumentos de palabras clave en clojure es el uso de hash-mapa en parámetros de descanso así:

> (defn kwtest [x & e] (:foo (apply hash-map e))) 
#'user/kwtest 
> (kwtest 12 :bar "ignored" :foo "returned") 
"returned" 

Rich Hickey proporciona una macro en this message from the clojure google group que le da parámetros de palabras clave. El corresponding thread contiene información sobre por qué los parámetros de palabra clave no son compatibles con clojure. Básicamente para evitar la sobrecarga de tiempo de ejecución. Rich explica el método que he mostrado anteriormente en this message

+0

Ver [respuesta de Alex Stoddard] (http://stackoverflow.com/questions/717963/clojure-keyword-arguments/3969693#3969693); soporte para keyword args ha sido agregado al enlace de parámetros. –

10

Una adición reciente a clojure.contrib.def es la defnk macro, que permite la definición de funciones con argumentos de palabras clave (véase here).

94

de actualizar esta respuesta para Clojure 1.2 ahora hay soporte completo palabra clave arg con valores por defecto proporcionado por el mapa formas de destructuring binding:

user> (defn foo [bar &{ :keys [baz quux] 
         :or {baz "baz_default" quux "quux_default"}}] 
     (list bar baz quux)) 
#'user/foo 

user> (foo 1 :quux 3) 
(1 "baz_default" 3) 
+7

Creo que esto debería promoverse para ser la respuesta? – john2x

Cuestiones relacionadas