我已经开始学习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数据结构时非常有用。我的脑海中有这样的图像:传送带(一个序列)将一堆随机对象放入一个大桶(目标集合)。