在Clojure中加入多个懒惰的字符串序列

Mir*_*lov 2 string concatenation clojure lazy-sequences

我有几个字符串:

(def a "some random string")
(def b "this is a text")
Run Code Online (Sandbox Code Playgroud)

现在我想连接它们的一部分来创建一个字符串"some text".不幸的是,下面的两个字符串都不起作用.

(clojure.string/join " " [(take 4 a) (take-last 4 b)])
(str (take 4 a) " " (take-last 4 b))
Run Code Online (Sandbox Code Playgroud)

这是因为函数taketake-last返回延迟序列.问题是:连接多个懒惰的字符串序列并返回一个字符串的正确方法是什么?

编辑:我找到了一个解决方案 - (apply str (concat (take 4 a) " " (take-last 4 a)))- 但这是最​​正确的方法吗?

Mic*_*zyk 6

而不是使用顺序功能切片输入字符串,你可能想用多少更有效subs(子字符串;注意有一个关于它的GC相关的警告,见下文):

(subs "asdf" 1 2)
; => "s"

;; a and b as in the question text
(clojure.string/join " " [(subs a 0 4) (subs b (- (count b) 4))])
; => "some text"
Run Code Online (Sandbox Code Playgroud)

前面提到的警告是,只要"s"在这里的第一个示例中返回的内容仍然不符合垃圾回收的条件,原始内容也是如此"asdf"(因为subsString不分配新存储的情况下将"视图"返回到输入- 这是Java的substring方法subs包装的行为).如果您立即将其"s"关闭subs并保留其他任何引用,这不是问题,因为join在拉动字符后将丢弃它.

如果你最终总是使用懒惰的字符序列,那么就没有什么可以做的,而是使用类似的东西(map (partial apply str) [...your vector here...])将输入转换clojure.string/join为字符串.