Skip to content

Instantly share code, notes, and snippets.

@fogus
Last active May 19, 2022 18:34
Show Gist options
  • Save fogus/678bf3f506195d212a8d0fece3c6d8d4 to your computer and use it in GitHub Desktop.
Save fogus/678bf3f506195d212a8d0fece3c6d8d4 to your computer and use it in GitHub Desktop.
;;;; 0 - naive
(defn take+rest0 [n coll]
[(->> coll (take n) vec)
(drop n coll)])
; "Elapsed time: 700 msecs" with (range), take 10
; "Elapsed time: 5860 msecs" with (range), take 100
; "Elapsed time: 818 msecs" with [0...99999], take 10
; "Elapsed time: 6439 msecs" with [0...99999], take 100
;; 2 - explicit transient with return of tail
(defn take+rest2 [n coll]
(loop [head (transient [])
n n
tail coll]
(if (and (seq tail) (pos? n))
(recur (conj! head (first tail)) (dec n) (rest tail))
[(persistent! head) tail])))
; "Elapsed time: 601 msecs" with coll seq, take 10
; "Elapsed time: 4152 msecs" with coll seq, take 100
; "Elapsed time: 723 msecs" with (range), take 10
; "Elapsed time: 5920 msecs" with (range), take 100
; "Elapsed time: 732 msecs" with [0...99999], take 10
; "Elapsed time: 4254 msecs" with [0...99999], take 100
; "Elapsed time: 1691 msecs" with (take 200 (range)), take 10
; "Elapsed time: 14221 msecs" with (range), take 100
;; 3 - use of into for head, drop for tail
(defn take+rest3
[n coll]
[(into [] (take n) coll)
(drop n coll)])
; "Elapsed time: 565 msecs" with coll seq, take 10
; "Elapsed time: 2762 msecs" with coll seq, take 100
; "Elapsed time: 462 msecs" with (range), take 10
; "Elapsed time: 2755 msecs" with (range), take 100
; "Elapsed time: 517 msecs" with [0...99999], take 10
; "Elapsed time: 2777 msecs" with [0...99999], take 100
; "Elapsed time: 1353 msecs" with (take 200 (range)), take 10
; "Elapsed time: 11327 msecs" with (range), take 100
(defn drop-eager
"eager/fast version of drop"
[n coll]
(if (instance? Iterable coll)
(let [i (.iterator ^Iterable coll)]
(loop [n n]
(if (and (pos? n) (.hasNext i))
(do (.next i)
(recur (dec n)))
(iterator-seq i)))) ;;here we start losing
(nthrest coll n)))
;; 4 - use of into for head, drop-eager for tail
(defn take+rest4
"Returns a vector with two elements. The first is a collection of the first n
items in coll. The second is a collection of the rest of the items in coll, if any."
[n coll]
[(into [] (take n) coll)
(drop-eager n coll)])
;; TBD
(def take+rest99 split-at)
; "Elapsed time: 1021 msecs" with coll seq, take 10
; "Elapsed time: 7944 msecs" with coll seq, take 100
; "Elapsed time: 1111 msecs" with (range), take 10
; "Elapsed time: 9450 msecs" with (range), take 100
; "Elapsed time: 1144 msecs" with [0...99999], take 10
; "Elapsed time: 9023 msecs" with [0...99999], take 100
; "Elapsed time: 1701 msecs" with (take 200 (range)), take 10
; "Elapsed time: 15743 msecs" with (range), take 100
(comment
;; loop with range
(let [n 100
f take+rest2]
(dotimes [_ 10]
(time (dotimes [_ 1000000]
(let [[head tail] (f n (range))]
(count head))))))
;; loop with vec
(let [coll (vec (range 100000))
n 100
f take+rest3]
(dotimes [_ 10]
(time (dotimes [_ 1000000]
(let [[head tail] (f n coll)]
(count head))))))
;; loop with lazy seq
(let [n 100
f take+rest3]
(dotimes [_ 10]
(time (dotimes [_ 1000000]
(let [[head tail] (f n (take 200 (range)))]
(count head))))))
;; loop with coll seq
(let [coll (vec (range 100000))
n 100
f take+rest3]
(dotimes [_ 10]
(time (dotimes [_ 1000000]
(let [[head tail] (f n (seq coll))]
(count head))))))
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment