【问题标题】:clojure data.xml force evaluate lazy xml treeclojure data.xml 强制评估惰性 xml 树
【发布时间】:2021-05-18 14:48:53
【问题描述】:

根据data.xml的README,parse返回的数据结构包含惰性序列。所以返回的 XML 树由

(with-open [r (io/input-stream (io/file "data.xml"))]
  (xml/parse r))

在此代码块外遍历树时可能会抛出异常,因为输入流已经关闭。

在返回之前强制评估整个树的最优雅的方法是什么?我尝试了以下方法,但我想知道是否有更简单的方法。

(with-open [r (io/input-stream (io/file "data.xml"))]
  (doto (xml/parse r)
    (->> (tree-seq map? :content) (dorun))))

【问题讨论】:

    标签: clojure


    【解决方案1】:

    使用doall 强制实现惰性序列,然后只保留第一个元素。另外,您可以使用xml-seq 而不是tree-seq

    (with-open [r (io/input-stream (io/file "data.xml"))]
      (-> r xml/parse xml-seq doall first))
    

    【讨论】:

    • 此版本将整个未使用的序列保留在内存中,直到函数返回。
    • 这是非惰性序列的必要成本。请注意,该序列与所需的树共享其数据结构,因此成本可能不会那么高。您将需要衡量应用程序中的成本。如果内存成本太高,您需要改变策略并接受懒惰,而不是试图避免它。
    • @erdos 如果你想参与懒惰,你必须将工作移到你的with-open
    【解决方案2】:

    对于一般的 XML 解析,我可能会建议 looking at tupelo.parse.xml。它不是惰性的,并且简化了 XML 数据的加载。解析HTML via TagSoup有类似的命名空间,还有parsing YAML

    对于一般用途,您始终可以回退到 tupelo.core/unlazy。它将递归地遍历数据结构并将每个项目转换为普通的地图、向量、集合等。它还将通过slurp 实现InputStream(对于测试返回InputStream 而不是细绳)。它还处理java.lang.Iterable => 向量。总体而言,unlazy 就像使用了类固醇的doall


    旁白:

    如果您对映射和设置的东西感到疑惑,那是因为 Datomic 返回值的行为类似于“惰性映射”并且不会实现所有键值对,除非您专门提取每个键或将对象转储到通过into 或类似方式的常规 Clojure 映射。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-08
      • 2013-03-11
      • 2017-01-18
      • 2018-11-11
      • 2015-05-29
      相关资源
      最近更新 更多