Аргументы ключевого слова 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 аргументов ключевых слов, который не выглядит, что кто-то взорвал пунктуационную бомбу?

3 51

3 ответа:

простой способ моделирования ключевых слов args в clojure использует хэш-карту для параметров rest следующим образом:

> (defn kwtest [x & e] (:foo (apply hash-map e)))
#'user/kwtest
> (kwtest 12 :bar "ignored" :foo "returned")
"returned"

Rich Hickey предоставил макрос в это сообщение от группы Clojure google это дает вам ключевые параметры. Элемент соответствующей ветке содержит информацию о том, почему параметры ключевых слов не поддерживаются clojure. В основном, чтобы избежать накладных расходов во время выполнения. Рич объясняет метод, который я показал выше в этот сообщение

чтобы обновить этот ответ для Clojure 1.2 теперь есть полная поддержка ключевых слов arg со значениями по умолчанию, предоставляемыми формами карты разрушение привязки:

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)

недавнее дополнение к clojure.contrib.def - Это defnk макрос, который позволяет определять функции с аргументами ключевых слов (см. здесь).