2010-07-26 15 views

ответ

109

В Clojure 1.2 вы можете разрушить аргумент rest так же, как вы бы разрушили карту. Это означает, что вы можете использовать именованные непозиционные аргументы ключевых слов. Вот пример:

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

Все вы можете сделать в то время как уничтожение того карту Clojure может быть сделано в списке аргументов функции, как показано выше. В том числе с помощью: или определить значения по умолчанию для аргументов, как это:

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

Но это в Clojure 1.2. Альтернативно, в более старых версиях вы можете сделать это, чтобы имитировать то же самое:

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" 

и что работает в целом одинаково.

И вы также можете иметь позиционные аргументы, которые приходят до именованных аргументов:

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" 

Они не являются обязательными и должны быть обеспечены.

Вы можете фактически разрушить аргумент rest, как и любую коллекцию 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\")" 

Вы можете делать такие вещи даже в Clojure 1.1. Однако деструктурирование в стиле файла для аргументов ключевого слова появилось только в 1.2.

+5

Спасибо за ответ. Лисп - GREAAAAT !!! :-) –

+0

Добро пожаловать. И да, это так. Это определенно. =) – Rayne

0

Возможно, вы имеете в виду с указанием параметров? Они не доступны напрямую, но вы можете use this vectors approach, если хотите, что может дать вам то, что вы хотите.

At RosettaCode есть более глубокое объяснение того, как это сделать, используя деструктурирование.

+0

Спасибо за ответ! :-) –

+3

@Abel Можете ли вы поделиться примерами, на которые вы ссылаетесь? (У них есть способ изменения или устаревания). –

32

В дополнении к отличному ответу Raynes', есть также a macro in clojure-contrib, что делает жизнь проще:

 
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

Я забыл упомянуть об этом! Я был доволен тем, что показал 10 тысяч способов, которыми Clojure может разрушить материал. : p – Rayne

+0

clojure-contrib устарел, и я не мог найти альтернативу. Есть идеи? – Lstor

+1

@Lstor: проверьте [defnk] (https://github.com/Prismatic/plumbing/blob/7ae0e85e4921325b3c41ef035c798c29563736dd/src/plumbing/core.cljx#L470) в [призматическом/сантехническом] (https://github.com/Призматический/водопроводное) – Ian

Смежные вопросы