Какова стоимость преобразования между последовательностями и векторами? - PullRequest
2 голосов
/ 06 августа 2020

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

(into [] (filter my-pred my-vec))

Или:

(vec (filter my-pred my-vec))

Хотя я не уверен, есть ли значимая разница между ними.

Эта операция дорогая или вы получаете ее бесплатно, как при конвертации в / из переходного процесса?

Я понимаю, что seq является ленивым, поэтому на самом деле ничего не будет вычислено, пока вы не вставите его в выходной вектор, но есть ли накладные расходы на преобразование из seq и конкретной коллекции? Можно ли его охарактеризовать в терминах «большого О», или «Большое О» здесь не имеет смысла? А как насчет другого пути при преобразовании из вектора в последовательность?

Ответы [ 2 ]

4 голосов
/ 06 августа 2020

На сайте Clojure есть FAQ для хороших вариантов использования преобразователей , которые могут быть полезны для некоторых сложных преобразований (больше, чем просто фильтрация или когда предикат довольно сложен). В противном случае вы можете использовать filterv , который находится в основной библиотеке, и вы можете предположить, что он делает любую разумную оптимизацию для вас.

1 голос
/ 06 августа 2020

TL; DR Не беспокойтесь об этом

Более длинная версия:

  1. Основные затраты - это выделение памяти / G C. Обычно это тривиально. Если у вас слишком много данных для одновременного размещения в ОЗУ, ленивая версия может вас спасти.

  2. Если вы хотите измерить проблемы с игрушками, вы можете поэкспериментировать с библиотекой Criterium . Попробуйте использовать степени 10 от 10 ^ 2 до 10 ^ 9.

(crit/quick-bench (println :sum (reduce + 0 (into [] (range (Math/pow 10 N))))))

для N = 2..9 с частью (into [] ...) и без нее.

...