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 для большинства имен.

Другие вопросы по тегам