为什么我的字符串函数返回clojure.lang.LazySeq@xxxxxx



使用leiningen REPL定义了以下3个函数:

(defn rand-int-range [floor ceiling] (+ floor (rand-int (- ceiling floor))))

(defn mutate-index
  "mutates one index in an array of char and returns the new mutated array"
  [source idx]
  (map
    #(if (= %1 idx)
       (char (+ (int %2) (rand-int-range -3 3)))
       %2)
    (iterate inc 0)
    source))
(defn mutate-string
  [source]
  (str
    (mutate-index
      (.toCharArray source)
      (rand-int (alength (.toCharArray source))))))

当我运行(mutate-string "hello")时,REPL不是打印出变异的字符串,而是打印出clojure.lang。LazySeq@xxxxxx,其中"xxxxx"是数字和字母的随机序列。我希望它输出像"hellm"这样的东西,这真的像我想的那样返回一个字符串吗?如果是,我如何让REPL显示该字符串?

1)要将字符序列(这是mutate-index返回的)转换为字符串,使用apply str而不仅仅是str。后者操作对象,而不是序列。

(str [a b c])
=> "[\a \b \c]"
(apply str [a b c])
=> "abc"

2)字符串是可序列的,这意味着你可以直接在它们上使用像mapfilter这样的序列函数,而不需要像.toCharArray这样的东西。

3)考虑使用map-indexedStringBuilder来完成你想做的事情:

(apply str (map-indexed (fn [i c] (if (= 3 i) X c)) "foobar"))
=> "fooXar"
(str (doto (StringBuilder. "foobar") (.setCharAt 3 X)))
=> "fooXar"

会发生这种情况,因为map函数返回一个惰性序列,其字符串表示只是类名和散列(clojure.lang.LazySeq@xxxxxx)。

为了得到原始的工作,你需要首先得到惰性序列的求值。通过使用(apply str…),就像Justin建议的那样,应该会发生,你应该得到正确的结果。

否则,通常如果您看到由于没有计算惰性序列而导致的类似问题,您应该尝试函数doall,它强制计算惰性序列

每当我想获得延迟序列的字符串值时,我使用clojure.core/pr-str:

user=> (clojure.tools.logging/infof "This is a lazy seq [%s]" (take 5 (range 100)))
INFO  user - This is a lazy seq [clojure.lang.LazySeq@1b554e1]
nil
user=> (clojure.tools.logging/infof "This is a lazy seq [%s]" (pr-str (take 5 (range 100))))
INFO  user - This is a lazy seq [(0 1 2 3 4)]
nil

最新更新