在clojure中构建集是惰性的



我已经开始学习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的每个值对应一个不同的文件),并将其中存储的单词以集合的形式返回。

任何指示将非常感激!

谢谢!菲利普

您可以通过使用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,但因为听起来你真的想在这里偷懒,我认为这是最好的。

这可能有更好的堆栈行为

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

我可能会这样写:

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

一般来说,"into"在构造Clojure数据结构时非常有用。我的脑海中有这样的图像:传送带(一个序列)将一堆随机对象放入一个大桶(目标集合)。

相关内容

  • 没有找到相关文章

最新更新