在 Clojure 中延迟构建集

发布于 2024-11-01 16:01:48 字数 449 浏览 4 评论 0原文

我已经开始学习 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 的每个值都有一个不同的文件)并返回存储在其中的单词集合。

任何指示将不胜感激!

谢谢! -菲利普

I've started to learn clojure but I'm having trouble wrapping my mind around certain concepts. For instance, what I want to do here is to take this function and convert it so that it calls get-origlabels lazily.

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

My first attempt used recursion but blew up the stack (song-count is about 10,000). I couldn't figure out how to do it with tail recursion.

get-origlabels returns a set each time it is called, but values are often repeated between calls. What the get-origlabels function actually does is read a file (a different file for each value from 0 to song-count-1) and return the words stored in it in a set.

Any pointers would be greatly appreciated!

Thanks!
-Philip

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

看透却不说透 2024-11-08 16:01:48

你可以使用mapcat得到你想要的东西。我相信将它放入实际的 Clojure 集合中将会消除它的惰性,正如 (take 10 (set (iterate inc 0))) 尝试在 take 之前实现整个集合的事实所证明的那样10.

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

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

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

您最终会得到一个 seq,而不是一个集合,但由于听起来您确实想要在这里懒惰,所以我认为这是最好的。

You can get what you want by using mapcat. I believe putting it into an actual Clojure set is going to de-lazify it, as demonstrated by the fact that (take 10 (set (iterate inc 0))) tries to realize the whole set before taking 10.

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

This will give you a lazy sequence. You can verify that by doing something like, starting with an infinite sequence:

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

You'll end up with a seq, rather than a set, but since it sounds like you really want laziness here, I think that's for the best.

孤芳又自赏 2024-11-08 16:01:48

这可能有更好的堆栈行为

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

This may have better stack behavior

(defn get-all-origlabels []
    (reduce (fn (s x) (union s (get-origlabels x))) ${} (range *song-count*)))
欢你一世 2024-11-08 16:01:48

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

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

一般来说,“into”在构建 Clojure 数据结构时非常有用。我的脑海中浮现出这样的画面:传送带(一个序列)将一堆随机物体放入一个大桶(目标集合)中。

I'd probably use something like:

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

In general, "into" is very helpful when constructing Clojure data structures. I have this mental image of a conveyor belt (a sequence) dropping a bunch of random objects into a large bucket (the target collection).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文