Clojure嵌套剂量环

Est*_*sti 1 loops nested clojure

我是Clojure的新手,我有一个关于嵌套doseq循环的问题.

我想迭代一个序列并得到一个子序列,然后得到一些键来在所有序列元素上应用一个函数.

给定的序列具有或多或少的结构,但有数百本书籍,书架和许多库:

([:state/libraries {6 #:library {:name "MUNICIPAL LIBRARY OF X" :id 6 
:shelves {3 #:shelf {:name "GREEN SHELF" :id 3 :books  
{45 #:book {:id 45 :name "NECRONOMICON" :pages {...}, 
{89 #:book {:id 89 :name "HOLY BIBLE" :pages {...}}}}}}}}])
Run Code Online (Sandbox Code Playgroud)

这是我的代码:

(defn my-function []   (let [conn  (d/connect (-> my-system :config :datomic-uri))]
(doseq [library-seq (read-string (slurp "given-sequence.edn"))]
  (doseq [shelves-seq (val library-seq)]
    (library/create-shelf conn {:id (:shelf/id (val shelves-seq)) 
                                :name (:shelf/name (val shelves-seq))})
    (doseq [books-seq (:shelf/books (val shelves-seq))]
      (library/create-book conn (:shelf/id (val shelves-seq)) {:id (:book/id (val books-seq))
                                                               :name (:book/name (val books-seq))})
                                                               )))))
Run Code Online (Sandbox Code Playgroud)

问题是我想摆脱嵌套剂量混乱,但我不知道什么是最好的方法,因为在每次迭代中键都会改变.使用复发?降低?也许我正在以完全错误的方式思考这个问题?

mad*_*tap 5

就像Carcigenicate在评论中所说的那样,假设库/ ...函数只是副作用,你可以把它写成一个doseq.

(defn my-function []
  (let [conn  (d/connect (-> my-system :config :datomic-uri))]
    (doseq [library-seq (read-string (slurp "given-sequence.edn"))
            shelves-seq (val library-seq)
            :let [_ (library/create-shelf conn
                                          {:id (:shelf/id (val shelves-seq))
                                           :name (:shelf/name (val shelves-seq))})]
            books-seq (:shelf/books (val shelves-seq))]
      (library/create-book conn
                           (:shelf/id (val shelves-seq))
                           {:id (:book/id (val books-seq))
                            :name (:book/name (val books-seq))}))))
Run Code Online (Sandbox Code Playgroud)

我会将"连接数据库"从"啜饮文件"与"写入数据库"分开.再加上一些解构,我最终会得到一些更像:

(defn write-to-the-db [conn given-sequence]
  (doseq [library-seq given-sequence
          shelves-seq (val library-seq)
          :let [{shelf-id   :shelf/id,
                 shelf-name :shelf/name
                 books      :shelf/books} (val shelves-seq)
                _ (library/create-shelf conn {:id shelf-id, :name shelf-name})]
          {book-id :book/id, book-name :book/name} books]
    (library/create-book conn shelf-id {:id book-id, :name book-name})))
Run Code Online (Sandbox Code Playgroud)