886886 (-iterator [coll]
887887 " Returns an iterator for coll." ))
888888
889+ (defprotocol IDrop
890+ " Protocol for persistent or algorithmically defined collections to provide a
891+ means of dropping N items that is more efficient than sequential walking."
892+ (^clj-or-nil -drop [coll n]
893+ " Returns a collection that is ISequential, ISeq, and IReduce, or nil if past
894+ the end. The number of items to drop n must be > 0. It is also useful if the
895+ returned coll implements IDrop for subsequent use in a partition-like scenario." ))
896+
889897; ; Printing support
890898
891899(deftype StringBufferWriter [sb]
@@ -1631,6 +1639,14 @@ reduces them without incurring seq initialization"
16311639 (IndexedSeq. arr (inc i) nil )
16321640 nil ))
16331641
1642+ IDrop
1643+ (-drop [coll n]
1644+ (if (pos? n)
1645+ (if (< (+ i n) (alength arr))
1646+ (IndexedSeq. arr (+ i n) nil )
1647+ nil )
1648+ coll))
1649+
16341650 ICounted
16351651 (-count [_]
16361652 (max 0 (- (alength arr) i)))
@@ -1949,10 +1965,14 @@ reduces them without incurring seq initialization"
19491965(defn nthrest
19501966 " Returns the nth rest of coll, coll when n is 0."
19511967 [coll n]
1952- (loop [n n xs coll]
1953- (if-let [xs (and (pos? n) (seq xs))]
1954- (recur (dec n) (rest xs))
1955- xs)))
1968+ (if (implements? IDrop coll)
1969+ (if (pos? n)
1970+ (or (-drop coll (Math/ceil n)) ())
1971+ coll)
1972+ (loop [n n xs coll]
1973+ (if-let [xs (and (pos? n) (seq xs))]
1974+ (recur (dec n) (rest xs))
1975+ xs))))
19561976
19571977(defn get
19581978 " Returns the value mapped to key, not-found or nil if key not present
@@ -2997,10 +3017,14 @@ reduces them without incurring seq initialization"
29973017(defn nthnext
29983018 " Returns the nth next of coll, (seq coll) when n is 0."
29993019 [coll n]
3000- (loop [n n xs (seq coll)]
3001- (if (and xs (pos? n))
3002- (recur (dec n) (next xs))
3003- xs)))
3020+ (if (implements? IDrop coll)
3021+ (if (pos? n)
3022+ (-drop coll (Math/ceil n))
3023+ (seq coll))
3024+ (loop [n n xs (seq coll)]
3025+ (if (and xs (pos? n))
3026+ (recur (dec n) (next xs))
3027+ xs))))
30043028
30053029; ;;;;;;;;;;;;;;;;;;;;;;;;; basics ;;;;;;;;;;;;;;;;;;
30063030
@@ -4828,7 +4852,7 @@ reduces them without incurring seq initialization"
48284852 (cons (first s) (take (dec n) (rest s))))))))
48294853
48304854(defn drop
4831- " Returns a lazy sequence of all but the first n items in coll.
4855+ " Returns a laziness-preserving sequence of all but the first n items in coll.
48324856 Returns a stateful transducer when no collection is provided."
48334857 ([n]
48344858 {:pre [(number? n)]}
@@ -4845,12 +4869,18 @@ reduces them without incurring seq initialization"
48454869 (rf result input))))))))
48464870 ([n coll]
48474871 {:pre [(number? n)]}
4848- (let [step (fn [n coll]
4849- (let [s (seq coll)]
4850- (if (and (pos? n) s)
4851- (recur (dec n) (rest s))
4852- s)))]
4853- (lazy-seq (step n coll)))))
4872+ (if (implements? IDrop coll)
4873+ (or
4874+ (if (pos? n)
4875+ (-drop coll (Math/ceil n))
4876+ (seq coll))
4877+ ())
4878+ (let [step (fn [n coll]
4879+ (let [s (seq coll)]
4880+ (if (and (pos? n) s)
4881+ (recur (dec n) (rest s))
4882+ s)))]
4883+ (lazy-seq (step n coll))))))
48544884
48554885(defn drop-last
48564886 " Return a lazy sequence of all but the last n (default 1) items in coll"
@@ -5019,6 +5049,14 @@ reduces them without incurring seq initialization"
50195049 ICollection
50205050 (-conj [coll o] (cons o coll))
50215051
5052+ IDrop
5053+ (-drop [coll n]
5054+ (if (== count -1 )
5055+ coll
5056+ (let [dropped-count (- count n)]
5057+ (when (pos? dropped-count)
5058+ (Repeat. nil dropped-count val nil nil )))))
5059+
50225060 IEmptyableCollection
50235061 (-empty [coll] (.-EMPTY List))
50245062
@@ -5645,6 +5683,13 @@ reduces them without incurring seq initialization"
56455683 (<= cnt 32 ) (IndexedSeq. tail 0 nil )
56465684 :else (chunked-seq coll (first-array-for-longvec coll) 0 0 )))
56475685
5686+ IDrop
5687+ (-drop [coll n]
5688+ (if (< n cnt)
5689+ (let [offset (js-mod n 32 )]
5690+ (chunked-seq coll (unchecked-array-for coll n) (- n offset) offset))
5691+ nil ))
5692+
56485693 ICounted
56495694 (-count [coll] cnt)
56505695
@@ -5849,6 +5894,17 @@ reduces them without incurring seq initialization"
58495894 s))
58505895 (-chunked-next coll)))
58515896
5897+ IDrop
5898+ (-drop [coll n]
5899+ (let [o (+ off n)]
5900+ (if (< o (alength node))
5901+ (chunked-seq vec node i o)
5902+ (let [i (+ i o)]
5903+ (if (< i (-count vec))
5904+ (let [new-offset (js-mod i 32 )]
5905+ (chunked-seq vec (unchecked-array-for vec i) (- i new-offset) new-offset))
5906+ nil )))))
5907+
58525908 ICollection
58535909 (-conj [coll o]
58545910 (cons o coll))
@@ -6864,6 +6920,11 @@ reduces them without incurring seq initialization"
68646920 (when (< i (- (alength arr) 2 ))
68656921 (PersistentArrayMapSeq. arr (+ i 2 ) nil )))
68666922
6923+ IDrop
6924+ (-drop [coll n]
6925+ (when (< n (-count coll))
6926+ (PersistentArrayMapSeq. arr (+ i (* 2 n)) nil )))
6927+
68676928 IReduce
68686929 (-reduce [coll f] (seq-reduce f coll))
68696930 (-reduce [coll f start] (seq-reduce f start coll)))
@@ -6964,6 +7025,11 @@ reduces them without incurring seq initialization"
69647025 (-seq [coll]
69657026 (persistent-array-map-seq arr 0 nil ))
69667027
7028+ IDrop
7029+ (-drop [coll n]
7030+ (when-some [s (-seq coll)]
7031+ (-drop s n)))
7032+
69677033 ICounted
69687034 (-count [coll] cnt)
69697035
@@ -9737,6 +9803,47 @@ reduces them without incurring seq initialization"
97379803 (when-let [s (seq coll)]
97389804 (cons (take n s) (partition-all n step (drop step s)))))))
97399805
9806+ (defn splitv-at
9807+ " Returns a vector of [(into [] (take n) coll) (drop n coll)]"
9808+ [n coll]
9809+ [(into [] (take n) coll) (drop n coll)])
9810+
9811+ (defn partitionv
9812+ " Returns a lazy sequence of vectors of n items each, at offsets step
9813+ apart. If step is not supplied, defaults to n, i.e. the partitions
9814+ do not overlap. If a pad collection is supplied, use its elements as
9815+ necessary to complete last partition upto n items. In case there are
9816+ not enough padding elements, return a partition with less than n items."
9817+ ([n coll]
9818+ (partitionv n n coll))
9819+ ([n step coll]
9820+ (lazy-seq
9821+ (when-let [s (seq coll)]
9822+ (let [p (into [] (take n) s)]
9823+ (when (= n (count p))
9824+ (cons p (partitionv n step (nthrest s step))))))))
9825+ ([n step pad coll]
9826+ (lazy-seq
9827+ (when-let [s (seq coll)]
9828+ (let [p (into [] (take n) s)]
9829+ (if (= n (count p))
9830+ (cons p (partitionv n step pad (nthrest s step)))
9831+ (list (into [] (take n) (concat p pad)))))))))
9832+
9833+ (defn partitionv-all
9834+ " Returns a lazy sequence of vector partitions, but may include
9835+ partitions with fewer than n items at the end.
9836+ Returns a stateful transducer when no collection is provided."
9837+ ([n]
9838+ (partition-all n))
9839+ ([n coll]
9840+ (partitionv-all n n coll))
9841+ ([n step coll]
9842+ (lazy-seq
9843+ (when-let [s (seq coll)]
9844+ (let [seg (into [] (take n) coll)]
9845+ (cons seg (partitionv-all n step (drop step s))))))))
9846+
97409847(defn take-while
97419848 " Returns a lazy sequence of successive items from coll while
97429849 (pred item) returns logical true. pred must be free of side-effects.
@@ -9824,7 +9931,12 @@ reduces them without incurring seq initialization"
98249931 (set! i (+ i step))
98259932 ret)))
98269933
9827- (deftype IntegerRange [meta start end step ^:mutable chunk ^:mutable chunk-next ^:mutable __hash]
9934+ (defn- range-count
9935+ " Returns exact size of remaining items in an IntegerRange."
9936+ [start end step]
9937+ (Math/ceil (/ (- end start) step)))
9938+
9939+ (deftype IntegerRange [meta start end step cnt ^:mutable __hash]
98289940 Object
98299941 (toString [coll]
98309942 (pr-str* coll))
@@ -9838,23 +9950,15 @@ reduces them without incurring seq initialization"
98389950 (-lastIndexOf coll x (count coll)))
98399951 (lastIndexOf [coll x start]
98409952 (-lastIndexOf coll x start))
9841- (forceChunk [coll]
9842- (when (nil? chunk)
9843- (let [count (-count coll)]
9844- (if (> count 32 )
9845- (do
9846- (set! chunk-next (IntegerRange. nil (+ start (* step 32 )) end step nil nil nil ))
9847- (set! chunk (IntegerRangeChunk. start step 32 )))
9848- (set! chunk (IntegerRangeChunk. start step count))))))
98499953
98509954 ICloneable
9851- (-clone [_] (IntegerRange. meta start end step chunk chunk-next __hash))
9955+ (-clone [_] (IntegerRange. meta start end step cnt __hash))
98529956
98539957 IWithMeta
98549958 (-with-meta [rng new-meta]
98559959 (if (identical? new-meta meta)
98569960 rng
9857- (IntegerRange. new-meta start end step chunk chunk-next __hash)))
9961+ (IntegerRange. new-meta start end step cnt __hash)))
98589962
98599963 IMeta
98609964 (-meta [rng] meta)
@@ -9878,19 +9982,40 @@ reduces them without incurring seq initialization"
98789982 (-next [rng]
98799983 (if (pos? step)
98809984 (when (< (+ start step) end)
9881- (IntegerRange. nil (+ start step) end step nil nil nil ))
9985+ (IntegerRange. nil (+ start step) end step ( range-count ( + start step) end step) nil ))
98829986 (when (> (+ start step) end)
9883- (IntegerRange. nil (+ start step) end step nil nil nil ))))
9987+ (IntegerRange. nil (+ start step) end step (range-count (+ start step) end step) nil ))))
9988+
9989+ IDrop
9990+ (-drop [rng n]
9991+ (if (pos? n)
9992+ (if (< n cnt)
9993+ (IntegerRange. nil (+ start (* step n)) end step (- cnt n) nil )
9994+ nil )
9995+ rng))
98849996
98859997 IChunkedSeq
98869998 (-chunked-first [rng]
9887- (.forceChunk rng)
9888- chunk)
9999+ (IntegerRangeChunk. start step (min cnt 32 )))
988910000 (-chunked-rest [rng]
9890- (.forceChunk rng)
9891- (if (nil? chunk-next)
10001+ (if (<= cnt 32 )
989210002 ()
9893- chunk-next))
10003+ (let [start (+ start (* step 32 ))]
10004+ (cond
10005+ (pos? step)
10006+ (if (<= end start)
10007+ ()
10008+ (IntegerRange. nil start end step (range-count start end step) nil ))
10009+
10010+ (neg? step)
10011+ (if (>= end start)
10012+ ()
10013+ (IntegerRange. nil start end step (range-count start end step) nil ))
10014+
10015+ :else
10016+ (if (== end start)
10017+ ()
10018+ (repeat start))))))
989410019
989510020 IChunkedNext
989610021 (-chunked-next [rng]
@@ -9911,7 +10036,7 @@ reduces them without incurring seq initialization"
991110036
991210037 ICounted
991310038 (-count [rng]
9914- ( Math/ceil ( / ( - end start) step)) )
10039+ cnt )
991510040
991610041 IIndexed
991710042 (-nth [rng n]
@@ -10060,14 +10185,14 @@ reduces them without incurring seq initialization"
1006010185 (if (<= end start)
1006110186 ()
1006210187 (if (and (integer? start) (integer? end) (integer? step))
10063- (IntegerRange. nil start end step nil nil nil )
10188+ (IntegerRange. nil start end step ( range-count start end step) nil )
1006410189 (Range. nil start end step nil nil nil )))
1006510190
1006610191 (neg? step)
1006710192 (if (>= end start)
1006810193 ()
1006910194 (if (and (integer? start) (integer? end) (integer? step))
10070- (IntegerRange. nil start end step nil nil nil )
10195+ (IntegerRange. nil start end step ( range-count start end step) nil )
1007110196 (Range. nil start end step nil nil nil )))
1007210197
1007310198 :else
0 commit comments