Вопрос

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

Это было полезно?

Решение

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

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

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

Другие советы

Чтобы обновить этот ответ для 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)

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top