Clojure аргументы ключевого слова
В Common Lisp вы можете сделать это:
(defun foo (bar &key baz quux)
(list bar baz quux))
(foo 1 :quux 3 :baz 2) ; => (1 2 3)
Clojure не содержит аргументов ключевого слова. Один из вариантов:
(defn foo [bar {:keys [baz quux]}]
(list bar baz quux))
(foo 1 {:quux 3 :baz 2}) ; => (1 2 3)
Это слишком много вложенных скобок, которые нужно печатать и читать все время. Для этого также требуется, чтобы явная хэш-карта передавалась как аргумент, а не как плоский список.
Какой самый идиоматический Clojure эквивалент аргументов ключевого слова, который не похож на кого-то, который запустил препинающую бомбу?
Ответы
Ответ 1
Простым способом симуляции ключевых слов args в clojure является использование хэш-карты для параметров отдыха, таких как:
> (defn kwtest [x & e] (:foo (apply hash-map e)))
#'user/kwtest
> (kwtest 12 :bar "ignored" :foo "returned")
"returned"
Rich Hickey предоставил макрос в это сообщение из группы clojure google, в которой указаны параметры ключевых слов. соответствующий поток содержит информацию о том, почему параметры ключевого слова не поддерживаются clojure. В основном, чтобы избежать накладных расходов времени исполнения. Рич объясняет метод, который я показал выше в это сообщение
Ответ 2
Чтобы обновить этот ответ для Clojure 1.2, теперь имеется полная поддержка поддержки ключевого слова с значениями по умолчанию, предоставляемыми формами карты связывание деструктурирования:
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)
Ответ 3
Последнее дополнение к clojure.contrib.def
- это макрос defnk
, который позволяет определять функции с помощью аргументов ключевого слова (см. здесь).