2009-04-04 15 views
51

In Common Lisp si può fare questo:argomenti Clojure parole chiave

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

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

Clojure non ha argomenti chiave. Un'alternativa è questo:

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

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

Ecco troppe parentesi nidificate dover digitare e leggere tutto il tempo. Richiede anche che una hash-map esplicita sia passata come argomento piuttosto che come lista piatta.

Qual è l'equivalente Clojure più idiomatico degli argomenti delle parole chiave che non sembra che qualcuno abbia lanciato una bomba a punteggiatura?

+3

Dal momento che questa domanda era ultima parola chiave attiva destrutturazione vincolante è stato aggiunto a Clojure. Ho fornito una risposta per indicarlo. –

+1

@Brian dovresti considerare di aggiornare la risposta accettata. –

risposta

39

Un modo semplice per simulare args parole chiave in clojure sta utilizzando hash-mappa su parametri di riposo in questo modo:

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

Rich Hickey ha fornito una macro in this message from the clojure google group che ti dà i parametri di parole chiave. Lo corresponding thread contiene informazioni sul motivo per cui i parametri delle parole chiave non sono supportati da clojure. Fondamentalmente per evitare il sovraccarico di runtime. Rich spiega il metodo che ho mostrato sopra in this message

+0

Vedere [risposta di Alex Stoddard] (http://stackoverflow.com/questions/717963/clojure-keyword-arguments/3969693#3969693); il supporto per le parole chiave arg è stato aggiunto al collegamento dei parametri. –

10

Una recente aggiunta alla clojure.contrib.def è il defnk macro, che consente di definire funzioni con argomenti a parola chiave (vedi here).

94

di aggiornare questa risposta per Clojure 1.2 v'è ora il supporto completo parola chiave arg con valori di default forniti dalla mappa forme di 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

Penso che questo dovrebbe essere promosso per essere la risposta? – john2x

Problemi correlati