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 >