简体   繁体   English

使用列表或向量,我的Clojure功能可能会非常慢吗?

[英]Is my Clojure function likely to be very slow with lists or vectors?

I'm just learning Clojure and I just wrote this function: 我刚刚学习Clojure,我刚刚编写了这个函数:

(defn replace-last [coll value]
    (assoc coll (dec (count coll)) value))

I'm just a little concerned that it's likely to be really slow for either lists and/or vectors — I just don't understand them enough yet to know. 我只是有点担心它对于列表和/或向量来说可能真的很慢 - 我只是不了解它们还不知道。

Thanks! 谢谢!

For vectors, this will be pretty fast -- one of the promises of vectors is fast creation of slightly modified copies. 对于向量,这将非常快 - 向量的一个承诺是快速创建略微修改的副本。

For lists, this won't work at all -- they are not associative ( clojure.lang.Associative ) and thus are not valid arguments to assoc . 对于列表,这根本不起作用 - 它们不是关联的( clojure.lang.Associative ),因此不是assoc有效参数。 As for other possible approaches, if you need to get an actual list back (as opposed to a seq(able)), you're out of luck -- accessing / replacing the final element of a list is fundamentally a linear time operation. 至于其他可能的方法,如果你需要获得一个实际的列表(而不是seq(能)),你运气不好 - 访问/替换列表的最后一个元素基本上是一个线性时间操作。 If, on the other hand, you'd be ok with a lazy seq which would look like your list except for the final element, you could implement a semi-lazy variant of butlast (the one in clojure.core is not lazy at all) and use that with lazy-cat : 另一方面,如果你可以使用懒惰的seq,除了最后一个元素之外你看起来像你的列表,你可以实现butlast的半惰性变体( clojure.corebutlast并不是懒惰的)并与lazy-cat

(defn semi-lazy-butlast [s]
  (cond (empty? s) s
        (empty? (next s)) nil ; or perhaps ()
        :else (lazy-seq (cons (first s)
                              (semi-lazy-butlast (next s))))))

(defn replace-last [s x]
  (if (empty? s) ; do nothing if there is no last element to replace
    s
    (lazy-cat (semi-lazy-butlast s) [x])))

This defers replacing the final element until you actually get close to it in consuming your seq. 这会延迟更换最终元素,直到你实际接近消耗你的seq。

A sample interaction: 示例交互:

user=> (take 10 (replace-last (range) :foo))
(0 1 2 3 4 5 6 7 8 9)
user=> (take 10 (replace-last (range 10) :foo))
(0 1 2 3 4 5 6 7 8 :foo)
user=> (replace-last () :foo)
()

对于向量,这将与其他任何内容一样快,并且对列表不起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM