Clojure аргументы ключевых слов - PullRequest
52 голосов
/ 05 апреля 2009

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

98 голосов
/ 19 октября 2010

Чтобы обновить этот ответ для 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)
38 голосов
/ 05 апреля 2009

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

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

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

9 голосов
/ 16 июня 2009

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

...