Почему вы не можете найти RSeq?
user=> (rseq [:a :b])
(:b :a)
user=> (rseq (rseq [:a :b]))
ClassCastException clojure.lang.APersistentVector$RSeq cannot be cast to
clojure.lang.Reversible clojure.core/rseq (core.clj:1532)
Почему не могу rseq
принять результат предыдущего вызова rseq
?
Я прочитал в строке документации, что аргумент должен быть (на самом деле, "может быть") вектором или отсортированной картой, и приведенное выше показывает, что он не может быть RSeq
так что я уже это знаю. Что я хочу знать: есть ли веская причина для такого ограничения? Это просто недосмотр или это ограничение дает какое-то важное преимущество?
Кроме того, есть ли удобный обходной путь для этого, кроме как никогда не звонить rseq
? Трудно знать, когда вы возвращаете RSeq
из одной функции, может ли какая-то другая функция где-то еще вызвать rseq
в теме.
Я спрашиваю, потому что расстраивает то, что мой код генерирует исключения по такой удивительной причине. Если бы я знал, почему это имело смысл, я мог бы с меньшей вероятностью совершать подобные и подобные ошибки.
2 ответа
Вы не можете позвонить rseq
на последующем, так как вам нужен входной набор с постоянным произвольным доступом к fullfill rseq
Характеристики производительности в постоянном времени, а секвенс обеспечивает эффективный доступ (итерацию) из головы вниз.
призвание rseq
на результат rseq
не может быть в специальном случае возвращать исходную коллекцию, поскольку исходная коллекция никогда не является последовательной. А если звонит rseq
на RSeq вернул бы что-нибудь (seq coll)
, это не будет просто поддерживать (rseq (drop x (rseq coll)))
, Вероятно, именно такие сложности не позволили разработчикам языка вообще поддерживать "рекурсивный" rseq.
Если вам нужна общая функция обращения, используйте reverse
- который будет медленнее. Если вы можете, вы, вероятно, просто хотите сохранить ссылку на (seq coll)
а также (rseq coll)
если вам нужно оба.
Так как rseq
работает только для специальных обратимых последовательностей. Но результатом его применения является обычная последовательность. Вы всегда можете проверить, можете ли вы rseq
последовательность с reversible?
сказуемое:
(defn reverse* [s]
(if (reversible? s)
(rseq s)
(reverse s)))
Почему этот запасной вариант не в rseq
(или же reverse
) сама функция? Причина в том, что rseq
Я должен гарантировать предсказуемость времени его исполнения.
Если вам действительно нужно позже вернуться к коллекции, лучше сохранить ее как вектор, например: (rseq (vec (rseq [1 2 3])))