此代码无法正常工作。你能解释一下原因吗?
(defn make-str [s c]
(let [my-str (ref s)]
(dosync (alter my-str str c))))
(defn make-str-from-chars
"make a string from a sequence of characters"
([chars] make-str-from-chars chars "")
([chars result]
(if (== (count chars) 0) result
(recur (drop 1 chars) (make-str result (take 1 chars))))))
谢谢!
答案 0 :(得分:12)
这是非常慢的&从seq of characters创建字符串的错误方法。主要问题是,更改不会传播 - ref会创建对现有字符串的新引用,但在从函数退出后,引用将被销毁。
正确的方法是:
(apply str seq)
例如,
user=> (apply str [\1 \2 \3 \4])
"1234"
如果你想让它更有效,那么你可以使用Java的StringBuilder来收集字符串中的所有数据。 (Java中的字符串也是不可变的)
答案 1 :(得分:11)
将包含一个字符的序列传递给make-str
函数,而不是字符本身。使用first
代替take
会给您带来理想的效果。
此外,无需使用参考。实际上,你对它们的使用是对它们的严重滥用。您已在函数中使用累加器,因此可以直接使用str
。
(defn make-str-from-chars
"make a string from a sequence of characters"
([chars] (make-str-from-chars chars ""))
([chars result]
(if (zero? (count chars))
result
(recur (drop 1 chars) (str result (first chars))))))
当然count
在这种情况下不是很好,因为它总是需要遍历整个序列来计算它的长度。因此,您不必要地多次遍历输入序列。通常使用seq
来识别序列何时耗尽。我们还可以使用next
而不是drop
来节省创建不必要的序列对象的一些开销。请务必捕获seq
的返回值,以避免以后创建对象的开销。我们在if-let
。
(defn make-str-from-chars
"make a string from a sequence of characters"
([chars] (make-str-from-chars chars ""))
([chars result]
(if-let [chars (seq chars)]
(recur (next chars) (str result (first chars)))
result)))
这样的函数,它只是在完全消耗它的输入时返回累加器,为reduce
而哭泣。
(defn make-str-from-chars
"make a string from a sequence of characters"
[chars]
(reduce str "" chars))
这已经很好而且简短,但在这种特殊情况下,我们可以使用apply
做得更好。然后str
可以使用基础StringBuilder
来充分发挥其力量。
(defn make-str-from-chars
"make a string from a sequence of characters"
[chars]
(apply str chars))
希望这有帮助。
答案 2 :(得分:2)
您还可以使用 clojure.string / join ,如下所示:
(require '[clojure.string :as str] )
(assert (= (vec "abcd") [\a \b \c \d] ))
(assert (= (str/join (vec "abcd")) "abcd" ))
还有一种替代形式的 clojure.string / join ,它接受一个分隔符。参见: