Это ожидаемое поведение.(doseq [x ... y ...])
будет перебирать каждый элемент в y
для каждого элемента в x
.
Вместо этого вы должны перебирать саму карту один раз.(seq some-map)
вернет список векторов из двух элементов, по одному для каждой пары ключ / значение на карте.(На самом деле они clojure.lang.MapEntry
, но ведут себя как векторы из 2 элементов.)
user> (seq {:foo 1 :bar 2})
([:foo 1] [:bar 2])
doseq
может выполнять итерации по этому результату, как и любой другой.Как и большинство функций в Clojure, которые работают с коллекциями, doseq
внутренне вызывает seq
вашей коллекции, прежде чем выполнять итерацию по ней.Таким образом, вы можете просто сделать это:
user> (doseq [keyval db] (prn keyval))
[:subprotocol "mysql"]
[:username "usr"]
[:classname "com.mysql.jdbc.Driver"]
[:subname "//100.100.100.100:3306/clo"]
[:password "pwd"]
Вы можете использовать key
и val
, или first
и second
, или nth
, или get
, чтобы получить ключи изначения из этих векторов.
user> (doseq [keyval db] (prn (key keyval) (val keyval)))
:subprotocol "mysql"
:username "usr"
:classname "com.mysql.jdbc.Driver"
:subname "//100.100.100.100:3306/clo"
:password "pwd"
Более кратко, вы можете использовать деструктурирование, чтобы привязать каждую половину записей карты к некоторым именам, которые вы можете использовать внутри формы doseq
.Это идиоматично:
user> (doseq [[k v] db] (prn k v))
:subprotocol "mysql"
:username "usr"
:classname "com.mysql.jdbc.Driver"
:subname "//100.100.100.100:3306/clo"
:password "pwd"