首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >同一多重方法的不同方法之间的递归

问同一多重方法的不同方法之间的递归
EN

Stack Overflow用户
提问于 2011-02-01 19:22:46
回答 2查看 307关注 0票数 5

我正在编写一个Clojure库来解析Mac的基于XML的属性列表文件。除非您给它一个大的输入文件,否则代码工作得很好,这时您将得到java.lang.OutOfMemoryError: Java heap space。

下面是一个输入文件示例(足够小到可以正常工作):

代码语言:javascript
复制
<plist version="1.0">
<dict>
    <key>Integer example</key>
    <integer>5</integer>
    <key>Array example</key>
    <array>
        <integer>2</integer>
        <real>3.14159</real>
    </array>
    <key>Dictionary example</key>
    <dict>
        <key>Number</key>
        <integer>8675309</integer>
    </dict>
</dict>
</plist>

clojure.xml/parse将其转化为:

代码语言:javascript
复制
{:tag :plist, :attrs {:version "1.0"}, :content [
    {:tag :dict, :attrs nil, :content [
        {:tag :key, :attrs nil, :content ["Integer example"]}
        {:tag :integer, :attrs nil, :content ["5"]}
        {:tag :key, :attrs nil, :content ["Array example"]}
        {:tag :array, :attrs nil, :content [
            {:tag :integer, :attrs nil, :content ["2"]}
            {:tag :real, :attrs nil, :content ["3.14159"]}
        ]}
        {:tag :key, :attrs nil, :content ["Dictionary example"]}
        {:tag :dict, :attrs nil, :content [
            {:tag :key, :attrs nil, :content ["Number"]}
            {:tag :integer, :attrs nil, :content ["8675309"]}
        ]}
    ]}
]}

我的代码将其转换为Clojure数据结构。

代码语言:javascript
复制
{"Dictionary example" {"Number" 8675309},
 "Array example" [2 3.14159],
 "Integer example" 5}

我代码的相关部分如下

代码语言:javascript
复制
; extract the content contained within e.g. <integer>...</integer>
(defn- first-content
  [c]
  (first (c :content)))

; return a parsed version of the given tag
(defmulti content (fn [c] (c :tag)))

(defmethod content :array
  [c]
  (apply vector (for [item (c :content)] (content item))))

(defmethod content :dict
  [c]
  (apply hash-map (for [item (c :content)] (content item))))

(defmethod content :integer
  [c]
  (Long. (first-content c)))

(defmethod content :key
  [c]
  (first-content c))

(defmethod content :real
  [c]
  (Double. (first-content c)))

; take a java.io.File (or similar) and return the parsed version
(defn parse-plist
  [source]
  (content (first-content (clojure.xml/parse source))))

代码的核心是content函数,这是一个在:标记( XML的名称)上分派的multimethod方法。我想知道,为了使这个递归更好地工作,我是否应该做一些不同的事情。我试着用trampoline content替换对trampoline content的所有三个调用,但都没有效果。为了让这种相互递归更有效地工作,我应该做些什么呢?还是我采取了根本错误的做法?

编辑:顺便说一下,这段代码是可在GitHub上获得,它的形式可能更容易使用。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-02-02 06:55:56

您有来自单个方法的多个递归调用(每个子方法一个),因此您的代码不是(也不可能没有繁重的reorg)尾递归。trampoline用于互尾递归函数.

您的大型XML文件有多深,有多长?我这么问是因为你得到的是OoM,不是这样的。

无论如何,要解决递归问题(不太可能导致异常),您必须遍历XML (例如使用xml-zip),同时维护一个表示正在构建的结果树的堆栈(向量或列表)。具有讽刺意味的是,XML数据结构的遍历在某种程度上等同于用于构建该结构的sax事件。

票数 4
EN

Stack Overflow用户

发布于 2011-02-02 06:39:32

大量递归将导致StackOverflowException,而不是OutOfMemoryError。此外,这里的递归似乎不太深入(根据示例中的XML文件,只有3个级别)。

我的猜测是,抛出OutOfMemoryError是因为您的大型XML文件被解析到的数据结构太大,无法适应JVM堆。您可以使用-Xms和-Xmx选项尝试增加堆大小。但是,解析大型XML文件的正确方法是使用SAX事件,而不是构建树(DOM或Clojure数据结构)。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4867013

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档