当前位置: 首页 > 知识库问答 >
问题:

我可以一步一步地处理一个未实现的懒惰序列吗

薄高懿
2023-03-14
(defn gen-lazy-seq [size]
  (for [i (range size)]
    (do
      (Thread/sleep 1000)
      (rand-int 10))))
(doseq [item (gen-lazy-seq 10)]
  (println item))

(for [item (gen-lazy-seq 10)]
  (println item))

这两个表达式都将等待10秒,然后才打印出任何内容。我已经将doall和dorun作为解决方案,但它们要求lazy-seq生产函数包含println。我想分别定义一个lazy-seq生产函数和lazy-seq打印函数,并使它们逐项协同工作。

尝试这样做的动机:我有来自网络的消息,我希望在所有消息都收到之前就开始处理它们。同时,最好将与查询对应的所有消息保存在一个lazy-seq中。

编辑1:

(defn seq1 [s]
  (lazy-seq
    (when-let [[x] (seq s)]
      (cons x (seq1 (rest s))))))

(let [start-time (java.lang.System/currentTimeMillis)]
  (doseq [item (seq1 (gen-lazy-seq 10))]
    (let [elapsed-time (- (java.lang.System/currentTimeMillis) start-time)]
      (println "time: " elapsed-time "item: " item))))

; output:
time:  10002 item:  1
time:  10002 item:  8
time:  10003 item:  9
time:  10003 item:  1
time:  10003 item:  7
time:  10003 item:  2
time:  10004 item:  0
time:  10004 item:  3
time:  10004 item:  5
time:  10004 item:  0
; output:
time:  1002 item:  4
time:  2002 item:  1
time:  3002 item:  6
time:  4002 item:  8
time:  5002 item:  8
time:  6002 item:  4
time:  7002 item:  5
time:  8002 item:  6
time:  9003 item:  1
time:  10003 item:  4

不仅仅是用它生成的序列有这个问题。无论seq1换行如何,都不能逐步处理用map生成的这个序列:

(defn gen-lazy-seq [size]
  (map (fn [_] 
         (Thread/sleep 1000)
         (rand-int 10))
       (range 0 size)))

但是这个序列,也是用map创建的:

(defn gen-lazy-seq [size] 
  (map (fn [_] 
         (Thread/sleep 1000)
         (rand-int 10))
       (repeat size :ignored)))

共有1个答案

仲柏
2023-03-14

Clojure的懒惰序列通常是分块的。如果采用较大的大小,您可以在示例中看到分块在工作(在这种情况下,这将有助于减少线程Hibernate时间)。另见这些相关的SO帖子。

虽然for似乎是分块的,但以下内容并不是按需要工作的:

(defn gen-lazy-seq [size]
  (take size (repeatedly #(do (Thread/sleep 1000)
                              (rand-int 10)))))

(doseq [item (gen-lazy-seq 10)]
  (println item)) 

“我有来自网络的消息,我想在所有消息都收到之前开始处理它们。”分块或不分块,如果你懒洋洋地处理它们,实际上应该是这样。

 类似资料:
  • 问题内容: 随着去除传统的C风格的for循环雨燕3.0的,我该怎么办下面? 在Python中,for-in控制流语句具有可选的step值: 但是Swift范围运算符似乎没有等效项: 问题答案: “步骤”的Swift同义词是“跨步”(stride)- 实际上是可跨步协议,由许多常见的数值类型实现。 等效于: 或者,要获取等价的,请使用变体: 请注意,返回/ ,这符合,所以任何你可以用序列做,你可以用

  • 本文向大家介绍一步一步实现iOS主题皮肤切换效果,包括了一步一步实现iOS主题皮肤切换效果的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了iOS主题皮肤切换代码,供大家参考,具体内容如下 1. 主题皮肤功能切换介绍 主题切换就是根据用户设置不同的主题,来动态改变用户的界面,通常会改变navigationBar背景图片、tabBar背景图片、tabBar中的按钮的图片和选中的背景图片、

  • 我一直在研究如何改变c#方法执行的行为,特别是当出现异常以支持: 重试/继续:能够再次尝试同一语句并在成功后继续跳过/继续:移动到下一个语句并继续执行 我读过很多回复,说这是糟糕的编码实践,但这是针对代码转换器的,它从支持此功能的语言转换数百万行代码。我需要在功能上保持一致。

  • 我无法理解页面翻译机制。我保存在yml文件翻译中的特定语言的翻译可以通过两种方式获得: 在会话中保留当前选定的翻译 只有在什么时候语言才会改变?我创建了一个单独的控制器,使用GET将参数传递给该控制器,并在控制器中执行代码? 为了不在任何控制器中编写相同的代码,我应该有一个只更改语言并将页面返回到上一个页面的控制器。仅通过重定向返回到上一页不会使用新语言传递请求,只有文档中给出的类使用默认语言。

  • 问题内容: 每次执行一次,在执行代码时,屏幕似乎都被锁定了几秒钟。因此,我通常在放置线程的同时在单独的线程中完成所有工作,以便用户知道发生了什么。 我最近遇到了以下情况:我之一的输入取决于先前(+ parse)操作的结果。我不能只按顺序放两个,因为Android会将它们放到两个线程中并在没有完成第一个线程的情况下启动第二个线程。如果没有适当的输入(第一个的结果),第二个将使应用程序崩溃。 有没有办