Clojure中的echo程序可以用惰性无限序列构建吗?

Clojure中的echo程序可以用惰性无限序列构建吗?,clojure,echo,lazy-sequences,Clojure,Echo,Lazy Sequences,以以下程序为例: (defn echo-ints [] (doseq [i (->> (BufferedReader. *in*) (line-seq) (map read-string) (take-while integer?))] (println i))) 其思想是提示用户输入,如果是整数,则返回。然而,在这个特殊的程序中,几乎每秒钟的输入都不会立即被回响。相反

以以下程序为例:

(defn echo-ints []
  (doseq [i (->> (BufferedReader. *in*)
                 (line-seq)
                 (map read-string)
                 (take-while integer?))]
    (println i)))
其思想是提示用户输入,如果是整数,则返回。然而,在这个特殊的程序中,几乎每秒钟的输入都不会立即被回响。相反,程序将在一次处理两个输入之前等待其他输入。
这大概是幕后发生的一些性能调整的结果。然而,在这种情况下,我真的希望有一个即时的反馈循环。是否有一种简单的方法来实现这一点,或者程序的逻辑是否必须进行重大更改?

(这里的主要动机是将用户输入的无限序列传递给另一个函数
f
,该函数将惰性序列转换为其他惰性序列。如果我编写了某种while循环,我将无法使用
f

通常情况下,将懒散与副作用混为一谈是不好的(在这种情况下打印),因为大多数序列函数都有内置的优化,这些优化在功能上仍然正确的同时会导致意外的效果

下面是一篇很好的评论:


您尝试执行的操作似乎非常适合core.async通道。我认为问题在于“用户输入流”而不是“用户输入的无限序列”,而“f将惰性序列转换为惰性序列”变成了“f将一个流转换为另一个流”。这将允许您将f作为传感器写入,您可以任意编写。

我将按照以下方式编写。注意:我们使用
spyx
spyxx
来显示一些结果

首先,编写一个包含固定测试数据的简单版本:

(ns tst.demo.core
  (:use tupelo.test)
  (:require
    [tupelo.core :as t] )
  (:import [java.io BufferedReader StringReader]))
(t/refer-tupelo)

(def user-input
 "hello
  there
  and
  a
  1
  and-a
  2
  and
  a
  3.14159
  and-a
  4
  bye" )

(defn echo-ints
  [str]
  (let [lines (line-seq (BufferedReader. (StringReader. str)))
        data  (map read-string lines)
        nums  (filter integer? data) ]
    (doseq [it data]
      (spyxx it))
    (spyx nums)))
(newline)
(echo-ints user-input)
这给了我们以下结果:

it => <#clojure.lang.Symbol hello>
it => <#clojure.lang.Symbol there>
it => <#clojure.lang.Symbol and>
it => <#clojure.lang.Symbol a>
it => <#java.lang.Long 1>
it => <#clojure.lang.Symbol and-a>
it => <#java.lang.Long 2>
it => <#clojure.lang.Symbol and>
it => <#clojure.lang.Symbol a>
it => <#java.lang.Double 3.14159>
it => <#clojure.lang.Symbol and-a>
it => <#java.lang.Long 4>
it => <#clojure.lang.Symbol bye>

nums => (1 2 4)
接下来,我们编写一个无限循环来读取键盘。您需要在键盘上用CRTL-C终止此操作:

(ns demo.core
  (:require [tupelo.core :as t])
  (:import [java.io BufferedReader StringReader]))
(t/refer-tupelo)


(defn echo-ints-inf
  []
  (loop [lines (line-seq (BufferedReader. *in*))]
    (let [line      (first lines)
          remaining (rest lines)
          data      (read-string line)]
      (when (integer? data)
        (println "found:" data))
      (when (not-empty? remaining)
        (recur remaining)))))

(defn -main []
  (println "main - enter")
  (newline)
  (echo-ints-inf))
我们手动运行它:

~/clj > lein run
main - enter
hello
there
1

found: 1
and
a
2
found: 2
and-a
3
found: 3
further more
4
found: 4
^C
                                                                                                                                                                      ~/clj > 
~/clj > 

(读取行)
也会发生这种情况吗?
~/clj > lein run
main - enter
hello
there
1

found: 1
and
a
2
found: 2
and-a
3
found: 3
further more
4
found: 4
^C
                                                                                                                                                                      ~/clj > 
~/clj >