2009-04-04 7 views
51

В Common Lisp вы можете сделать это:аргументов Clojure ключевого слова

(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) 

Это слишком много вложенных скобок, чтобы напечатать и читать все время. Для этого также требуется, чтобы явная хэш-карта передавалась как аргумент, а не как плоский список.

Какой самый идиоматический эквивалент Ключевого слова, связанный с ключевыми словами, который не смотрит, что кто-то отправил препинающую бомбу?

+3

Поскольку этот вопрос был обязательное уничтожение того, были добавлены в Clojure последнего активным ключевым слова. Я дал ответ, чтобы указать на это. –

+1

@Brian вы должны рассмотреть возможность обновления принятого ответа. –

ответ

39

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

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

Rich Хики предоставил макрос this message from the clojure google group, который дает вам параметры ключевых слов. В файле corresponding thread содержится информация о том, почему ключевые слова не поддерживаются clojure. В основном, чтобы избежать накладных расходов времени исполнения. Рич объясняет метод я показал выше в this message

+0

См. [Ответ Алекс Стоддарда] (http://stackoverflow.com/questions/717963/clojure-keyword-arguments/3969693#3969693); поддержка привязки ключевых слов была добавлена ​​в привязку параметров. –

10

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

94

Чтобы обновить этот ответ на Clojure 1.2 есть теперь полное ключевое слово поддержка агд со значениями по умолчанию предоставляется карта формами destructuring binding:

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) 
+7

Я думаю, что это должно стать ответом? – john2x

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

  • Нет связанных вопросов^_^