交换!价值无法解决

时间:2017-06-07 16:10:25

标签: xml clojure lazy-evaluation

在解析xml文件时,我将值标准化并通过交换保存它们!变成一个原子。另外,我构建了一棵树来反映原始结构。

当我调用该函数时,它只返回部分数据,但不返回规范化值。当我解析原子时,数据被完全写入。

这里代码的部分,似乎对该行为至关重要。

(defn normalize-values
  "Save the dataset to the atom and returns the reference"
  [tour-id key value]
  (swap! db assoc-in [tour-id (query-key key :name) value] {:title value})
  {key [(query-key key) value]})


(defn extract-tags
  "Differs between unique and normalizable values"
  [node tour-id]
  (let [data (zip/xml-zip node)
        key (:tag node)
        value (zx/xml1-> data key zx/text)
        res (if (some #{key} [:sound :map :video :creator])
              (normalize-values tour-id key value)
              {key value})]
    res))

(defn panorama->map
  "Creates a panorama map from the xml data"
  [node tour-id]
  (let [xml-node (zip/node node)
        tag-values (into {} (map #(extract-tags % tour-id) (:content xml-node)))]
    (merge tag-values
           {:id     (get-file-id (:file tag-values))
            :hidden (read-string (get-in xml-node [:attrs :hidden]))})))


(defn menu->map
  "Loops over the xml tree and builds the structure"
  [tour-id menu]
  (for [entry menu]
    (let [children (childs-of-child entry)]
      (if (not-empty children)
        (let [{:keys [id] :as category-map} (category->map entry)]
          (swap! db assoc-in [tour-id (query-key :categorie :id) id] category-map)
          {:loc      [:categories/by-id id]
           :children (menu->map tour-id children)})

        (let [{:keys [id] :as panorama-map} (panorama->map entry tour-id)]
          (swap! db assoc-in [tour-id (query-key :pano :id) id] panorama-map)

          {:loc [:panos/by-id id]})))))

(defn parse-menu
  "Starting function which resets the db and saves all data to the atom "
  [path id]
  (swap! db dissoc id)
  (logging/debug "Parse Menu: " path)

  (let [xml (xml->map path)
        menu-data (menu->map id (:content xml))]

    (swap! db assoc-in [id :title] (tour-title xml))
    (swap! db assoc-in [id :tree] menu-data)

    (get @db id)))

我怎么能意识到原子是否正确解析了?

2 个答案:

答案 0 :(得分:1)

for是懒惰的,在你意识到它产生的序列的元素之前,它不会执行你偷偷摸摸的副作用。你的描述"当我解析原子时,数据是完全写的。"不清楚,但我怀疑你的意思是你在repl中deref它,导致它的值打印,这会强制嵌入其中的懒惰seqs,这会导致它们的副作用运行。

答案 1 :(得分:0)

正如@Alan Thompson评论的那样,这里的错误来源是懒惰的评价。在(vec)循环之前添加(for)之后,问题就消失了。

(defn menu->map
  "Loops over the xml tree and builds the structure"
  [tour-id menu]

  (vec    ;;forcing the evaluation of the loop

   (for [entry menu]
     (let [children (childs-of-child entry)]
       (if (not-empty children)
         (let [{:keys [id] :as category-map} (category->map entry)]
           (swap! db assoc-in [tour-id (query-key :categorie :id) id] category-map)
           {:loc      [:categories/by-id id]
            :children (menu->map tour-id children)})

         (let [{:keys [id] :as panorama-map} (panorama->map entry tour-id)]
           (swap! db assoc-in [tour-id (query-key :pano :id) id] panorama-map)

           {:loc [:panos/by-id id]}))))))