Assoc-if в Clojure
Есть ли в библиотеке Clojure функция "assoc-if"? I. Если значение истинно, обновите карту с заданным значением ключа. Я попытался найти что-то с этой точки зрения, но мне не хватало.
(defn assoc-if
[m key value]
(if value (assoc m key value) m))
Ответы
Ответ 1
Если цель состоит в том, чтобы избежать повторения m
, вы можете использовать conj
:
(conj m (when value [key value]))
... или Clojure 1.5 новых макросов для потоковой передачи:
(-> m
(cond-> value (assoc key value)))
Если действительно важно избегать повторения как m
, так и value
, вам придется написать свой собственный или выйти за пределы clojure.core
Ответ 2
В Clojure нет встроенной функции assoc-if
, но вы не первый, кто ей нужен. Проверьте эту ссылку с помощью assoc-if
ALEX MILLER:
(defn ?assoc
"Same as assoc, but skip the assoc if v is nil"
[m & kvs]
(->> kvs
(partition 2)
(filter second)
flatten
(apply assoc m)))
Но, поскольку flatten
является рекурсивным, лучше заменить его чем-то, что нет (спасибо kotarak за подсказку). Другая проблема этой реализации заключается в том, что (apply assoc m)
не будет работать в пустом списке. Поэтому лучше всего заменить его на:
(defn ?assoc
"Same as assoc, but skip the assoc if v is nil"
[m & kvs]
(->> kvs
(partition 2)
(filter second)
(map vec)
(into m)))