【问题标题】:build set lazily in clojure在clojure中懒惰地构建集合
【发布时间】:2011-04-13 01:45:50
【问题描述】:

我已经开始学习 clojure,但我在思考某些概念时遇到了麻烦。例如,我在这里要做的是获取这个函数并对其进行转换,以便它懒惰地调用 get-origlabels。

(defn get-all-origlabels []
    (set (flatten (map get-origlabels (range *song-count*)))))

我的第一次尝试使用了递归但炸毁了堆栈(song-count 大约是 10,000)。我不知道如何使用尾递归来做到这一点。

get-origlabels 每次调用都会返回一个集合,但值通常在调用之间重复。 get-origlabels 函数实际上做的是读取一个文件(从 0 到 song-count-1 的每个值对应一个不同的文件)并以集合的形式返回其中存储的单词。

任何指针将不胜感激!

谢谢! -菲利普

【问题讨论】:

    标签: clojure set lazy-evaluation


    【解决方案1】:

    您可以使用mapcat 获得您想要的。我相信将它放入一个实际的 Clojure 集合中会使其去懒惰,正如 (take 10 (set (iterate inc 0))) 试图在取 10 之前实现整个集合的事实所证明的那样。

    (distinct (mapcat get-origlabels (range *song-count*)))
    

    这会给你一个惰性序列。您可以通过执行类似的操作来验证这一点,从无限序列开始:

    (->> (iterate inc 0)
         (mapcat vector)
         (distinct)
         (take 10))
    

    你最终会得到一个 seq,而不是一个 set,但既然听起来你真的很想在这里偷懒,我认为这是最好的。

    【讨论】:

    • +1 用于解释该集合“去惰性化”序列。现在我们迫切需要一个动词。
    • “实现”序列是这个的标准动词;我似乎懒得回忆了:)
    • (iterate inc 0) 与 (range) 相同,因此您可以将其缩短一点。
    • 你也可以说懒惰的反义词是“渴望”。 set 函数是急切的。
    【解决方案2】:

    这可能有更好的堆栈行为

    (defn get-all-origlabels []
        (reduce (fn (s x) (union s (get-origlabels x))) ${} (range *song-count*)))
    

    【讨论】:

      【解决方案3】:

      我可能会使用类似的东西:

      (into #{} (mapcat get-origlabels (range *song-count*)))
      

      一般来说,“into”在构造 Clojure 数据结构时非常有用。我有一个传送带(一个序列)将一堆随机物体放入一个大桶(目标集合)的心理形象。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-29
        • 1970-01-01
        相关资源
        最近更新 更多