5 string state clojure sequence
此代码无法正常工作.你能解释一下原因吗?
(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))))))
Run Code Online (Sandbox Code Playgroud)
谢谢!
Ale*_*Ott 12
这是从seq of characters创建字符串的非常慢且不正确的方法.主要问题是,更改不会传播 - ref会创建对现有字符串的新引用,但在从函数退出后,引用将被销毁.
正确的方法是:
(apply str seq)
Run Code Online (Sandbox Code Playgroud)
例如,
user=> (apply str [\1 \2 \3 \4])
"1234"
Run Code Online (Sandbox Code Playgroud)
如果你想让它更有效,那么你可以使用Java的StringBuilder来收集字符串中的所有数据.(Java中的字符串也是不可变的)
kot*_*rak 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))))))
Run Code Online (Sandbox Code Playgroud)
当然,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)))
Run Code Online (Sandbox Code Playgroud)
像这样的函数,它只是在完全消耗它的输入时返回累加器,为之哭泣reduce.
(defn make-str-from-chars
"make a string from a sequence of characters"
[chars]
(reduce str "" chars))
Run Code Online (Sandbox Code Playgroud)
这已经很好而且简短,但在这种特殊情况下,我们可以通过使用来做得更好apply.然后str可以使用底层StringBuilder的全部功率.
(defn make-str-from-chars
"make a string from a sequence of characters"
[chars]
(apply str chars))
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助.