Last active
April 17, 2022 02:42
-
-
Save joshlemer/8305c8447cd98d1c01faa69b9b5077f0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns gen | |
(:require | |
[cloroutine.core :refer [cr]] | |
[criterium.core :as crit])) | |
(deftype ^:private GenIter [;; The Cloroutine generator function | |
^:unsynchronized-mutable ^clojure.lang.IFn g | |
;; Trilean boolean logic: | |
;; 0 = certainly no more elements, `x` is nil | |
;; 1 = certainly there are more elemennts, and the next object is stored in `x` | |
;; 2 = unknown, `x` is nil | |
^:unsynchronized-mutable ^byte _has-next | |
^:unsynchronized-mutable ^java.lang.Object x] | |
java.util.Iterator | |
(hasNext [_] | |
(if | |
(= _has-next (byte 2)) (let [elem (g)] | |
(if (identical? ::done elem) | |
(do | |
(set! _has-next (byte 0)) | |
;; release g for garbage collection | |
(set! g nil) | |
false) | |
(do | |
(set! _has-next (byte 1)) | |
(set! x elem) | |
true))) | |
(= _has-next (byte 1)))) | |
(next [_] | |
(cond | |
(= _has-next 1) (let [result x] | |
;; release x for garbage collection | |
(set! x nil) | |
(set! _has-next (byte 2)) | |
result) | |
(= _has-next 0) (throw (java.util.NoSuchElementException.)) | |
:else (g)))) | |
(defn gen-seq [g] | |
(iterator-seq (GenIter. g 2 nil))) | |
(defn yield [x] x) | |
(defn no-op []) | |
(defmacro generator [& body] | |
`(gen-seq (cr {yield no-op} ~@body ::done))) | |
(defn my-repeat [x] | |
(generator | |
(loop [] | |
(yield x) | |
(recur)))) | |
(defn repeat-l [x] | |
(lazy-seq | |
(cons x (repeat-l x)))) | |
(crit/bench (last (take 1000000 (my-repeat :a)))) ;; 128.499834 ms | |
(crit/bench (last (take 1000000 (repeat-l :a)))) ;; 112.217999 ms |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment