【问题标题】:Trying to split string in Clojure running into lazy seq problem尝试在 Clojure 中拆分字符串时遇到惰性序列问题
【发布时间】:2020-12-08 17:35:58
【问题描述】:

我正在解决一个读取文件的问题:

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)

请帮忙!

【问题讨论】:

    标签: clojure lazy-evaluation lazy-sequences


    【解决方案1】:

    str/split 的第一个参数必须是要拆分的 CharSequence。大概你想分割序列中的每一行输入,你可以使用map,而不需要急切地评估输入序列:

    (map (fn [line] (str/split line #" ")) lyne2)
    

    【讨论】:

      【解决方案2】:

      稍微扩展一下之前的结果,我们有这个例子。您可以使用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-&gt;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"]])))
      

      【讨论】:

        猜你喜欢
        • 2011-06-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-05
        相关资源
        最近更新 更多