Clojure удаляет первый (или последний) элемент вектора внутри ref

То, что мне нужно, - это простая очередь, что-то, куда я могу ставить задачи и получать их одну за другой от рабочих (без поддержания порядка задач).

Я написал примерно так:

;; Definition
(def q (ref []))

;; Put
(defn put-in-queue [i]
  (dosync (alter q conj i)))

;; Get
(defn get-from-queue []
  (dosync
    (let [v (peek q)]
      (alter q pop)
      v)))

Это правильное решение? (может быть, есть и лучшие решения для этой задачи)


person h3x3d    schedule 16.10.2013    source источник


Ответы (3)


Правильным решением, вероятно, будет использование очереди java.util.concurrent, скорее всего _ 2_. j.u.c очереди надежны, идеально подходят для поставленных задач и прекрасно работают в Clojure.

См. мой ответ на Производитель-потребитель с квалификацией SO-вопрос для сценария с 5 производителями, 2 потребителями и очередью ограниченного размера, реализованной двумя способами для сравнения: первый с c.l.PersistentQueue, второй с j.u.c.LinkedBlockingQueue.

person Michał Marczyk    schedule 18.10.2013

Вы должны использовать clojure.lang.PersistentQueue, правильный инструмент для работы и все такое :).

Пример ниже "заимствован" из Скрытых возможностей Clojure:

user> (-> (clojure.lang.PersistentQueue/EMPTY)
          (conj 1 2 3)
          pop)
(2 3)

См. Подробности в оставшейся части этого ответа.

person dsm    schedule 16.10.2013

как указывает dsm, когда вам нужна очередь, используйте очередь, а в тех случаях, когда вам действительно нужен вектор и вы хотите добавить элементы в конец и удалить их спереди, subvec и conj являются функциями O (1) на векторов.

user> (subvec [1 2 3] 1)
[2 3]
user> (conj [1 2 3] 4)
[1 2 3 4]
user> (-> [] (conj 1 2) (conj 3) (subvec 1))
person Arthur Ulfeldt    schedule 16.10.2013
comment
Речь идет о многопоточном окружении, а не только о субвеке. - person h3x3d; 18.10.2013
comment
clojure.core/subvec удерживает базовый вектор, поэтому это предотвратит неограниченное получение права на сборку мусора для всех записей. (Напротив, clojure.core.rrb-vector/subvec действительно выполняет срез, отбрасывая записи за пределами заданного диапазона индексов.) - person Michał Marczyk; 18.10.2013