Clojure: как передать два набора неограниченных параметров? - PullRequest
3 голосов
/ 18 февраля 2010

Придуманный пример для иллюстрации:

(def nest1 {:a {:b {:c "foo"}}})
(def nest2 {:d {:e "bar"}})

Если бы я хотел соединить эти гнезда на произвольных уровнях, я мог бы явно сделать это:

(conj (-> nest1 :a :b) (-> nest2 :d)) ; yields {:e "bar", :c "foo"}

(conj (-> nest1 :a) (-> nest2 :d)) ; yields {:e "bar", :b {:c "foo"}}

Но что если я захочу создать функцию, которая будет принимать "глубину" nest1 и nest2 в качестве параметров?

; Does not work, but shows what I am trying to do
(defn join-nests-by-paths [nest1-path nest2-path]
   (conj (-> nest1 nest1-path) (-> nest2 nest2-path))

И я мог бы попытаться назвать это так:

; Does not work
(join-nests-by-paths '(:a :b) '(:d))

Это не работает. Я не могу просто передать каждый «путь» в виде списка функции (или, возможно, смогу, но мне нужно работать с ним по-другому в функции).

Есть мысли? ТИА ... Шон

1 Ответ

5 голосов
/ 18 февраля 2010

Использование вход :

(defn join-by-paths [path1 path2]
  (conj (get-in nest1 path1) (get-in nest2 path2)))

user> (join-by-paths [:a :b] [:d])
{:e "bar", :c "foo"}
user> (join-by-paths [:a] [:d])
{:e "bar", :b {:c "foo"}}

Ваша версия на самом деле делает что-то вроде этого:

user> (macroexpand '(-> nest1 (:a :b)))
(:a nest1 :b)

который не работает, как вы сказали.

get-in имеет друзей assoc-in и update-in, все для работы с вложенными картами карт. Где-то в clojure.conrtrib есть dissoc-in.

(В Clojure более удобно использовать векторы вместо списков в кавычках, когда вы передаете последовательные группы вещей)

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