Clojure - параметры, передаваемые по имени

Clojure имеет параметры, передаваемые по имени? Если так, можно ли обеспечить небольшой пример его?

77
задан one-zero-zero-one 26 July 2010 в 18:40
поделиться

3 ответа

В 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.

117
ответ дан 24 November 2019 в 10:55
поделиться

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

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

0
ответ дан 24 November 2019 в 10:55
поделиться

В дополнение к отличному ответу Рейнса, есть также макрос в 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]
33
ответ дан 24 November 2019 в 10:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: