Может ли моя функция Clojure работать очень медленно со списками или векторами? - PullRequest
4 голосов
/ 17 января 2012

Я только изучаю Clojure и только что написал эту функцию:

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

Я просто немного обеспокоен тем, что это может быть очень медленным для обоих списков и / или векторов - я просто еще недостаточно понимаю их, чтобы знать.

Спасибо!

Ответы [ 2 ]

11 голосов
/ 17 января 2012

Для векторов это будет довольно быстро - одно из обещаний векторов - быстрое создание слегка модифицированных копий.

Для списков это не будет работать вообще - они не ассоциативны (clojure.lang.Associative) и, следовательно, не являются допустимыми аргументами для assoc. Что касается других возможных подходов, если вам нужно вернуть реальный список (в отличие от seq (способного)), вам не повезло - доступ / замена последнего элемента списка по сути является линейной операцией времени. Если, с другой стороны, вы будете в порядке с ленивым seq, который будет выглядеть как ваш список, за исключением последнего элемента, вы можете реализовать полуленивый вариант butlast (тот, что в clojure.core, не ленивый и используйте это с 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])))

Это откладывает замену последнего элемента до тех пор, пока вы фактически не приблизитесь к нему в использовании своей последовательности.

Пример взаимодействия:

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)
()
3 голосов
/ 17 января 2012

Это будет так же быстро, как и для векторов, и не будет работать вообще для списков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...