在REPL中实现Clojure惰性序列(string)

在REPL中实现Clojure惰性序列(string),clojure,lazy-evaluation,lazy-sequences,Clojure,Lazy Evaluation,Lazy Sequences,我试图在REPL中实现一个惰性序列(它应该生成一个字符串),但运气不好。原始代码工作正常: (def word_list ["alpha" "beta" "gamma" "beta" "alpha" "alpha" "beta" "beta" "beta"]) (def word_string (reduce str (interpose " " word_list))); word_string ; "alpha beta gamma beta alpha alpha beta beta b

我试图在REPL中实现一个惰性序列(它应该生成一个字符串),但运气不好。原始代码工作正常:

(def word_list ["alpha" "beta" "gamma" "beta" "alpha" "alpha" "beta" "beta" "beta"])
(def word_string (reduce str (interpose " " word_list))); 
word_string ; "alpha beta gamma beta alpha alpha beta beta beta"
但我不想让它单独存在,我想知道还有什么办法可以用,于是尝试删除
reduce
,认为
str
可能也有同样的效果。它没有

(def word_string (str (interpose " " word_list)))
word_string ; "clojure.lang.LazySeq@304a9790"
我尝试了显而易见的方法,再次使用
reduce
,但也没用。这是关于实现看起来很有希望的惰性序列,但我尝试了什么都不起作用:

(reduce str word_string)   ; "clojure.lang.LazySeq@304a9790"
(apply str word_string)    ; "clojure.lang.LazySeq@304a9790"
(println word_string)      ; "clojure.lang.LazySeq@304a9790"
(apply list word_string)   ; [\c \l \o \j \u \r \e \. \l \a \n \g \. \L \a \z \y...]
(vec word_string)          ; [\c \l \o \j \u \r \e \. \l \a \n \g \. \L \a \z \y...]
(apply list word_string)   ; (\c \l \o \j \u \r \e \. \l \a \n \g \. \L \a \z \y...)
(take 100 word_string)     ; (\c \l \o \j \u \r \e \. \l \a \n \g \. \L \a \z \y...)
事实上,一些变体给了我“clojure.lang.LazySeq”中的字符,这也让我担心——我是否不知何故丢失了实际的字符串值,而我的引用只有值“clojure.lang.LazySeq”?如果没有,我如何真正实现价值

澄清一下:假设
word\u string
被分配给一个惰性序列,我将如何实现它?类似于
(实现单词字符串)
,比如说,如果存在的话

更新:根据公认的答案和
str
的工作原理,我可以得到实际的序列值,而不仅仅是它的名称:

(reduce str "" word_string) ; "alpha beta gamma beta alpha alpha beta beta beta"
是的,这是可怕的代码。:)我只是想了解发生了什么,它为什么会断裂,以及实际值是否仍然存在。

您想要的是:

(def word_string (apply str (interpose " " word_list)))
(clojure.string/join " " word_list)
查看
str
的文档:

如果没有参数,则返回空字符串。对于一个参数x,返回
x、 toString()。(str nil)返回空字符串。超过
一个参数,返回参数的str值的串联

因此,您正在对序列调用
.toString
,它生成该表示,而不是将
str
作为参数应用于序列的元素

顺便说一句,做你想做的事情更惯用的方式是:

(def word_string (apply str (interpose " " word_list)))
(clojure.string/join " " word_list)

此外,字符串不是惰性序列
interpose
返回一个惰性序列,您正在调用
.toString

在clojure中实现惰性seq不需要做任何特殊的事情,只需在任何需要seq的地方使用它即可

user=> (def word-list ["alpha" "beta" "gamma" "beta" "alpha" "alpha" "beta" "beta" "beta"])
#'user/word-list
user=> (def should-be-a-seq (interpose " " word_list))
#'user/should-be-a-seq
user=> (class should-be-a-seq)
clojure.lang.LazySeq
所以我们有一个seq,如果我在任何情况下使用它,它将遍历seq中的所有值,它最终将完全实现。e、 g

user=> (seq should-be-a-seq)
("alpha" " " "beta" " " "gamma" " " "beta" " " "alpha" " " "alpha" " " "beta" " " "beta" " " "beta")
它仍然是一个序列,事实上它仍然是以前的同一个对象

user=> (str should-be-a-seq)
"clojure.lang.LazySeq@304a9790"
正如Diego Basch提到的,对某个对象调用str就像调用.toString一样,对于LazySeq方法来说,它显然只是从对象继承的默认.toString

因为它是一个seq,所以您可以像任何seq一样使用它,不管它之前是否已经完全实现。e、 g

user=> (apply str should-be-a-seq)
"alpha beta gamma beta alpha alpha beta beta beta"
user=> (reduce str should-be-a-seq)
"alpha beta gamma beta alpha alpha beta beta beta"
user=> (str/join should-be-a-seq)
"alpha beta gamma beta alpha alpha beta beta beta"
user=> (str/join (map #(.toUpperCase %) should-be-a-seq))
"ALPHA BETA GAMMA BETA ALPHA ALPHA BETA BETA BETA"

我想我的问题还不清楚-我可以使用
reduce
word\u string
分配一个完全实现的字符串,尽管
apply
可能更好。但是考虑到
word\u string
被分配给一个惰性序列,我如何实现它呢?我会对
word\u string
应用什么操作,比如
(realization word\u string)
?我想你很困惑:word\u string的第二个赋值不是给一个惰性序列;这是一个字符串,它是在惰性序列上调用.toString的结果。惰性序列的字符串表示不是很有用,也不是您想要的。看这个问题:是的,我确实很困惑Clojure、惰性序列等有很多奇怪的、错误的、非直觉的方面,我仍在努力理解。然而,我想我看到了在这个案例中发生的事情,str并没有按照我最初的想法去做。谢谢。如果您像我一样使用
str
,尽管
(def-should-be-a-seq(str(interpose“word_list))
,但它的行为不同。我是否应该使用
str
当然是一个有效的问题,但我正在试图理解分配给
的内容(def word\u string(str(interpose“word\u list))
,以及如何操作它。@JohnC
str
返回一个字符串。在这种情况下,这不是你想要的字符串。