Подтвердить что ты не робот

Поместите элемент в хвост коллекции

Я нахожу, что делаю много:

(concat coll [e]) где coll - это коллекция, а e - один элемент.

Есть ли функция для этого в Clojure? Я знаю, что conj делает работу лучше всего для векторов, но я не знаю, какой фронт будет использоваться. Это может быть вектор, список или отсортированный набор, например.

4b9b3361

Ответ 1

Некоторые типы коллекций могут добавить дешево на передний план (списки, seq), в то время как другие могут добавить дешево обратно (векторы, очереди, sorta-sorta lazy-seqs). Вместо использования concat, если возможно, вам следует организовать работу с одним из этих типов (вектор является наиболее распространенным) и просто сопрягаться с ним: (conj [1 2 3] 4) дает [1 2 3 4], а (conj '(1 2 3) 4) дает (4 1 2 3).

Ответ 2

concat не добавляет элемент в хвост коллекции и не объединяет две коллекции.

concat возвращает seq из конкатенации двух других секций. Исходный тип коллекций, из которых могут быть выведены seqs, теряется для возвращаемого типа concat.

Теперь коллекции clojure имеют разные свойства, о которых нужно знать, чтобы писать эффективный код, поэтому в ядре нет универсальной функции для объединения коллекций любого типа вместе. Напротив, список и векторы имеют "естественные позиции вставки", которые конно знает, и делает то, что подходит для вида коллекции.

Ответ 3

Чтобы перегонять лучшее из того, что сказал амаллоя, и Лоран Пети уже сказал: используйте функцию conj.

Одна из больших абстракций, которые предоставляет Clojure, - это API-интерфейс последовательности, который включает в себя функцию conj. Если это вообще возможно, ваш код должен быть агностиком типа коллекции, как он может быть, вместо этого использовать seq API для обработки операций с коллекциями и выбора определенного типа коллекции только тогда, когда вам нужно быть конкретным.

Если векторы соответствуют друг другу, то да, conj будет добавлять элементы в конец. Если вместо этого используются списки использования, то conj будет добавлять вещи в начало вашей коллекции. Но если вы затем используете стандартные функции API SEQ для вытягивания элементов из "вершины" коллекции (обратная сторона вектора, перед списком), не имеет значения, какую реализацию вы используете, потому что она всегда будет использовать один с лучшей производительностью и, таким образом, добавление и удаление элементов будет согласованным.

Ответ 4

Это очень небольшое добавление к ответу @amalloy, чтобы адресовать запрос OP для функции, которая всегда добавляет к хвосту любой коллекции. Это альтернатива (concat coll [x]). Просто создайте векторную версию оригинальной коллекции:

(defn conj*
  [s x]
  (conj (vec s) x))

Предостережения:

Если вы начали с ленивой последовательности, вы теперь уничтожили лень - т.е. выход не ленив. Это может быть хорошо или плохо, в зависимости от ваших потребностей.

Там некоторые затраты на создание вектора. Если вам нужно много раз называть эту функцию, и вы находите (например, сравнивая с Criterium), что эта стоимость значительна для ваших целей, затем следуйте рекомендациям других ответов, чтобы попытаться использовать векторы в первую очередь.