2010-07-26 15 views

Respuesta

109

En Clojure 1.2, puede desestructurar el argumento rest tal como lo haría con un mapa. Esto significa que puede hacer argumentos con palabras clave no posicionales. Aquí está un ejemplo:

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"} 

Cualquier cosa que puede hacer mientras desestructurar un mapa Clojure puede hacerse en la lista de argumentos de una función que se muestra arriba. Incluyendo el uso de: o definir valores por defecto para los argumentos como este:

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

Pero esto es en Clojure 1.2. Por otra parte, en las versiones anteriores, se puede hacer esto para simular lo mismo:

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" 

y que generalmente funciona de la misma manera.

y también se puede tener argumentos posicionales que se presentan ante los argumentos de palabra clave:

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" 

Estos no son opcionales y tienen que ser proporcionada.

En realidad, puede desestructurar el argumento rest como lo haría con cualquier colección de 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\")" 

Puede hacer este tipo de cosas incluso en Clojure 1.1. La desestructuración de estilo de mapa para argumentos de palabras clave solo vino en 1.2.

+5

Gracias por la respuesta. Lisp es GREAAAAT !!! :-) –

+0

Eres bienvenido. Y sí lo es. Ciertamente es =) – Rayne

0

¿Quizás quiere decir con los parámetros? Estos no están disponibles directamente, pero puede use this vectors approach si lo desea, que puede darle lo que desea.

At RosettaCode hay una explicación más profunda sobre cómo hacer esto usando la desestructuración.

+0

Gracias por la respuesta! :-) –

+3

@Abel ¿Puede compartir los ejemplos que enlaza? (Tienen una forma de cambiar o desactualizarse). –

32

Además de una excelente respuesta Raynes', también hay a macro in clojure-contrib que hace la vida más fácil:

 
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

¡Me olvidé de mencionar eso! Estaba atrapado en mostrar las 10 mil formas en que Clojure puede desestructurar cosas. : p – Rayne

+0

clojure-contrib está en desuso, y no pude encontrar una alternativa actual. ¿Algunas ideas? – Lstor

+1

@Lstor: echa un vistazo a [defnk] (https://github.com/Prismatic/plumbing/blob/7ae0e85e4921325b3c41ef035c798c29563736dd/src/plumbing/core.cljx#L470) en [prismatic/fonmbing] (https://github.com/Prismático/fontanería) – Ian

Cuestiones relacionadas