Clojure уничтожить карту для анализа в качестве ключевых параметров
У меня есть вопрос, касающийся двух функций, одной из которых является создание полной карты, а других конкретных ключевых слов, например:
(def mapVal
{:test "n"
:anotherKey "n"})
(defn functionTest
[& {:keys [test anotherKey] :or {:test "d" :anotherKey "d"}}]
(println :test :anotherKey))
(defn mapFunc
[map]
(functionTest (get-in map [:test :anotherKey])))
Цель состоит в том, чтобы все ключи в карте параметров были правильно переданы в functionTest. Есть ли в любом случае это может работать? Я попробовал несколько вещей, но я просто не могу получить все ключевые слова и значения, передаваемые в functionTest. Чего я не хочу, так это просто значения карты, она должна быть передана другой функции с ключевым словом и значением.
2 ответа
Ты довольно близко Несколько вещей должны прояснить это.
Во-первых, когда вы объявляете параметры с [& varname]
это означает varname
будет список, содержащий все дополнительные параметры. Таким образом, вам не нужно использовать это "&
здесь, чтобы деструктурировать вход. Вместо этого вы просто указываете, какие ключи вы хотите, чтобы они стали переменными.
Попробуй это:
(defn functionTest
[{:keys [test anotherKey]}]
(println test anotherKey))
И другая проблема заключается в использовании get-in
, С get-in
вы определяете "путь" через вложенные структуры данных с этим вектором. Например, учитывая:
{:first {:a 1 :b 2} :second {:c 3 :d 4}}
Вы могли бы использовать get-in
чтобы получить значение в :second
:c
с этим:
(get-in {:first {:a 1 :b 2} :second {:c 3 :d 4}} [:second :c])
В вашем случае вам не нужно использовать get-in
совсем. Вам просто нужно пройти всю карту. Разрушение, которое вы определили в functionTest
позаботится об остальном. Вот что я сделал, чтобы это работало:
(defn mapFunc
[map]
(functionTest map))
Я бы также предложил вам не называть эту переменнуюmap
поскольку это противоречит map
функция.
get-in
предназначен для доступа к вложенным ассоциативным структурам данных.
(def m {:a {:x 1}})
(get-in m [:a :x]) ;;=> 1
После деструктурирования карты эти значения находятся в области видимости и доступны через символы. Ваш пример должен выглядеть так:
(def mapVal
{:test "n"
:anotherKey "n"})
(defn functionTest
[& {:keys [test anotherKey]
:or {:test "d" :anotherKey "d"}}]
(println test anotherKey))
(defn mapFunc
[m]
(apply functionTest (apply concat (select-keys m [:test :anotherKey]))))
(mapFunc mapVal) ;;=> prints: n n
Вы должны пройти через это, потому что functionTest
принимает необязательные пары ключ-значение в качестве необязательных параметров (те, что справа от &), как в:
(functionTest :test "n"
:anotherKey "n" )
;;=> Also prints: n n
select-keys
возвращает карту только с указанными ключами:
(select-keys mapVal [:test])
;; => {:test "n"}
применение concat
на карту возвращает плоскую последовательность ключей и значений:
(apply concat (select-keys mapVal [:test :anotherKey]))
;; => (:test "n" :anotherKey "n")
apply
применяет функцию к seq, как если бы seq был ее списком аргументов:
(+ [1 2 3]) ;;=> Error.
(apply + [1 2 3]) ;; => 6
Как примечание, обычно в коде Clojure, случай змеи предпочтительнее, чем camelCase для большинства имен.