从字符序列创建字符串
这段代码没有按我的预期工作。您能解释一下原因吗?
(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))))))
谢谢你!
This code does not work as I expected. Could you please explain why?
(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))))))
Thank you!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这是非常慢的&从字符序列创建字符串的方法不正确。主要问题是更改不会传播 - ref 创建对现有字符串的新引用,但在退出函数后,引用将被销毁。
正确的做法是:
例如,
如果你想让它更有效,那么你可以使用Java的StringBuilder来收集字符串中的所有数据。 (Java中的字符串也是不可变的)
This is very slow & incorrect way to create string from seq of characters. The main problem, that changes aren't propagated - ref creates new reference to existing string, but after it exits from function, reference is destroyed.
The correct way to do this is:
for example,
If you want to make it more effective, then you can use Java's StringBuilder to collect all data in string. (Strings in Java are also immutable)
您将包含一个字符的序列传递给
make-str
函数,而不是字符本身。使用first
而不是take
应该会给您带来所需的效果。也不需要使用参考文献。实际上,您对它们的使用是对它们的严重滥用。您已经在函数中使用了累加器,因此可以直接使用
str
。当然,在这种情况下
count
并不是很好,因为它总是必须遍历整个序列才能算出其长度。因此,您不必要地多次遍历输入序列。人们通常使用seq
来识别序列何时耗尽。我们还可以使用next
而不是drop
来节省创建不必要的序列对象的一些开销。请务必捕获seq
的返回值,以避免稍后创建对象的开销。我们在if-let
中执行此操作。像这样的函数,在完全消耗其输入后仅返回累加器,迫切需要
reduce
。这已经很好很短了,但在这种特殊情况下,我们可以通过使用
apply
做得更好。然后str
可以充分利用底层StringBuilder
的功能。希望这有帮助。
You pass a sequence with one character in it to your
make-str
function, not the character itself. Usingfirst
instead oftake
should give you the desired effect.Also there is no need to use references. In effect your use of them is a gross misuse of them. You already use an accumulator in your function, so you can use
str
directly.Of course
count
is not very nice in this case, because it always has to walk the whole sequence to figure out its length. So you traverse the input sequence several times unnecessarily. One normally usesseq
to identify when a sequence is exhausted. We can also usenext
instead ofdrop
to save some overhead of creating unnecessary sequence objects. Be sure to capture the return value ofseq
to avoid overhead of object creations later on. We do this in theif-let
.Functions like this, which just return the accumulator upon fully consuming its input, cry for
reduce
.This is already nice and short, but in this particular case we can do even a little better by using
apply
. Thenstr
can use the underlyingStringBuilder
to its full power.Hope this helps.
您还可以使用 clojure.string/join,如下所示:
clojure.string/join 有另一种形式,它接受分隔符。请参阅:
http://clojuredocs.org/clojure_core/clojure.string/join
You can also use clojure.string/join, as follows:
There is an alternate form of clojure.string/join which accepts a separator. See:
http://clojuredocs.org/clojure_core/clojure.string/join