遍历映射并得到堆栈溢出错误 clojure



对于作业,我需要从 clojure 中的文本文件创建一个地图,这是我的新手。我专门使用哈希映射...但有可能我应该使用另一种类型的地图。我希望这里有人能为我回答这个问题。我确实尝试将我的哈希映射更改为排序映射,但它给了我同样的问题。

文件中每行中的第一个字符是键,整行是值。键是 0-9999 之间的数字。有 10,000 行,一行中第一个数字之后的每个数字都是介于 0 和 9999 之间的随机数。 我认为我已经成功地创建了哈希图。至少,当我运行该代码时,它不会给我错误。但是,当我尝试遍历它时,打印键 0-9999 的每个值,它会在第 2764 行(在文本文件中(的中间出现堆栈溢出错误。我希望有人能告诉我为什么这样做以及更好的方法? 这是我的代码:

(ns clojure-project-441.core
(:gen-class))
(defn -main 
[& args]
(def pages(def hash-map (file)))
(iter 0)

)
(-main)

(defn file []
(with-open [rdr (clojure.java.io/reader "pages.txt")]
(reduce conj [] (line-seq rdr))))

(defn iter [n]
(doseq [keyval (pages n)] (print keyval))
(if (< n 10000)
(iter (inc n))
)

)

这是我输出的屏幕截图

如果它完全相关,我将 repl.it 用作我的 IDE。

为清楚起见,以下是文本文件的一些屏幕截图。

文本文件的开头

引发错误的位置

谢谢。

我认为导致引发异常的特定问题是因为iter在达到 10,000 行限制之前递归调用自己的次数太多。

你的代码中有一些问题对于所有学习 Clojure 的人来说都很常见;我将尝试解释:

  • def用于定义顶级名称。它们对应于其他编程语言全局范围内的常量概念。考虑使用def的方式与使用defn定义函数的方式相同。在代码中,您可能希望使用let为中间结果命名,例如:
(let [uno 1
dos 2]
(+ uno dos)) ;; returns 3
  • 您正在使用名称hash-map将其绑定到某个结果,但是如果要使用用于创建地图的函数hash-map,这将妨碍您。尝试将其重命名为my-map或类似名称。

  • 要递归调用函数而不吹堆栈,您需要使用recur,原因有点长,难以解释。请参阅此处的阶乘示例:https://clojuredocs.org/clojure.core/recur

我的建议是将此作业视为由以下小函数组成的管道:

  • 从文件中读取行的函数(您已经有了这个(
  • 给定一行
  • 返回一对的函数:该对的第一个元素是该行的第一个数字,第二个元素是整行(输入参数(或
  • 读取行中第一个数字的函数
  • 要构建地图,您有几个选择;我想到了两个:
    • 使用loop结构,对于每一行,"更新"哈希映射以包含一个新的键值对(键是第一个数字,值是整行(,然后返回您构建的整个哈希映射
    • 使用reduce操作:创建键值对的集合,然后告诉reduce一次一步地合并到原始哈希映射中。结果是你想要的哈希映射

我认为关键是要熟悉您可以使用的功能并构建可以单独测试的小函数,并尝试方便地对它们进行分组以解决您的问题。尝试熟悉hash-mapassocletlooprecur等函数。https://clojuredocs.org/有一个很棒的文档站点,其中还包括可帮助您理解每个函数的示例。

最新更新