Skip to content

Instantly share code, notes, and snippets.

@divs1210
Last active March 7, 2024 10:06
Show Gist options
  • Save divs1210/53c86ddad2fc0f1bd30917e3d03840f0 to your computer and use it in GitHub Desktop.
Save divs1210/53c86ddad2fc0f1bd30917e3d03840f0 to your computer and use it in GitHub Desktop.
clojure.core/sequence implemented in plain Clojure
(ns sequence
(:refer-clojure :exclude [sequence sort])
(:require [clojure.core :as core]))
;; Helper
;; ======
(defn accumulate
([])
([acc] acc)
([acc x] (conj (vec acc) x)))
;; Implementation
;; ==============
(defn sequence*
[rf coll]
(when-let [[x & more] (seq coll)]
(let [result (rf nil x)]
(if (reduced? result)
(unreduced result)
(if (seq result)
(concat result (sequence* rf more))
(recur rf more))))))
(defn sequence
[xform coll]
(let [rf (xform accumulate)]
(rf (sequence* rf coll))))
;; Tests
;; =====
(assert (= (sequence (comp (map inc) (filter even?) (take 3))
(range 10))
[2 4 6]))
(assert (= (sequence (partition-all 2)
(range 5))
[[0 1] [2 3] [4]]))
(defn sort
"from net.cgrand.xforms"
[]
(fn [rf]
(let [buf (volatile! [])]
(fn
([] (rf))
([acc] (rf (reduce rf acc (core/sort @buf))))
([acc x] (vswap! buf conj x) acc)))))
(assert (= (sequence (comp (sort) (take 3))
(shuffle (range 10)))
[0 1 2]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment