试图将 Clojure 运行 中的字符串拆分为惰性序列问题
Trying to split string in Clojure running into lazy seq problem
我正在解决一个问题,以读取包含以下行的文件:
A abcdefg
B bcdefgh
但我不断收到关于 Lazy Sequence 与 Java Charseq 不兼容的错误 ..
我试过了:
(def notlazy (doall lyne2))
然后以为我验证了:
(realized? notlazy)
true
但仍然:
(str/split notlazy #" ")
ClassCastException class clojure.lang.LazySeq cannot be cast to class
java.lang.CharSequence (clojure.lang.LazySeq is in unnamed module of
loader 'app'; java.lang.CharSequence is in module java.base of loader
'bootstrap') clojure.string/split (string.clj:219)
请帮忙!
str/split
的第一个参数必须是要拆分的 CharSequence
。据推测,您希望拆分序列中的每个输入行,您可以使用 map
而无需急切地评估输入序列:
(map (fn [line] (str/split line #" ")) lyne2)
稍微扩展一下之前的结果,我们有这个例子。您可以使用 this template project.
重现以下内容
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test)
(:require
[clojure.java.io :as io]
[tupelo.string :as str]
))
(def data-file
"A abcdefg
B bcdefgh
")
(dotest
; Version #1
(let [lines (line-seq (io/reader (str/string->stream data-file)))
lines2 (remove str/blank? lines)
lines3 (map str/trim lines2)
line-words (mapv #(str/split % #"\s+") lines3) ; "\s+" => "one or more whitespace chars"
]
(spyxx lines)
(spyxx lines2)
(spyxx lines3)
(spyxx line-words))
结果:
--------------------------------------
Clojure 1.10.2-alpha1 Java 15
--------------------------------------
Testing tst.demo.core
lines => <#clojure.lang.Cons ("A abcdefg" " B bcdefgh" " ")>
lines2 => <#clojure.lang.LazySeq ("A abcdefg" " B bcdefgh")>
lines3 => <#clojure.lang.LazySeq ("A abcdefg" "B bcdefgh")>
line-words => <#clojure.lang.PersistentVector [["A" "abcdefg"] ["B" "bcdefgh"]]>
这会显示每个结果的类型及其值。我们使用 string->stream
所以我们不需要设置一个虚拟文件来读取。
下面显示了它通常是如何用真实代码编写的(不是像版本 #1 那样的演示练习)。我们使用“thread-last”运算符,并编写单元测试来验证结果:
; Version #2
(let [result (->> data-file
(str/string->stream)
(io/reader)
(line-seq)
(remove str/blank?)
(map str/trim)
(mapv #(str/split % #"\s+"))) ; "\s+" => "one or more whitespace chars"
]
(is= result [["A" "abcdefg"] ["B" "bcdefgh"]])))
我正在解决一个问题,以读取包含以下行的文件:
A abcdefg
B bcdefgh
但我不断收到关于 Lazy Sequence 与 Java Charseq 不兼容的错误 ..
我试过了:
(def notlazy (doall lyne2))
然后以为我验证了:
(realized? notlazy)
true
但仍然:
(str/split notlazy #" ")
ClassCastException class clojure.lang.LazySeq cannot be cast to class
java.lang.CharSequence (clojure.lang.LazySeq is in unnamed module of
loader 'app'; java.lang.CharSequence is in module java.base of loader
'bootstrap') clojure.string/split (string.clj:219)
请帮忙!
str/split
的第一个参数必须是要拆分的 CharSequence
。据推测,您希望拆分序列中的每个输入行,您可以使用 map
而无需急切地评估输入序列:
(map (fn [line] (str/split line #" ")) lyne2)
稍微扩展一下之前的结果,我们有这个例子。您可以使用 this template project.
重现以下内容(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test)
(:require
[clojure.java.io :as io]
[tupelo.string :as str]
))
(def data-file
"A abcdefg
B bcdefgh
")
(dotest
; Version #1
(let [lines (line-seq (io/reader (str/string->stream data-file)))
lines2 (remove str/blank? lines)
lines3 (map str/trim lines2)
line-words (mapv #(str/split % #"\s+") lines3) ; "\s+" => "one or more whitespace chars"
]
(spyxx lines)
(spyxx lines2)
(spyxx lines3)
(spyxx line-words))
结果:
--------------------------------------
Clojure 1.10.2-alpha1 Java 15
--------------------------------------
Testing tst.demo.core
lines => <#clojure.lang.Cons ("A abcdefg" " B bcdefgh" " ")>
lines2 => <#clojure.lang.LazySeq ("A abcdefg" " B bcdefgh")>
lines3 => <#clojure.lang.LazySeq ("A abcdefg" "B bcdefgh")>
line-words => <#clojure.lang.PersistentVector [["A" "abcdefg"] ["B" "bcdefgh"]]>
这会显示每个结果的类型及其值。我们使用 string->stream
所以我们不需要设置一个虚拟文件来读取。
下面显示了它通常是如何用真实代码编写的(不是像版本 #1 那样的演示练习)。我们使用“thread-last”运算符,并编写单元测试来验证结果:
; Version #2
(let [result (->> data-file
(str/string->stream)
(io/reader)
(line-seq)
(remove str/blank?)
(map str/trim)
(mapv #(str/split % #"\s+"))) ; "\s+" => "one or more whitespace chars"
]
(is= result [["A" "abcdefg"] ["B" "bcdefgh"]])))