Параметры Clojure с дополнительными флагами - PullRequest
14 голосов
/ 26 июня 2009

Каков наилучший способ реализации ключевых слов в качестве необязательных флагов для функции? Я хочу сделать вызовы функции, такие как:

(myfunction 5)
(myfunction 6 :do-this)
(myfunction 3 :go-here)
(myfunction 2 :do-this :do-that)

Используя defn, я могу определить функцию, такую ​​как:

(defn myfunction [value & flags] ... )

Но flags становится списком. Я могу написать свою собственную функцию для поиска в списке, но такая функция не включена в базовую библиотеку, поэтому я предполагаю, что она не идиоматическая.

Что я сейчас использую:

(defn flag-set? [list flag] (not (empty? (filter #(= flag %) list))))
(defn flag-add [list flag] (cons flag list))
(defn flag-remove [list flag] (filter #(not= flag %) list))

Ответы [ 4 ]

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

Списки (а также векторы и карты) не являются хорошим выбором структуры данных для поиска на основе значений (будет линейным временем), поэтому clojure.core не имеет таких функций.

Наборы обеспечивают быстрый поиск на основе значений с помощью «содержит?», Так как насчет

(defn foo [value & flags]
  (let [flags (set flags)]
    (if (contains? flags :add-one)
      (inc value)
      value)))

Если не будет более одного флага, вы можете использовать деструктурирование следующим образом:

(defn foo [value & [flag]] …)
5 голосов
/ 26 июня 2009

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

1 голос
/ 13 мая 2014

Вы можете использовать привязку хэш-карты для деструктурирования дополнительных параметров, таких как:

(defn myfunction 
  [value & {:keys [go-there do-this do-that times] :or {times 1}}]
  {:pre [(integer? times) (< 0 times)]}
  (println "Saw a" value)
  (when go-there
    (dotimes [n times]
      (when do-this (println "Did THIS with" value))
      (when do-that (println "Did THAT with" value)))))

Вышеуказанную функцию можно вызвать следующим образом:

(myfunction "foo" :go-there true :do-this true :do-that false :times 5)

Обратите внимание, что вы можете определить значения по умолчанию для ключей с предложением :or {times 1}. Следующий вызов функции будет повторяться только один раз из-за этого значения по умолчанию:

(myfunction "foo" :go-there true :do-this true :do-that false)

Кроме того, предусловия Clojure обеспечивают удобное тестирование параметров, что также применимо к значениям деструктурированных ключей, как это видно в выражении {:pre [...]} сразу после привязки параметров. Следующий вызов не будет выполнен из-за этой проверки предварительного условия:

(myfunction "foo" :go-there true :do-this true :do-that false :times -1)
0 голосов
/ 26 июня 2009

Строго говоря, это не самый эффективный способ написания этого, но понятно

(defn myfunction [value & flags] 
  (cond (contains? (set flags) :a) 1
        (contains? (set flags) :b) 2)

это может быть более эффективно, чтобы увеличить (установить флаги).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...