2010-07-26 13 views

risposta

109

In Clojure 1.2, è possibile destrutturare l'argomento rest proprio come si farebbe per destrutturare una mappa. Ciò significa che puoi fare argomenti con parole chiave non posizionali. Ecco un esempio:

user> (defn blah [& {:keys [key1 key2 key3]}] (str key1 key2 key3)) 
#'user/blah 
user> (blah :key1 "Hai" :key2 " there" :key3 10) 
"Hai there10" 
user> (blah :key1 "Hai" :key2 " there") 
"Hai there" 
user> (defn blah [& {:keys [key1 key2 key3] :as everything}] everything) 
#'user/blah 
user> (blah :key1 "Hai" :key2 " there") 
{:key2 " there", :key1 "Hai"} 

Tutto si può fare mentre destrutturazione una mappa Clojure può essere fatto in lista degli argomenti di una funzione, come indicato sopra. Tra cui l'uso: o per definire i valori predefiniti per gli argomenti di questo tipo:

user> (defn blah [& {:keys [key1 key2 key3] :or {key3 10}}] (str key1 key2 key3)) 
#'user/blah 
user> (blah :key1 "Hai" :key2 " there") 
"Hai there10" 

Ma questo è in Clojure 1.2. In alternativa, nelle versioni precedenti, è possibile eseguire questa operazione per simulare la stessa cosa:

user> (defn blah [& rest] (let [{:keys [key1 key2 key3] :or {key3 10}} (apply hash-map rest)] (str key1 key2 key3))) 
#'user/blah 
user> (blah :key1 "Hai" :key2 " there") 
"Hai there10" 

e che funziona generalmente allo stesso modo.

E si può anche avere argomenti posizionali che precedono la parola chiave argomenti:

user> (defn blah [x y & {:keys [key1 key2 key3] :or {key3 10}}] (str x y key1 key2 key3)) 
#'user/blah 
user> (blah "x" "Y" :key1 "Hai" :key2 " there") 
"xYHai there10" 

Questi non sono opzionali e devono essere fornite.

In realtà è possibile destrutturare l'argomento rest come se si trattasse di una raccolta Clojure.

user> (defn blah [& [one two & more]] (str one two "and the rest: " more)) 
#'user/blah 
user> (blah 1 2 "ressssssst") 
"12and the rest: (\"ressssssst\")" 

Si può fare questo genere di cose anche in Clojure 1.1. La destrutturazione in stile mappa per gli argomenti delle parole chiave è disponibile solo nella versione 1.2.

+5

Grazie per la risposta. Lisp è GREAAAAT !!! :-) –

+0

Sei il benvenuto. E sì lo è. Certamente è. =) – Rayne

0

Forse intendi i parametri con nome ? Questi non sono direttamente disponibili, ma puoi, se lo desideri, use this vectors approach, che potrebbe darti quello che vuoi.

At RosettaCode c'è una spiegazione più profonda su come farlo usando la destrutturazione.

+0

Grazie per la risposta! :-) –

+3

@Abel Puoi condividere gli esempi a cui ti colleghi? (Hanno un modo di cambiare o di non essere aggiornati). –

32

Oltre alla risposta eccellente Raynes', c'è anche a macro in clojure-contrib che rende la vita più facile:

 
user=> (use '[clojure.contrib.def :only [defnk]]) 
nil 
user=> (defnk foo [a b :c 8 :d 9] 
     [a b c d]) 
#'user/foo 
user=> (foo 1 2) 
[1 2 8 9] 
user=> (foo 1 2 3) 
java.lang.IllegalArgumentException: No value supplied for key: 3 (NO_SOURCE_FILE:0) 
user=> (foo 1 2 :c 3) 
[1 2 3 9] 
+6

Ho dimenticato di dirlo! Sono stato coinvolto nel mostrare i 10 mila modi in cui Clojure può distruggere le cose. : p – Rayne

+0

clojure-contrib è deprecato e non sono riuscito a trovare un'alternativa corrente. Qualche idea? – Lstor

+1

@Lstor: check out [defnk] (https://github.com/Prismatic/plumbing/blob/7ae0e85e4921325b3c41ef035c798c29563736dd/src/plumbing/core.cljx#L470) in [prismatic/plumbing] (https://github.com)/prismatico/idraulici) – Ian

Problemi correlati