diff --git a/jolt-core/clojure/core/40-lazy.clj b/jolt-core/clojure/core/40-lazy.clj new file mode 100644 index 0000000..7254b95 --- /dev/null +++ b/jolt-core/clojure/core/40-lazy.clj @@ -0,0 +1,114 @@ +;; clojure.core — lazy tier. Canonical CLJS-based lazy seq fns. +;; Loaded after 30-macros.clj, so lazy-seq macro is available. +;; +;; Each fn ported from CLJS core.cljs, stripped of chunked-seq branches. + +;; --- distinct --- +(defn distinct [coll] + (let [step (fn step [xs seen] + (lazy-seq + ((fn [[f :as xs] seen] + (when-let [s (seq xs)] + (if (contains? seen f) + (recur (rest s) seen) + (cons f (step (rest s) (conj seen f)))))) + xs seen)))] + (step coll #{}))) + +;; --- dedupe (lazy, canonical) --- +(defn dedupe [coll] + (let [step (fn step [s prev] + (lazy-seq + (let [s (seq s)] + (when s + (let [x (first s)] + (if (= x prev) + (step (rest s) prev) + (cons x (step (rest s) x))))))))] + (let [s (seq coll)] + (if s + (lazy-seq (cons (first s) (step (rest s) (first s)))) + ())))) + +;; --- keep --- +(defn keep + ([f] + (fn [rf] + (fn ([] (rf)) ([result] (rf result)) + ([result input] + (let [v (f input)] + (if (nil? v) result (rf result v))))))) + ([f coll] + (lazy-seq + (when-let [s (seq coll)] + (let [x (f (first s))] + (if (nil? x) + (keep f (rest s)) + (cons x (keep f (rest s))))))))) + +;; --- keep-indexed --- +(defn keep-indexed + ([f] + (fn [rf] + (let [ia (volatile! -1)] + (fn ([] (rf)) ([result] (rf result)) + ([result input] + (let [i (vswap! ia inc) + v (f i input)] + (if (nil? v) result (rf result v)))))))) + ([f coll] + (letfn [(keepi [idx coll] + (lazy-seq + (when-let [s (seq coll)] + (let [x (f idx (first s))] + (if (nil? x) + (keepi (inc idx) (rest s)) + (cons x (keepi (inc idx) (rest s))))))))] + (keepi 0 coll)))) + +;; --- map-indexed --- +(defn map-indexed + ([f] + (fn [rf] + (let [i (volatile! -1)] + (fn ([] (rf)) ([result] (rf result)) + ([result input] (rf result (f (vswap! i inc) input))))))) + ([f coll] + (letfn [(mapi [idx coll] + (lazy-seq + (when-let [s (seq coll)] + (cons (f idx (first s)) (mapi (inc idx) (rest s))))))] + (mapi 0 coll)))) + +;; --- cycle --- +(defn cycle [coll] + (if-let [vals (seq coll)] + (let [n (count vals)] + (letfn [(cstep [i] + (lazy-seq + (cons (nth vals (mod i n)) (cstep (inc i)))))] + (cstep 0))) + ())) + +;; --- repeatedly --- +(defn repeatedly + ([f] (lazy-seq (cons (f) (repeatedly f)))) + ([n f] (take n (repeatedly f)))) + +;; --- repeat --- +(defn repeat + ([x] (lazy-seq (cons x (repeat x)))) + ([n x] (take n (repeat x)))) + +;; --- iterate --- +(defn iterate [f x] + (lazy-seq (cons x (iterate f (f x))))) + + +;; --- partition-all --- +(defn partition-all + ([n coll] (partition-all n n coll)) + ([n step coll] + (lazy-seq + (when-let [s (seq coll)] + (cons (take n s) (partition-all n step (nthrest coll step))))))) diff --git a/src/jolt/api.janet b/src/jolt/api.janet index 08d6112..299d460 100644 --- a/src/jolt/api.janet +++ b/src/jolt/api.janet @@ -50,7 +50,8 @@ {:ns "clojure.core.00-kernel" :kernel true} {:ns "clojure.core.10-seq" :kernel false} {:ns "clojure.core.20-coll" :kernel false} - {:ns "clojure.core.30-macros" :kernel false}]) + {:ns "clojure.core.30-macros" :kernel false} + {:ns "clojure.core.40-lazy" :kernel false}]) (defn- eval-overlay-source [ctx src] (var s src) diff --git a/src/jolt/compiler.janet b/src/jolt/compiler.janet index 7af717a..d700472 100644 --- a/src/jolt/compiler.janet +++ b/src/jolt/compiler.janet @@ -96,6 +96,7 @@ "drop" "core-drop" "take-while" "core-take-while" "drop-while" "core-drop-while" + "interpose" "core-interpose" "nth" "core-nth" "mapcat" "core-mapcat" "apply" "core-apply" diff --git a/src/jolt/core.janet b/src/jolt/core.janet index c252abc..b9509e2 100644 --- a/src/jolt/core.janet +++ b/src/jolt/core.janet @@ -1257,31 +1257,6 @@ (sort-by keyfn arr)) (tuple/slice (tuple ;arr)))))) -(defn core-distinct [coll] - (if (nil? coll) @[] - (if (lazy-seq? coll) - (do - (var seen @{}) - (defn dstep [c] - (fn [] - (var cur c) (var found false) (var result nil) - (while (and (not found) (not (seq-done? cur))) - (let [x (ls-first cur)] - (set cur (ls-rest cur)) - (when (nil? (seen x)) - (put seen x true) - (set found true) - (set result x)))) - (if found @[result (dstep cur)] nil))) - (make-lazy-seq (dstep coll))) - (do - (var seen @{}) - (var result @[]) - (each x (realize-for-iteration coll) - (if (nil? (seen x)) - (do (put seen x true) (array/push result x)))) - (if (jvec? coll) (make-vec result) result))))) - # group-by / frequencies now live in the Clojure collection tier # (core/20-coll.clj). @@ -1317,32 +1292,6 @@ (+= i step)) result)))) - -(defn core-partition-all [n coll] - (if (lazy-seq? coll) - (do - (defn pstep [c] - (fn [] - (if (seq-done? c) nil - (do - (var part @[]) (var cur c) (var i 0) - (while (and (< i n) (not (seq-done? cur))) - (array/push part (ls-first cur)) - (set cur (ls-rest cur)) - (++ i)) - @[(tuple/slice (tuple ;part)) (pstep cur)])))) - (make-lazy-seq (pstep coll))) - (let [c (realize-for-iteration coll)] - (var result @[]) (var i 0) - (while (< i (length c)) - (var part @[]) (var j 0) - (while (and (< j n) (< (+ i j) (length c))) - (array/push part (in c (+ i j))) (++ j)) - (array/push result (tuple/slice (tuple ;part))) - (+= i n)) - result))) - - (defn core-keep-indexed [f coll] (def f (as-fn f)) (if (lazy-seq? coll) @@ -1379,14 +1328,6 @@ (each x c (array/push result (f i x)) (++ i)) (tuple/slice (tuple ;result))))))) -(defn core-cycle [coll] - (let [c (realize-for-iteration coll)] - (if (= 0 (length c)) - (make-lazy-seq (fn [] nil)) - (do - (defn cstep [i] (fn [] @[(in c (% i (length c))) (cstep (+ i 1))])) - (make-lazy-seq (cstep 0)))))) - # reduce-kv now lives in the Clojure collection tier (core/20-coll.clj). # pop is defined only on stacks (vectors -> last end, lists -> front); Clojure @@ -1432,16 +1373,6 @@ (+= i step)) (tuple/slice (tuple ;result)))))) -(defn core-repeat - "(repeat x) -> infinite lazy seq of x; (repeat n x) -> n copies of x." - [a & rest] - (if (= 0 (length rest)) - (do (defn rstep [] (fn [] @[a (rstep)])) (make-lazy-seq (rstep))) - (let [n a x (in rest 0)] - (var result @[]) (var i 0) - (while (< i n) (array/push result x) (++ i)) - result))) - (defn core-iterate [f x] "Lazy infinite sequence x, (f x), (f (f x)), ..." (defn istep [v] (fn [] @[v (istep (f v))])) @@ -2337,6 +2268,7 @@ (fn [& a] (case (length a) 0 (rf) 1 (rf (a 0)) (if started (rf (rf (a 0) sep) (a 1)) (do (set started true) (rf (a 0) (a 1)))))))) + (defn core-interpose [sep & rest] (if (= 0 (length rest)) (td-interpose sep) (let [coll (in rest 0)] @@ -2816,11 +2748,7 @@ "get-in" core-get-in "contains?" core-contains? "count" core-count - "partition-all" core-partition-all - "keep-indexed" core-keep-indexed - "map-indexed" core-map-indexed - "cycle" core-cycle - "pop" core-pop + "pop" core-pop "format" core-format "rand-int" core-rand-int "trampoline" core-trampoline @@ -2901,10 +2829,8 @@ "hash-unordered-coll" core-hash-unordered-coll "prefers" core-prefers "random-uuid" core-random-uuid - "interpose" core-interpose - "mapcat" core-mapcat - "keep" core-keep - "find" core-find + "mapcat" core-mapcat + "find" core-find "transduce" core-transduce "sequence" core-sequence "eduction" core-sequence @@ -2941,13 +2867,10 @@ "nth" core-nth "sort" core-sort "sort-by" core-sort-by - "distinct" core-distinct - "partition" core-partition + "partition" core-partition + "interpose" core-interpose "range" core-range - "repeat" core-repeat - "iterate" core-iterate - "repeatedly" core-repeatedly - "identity" core-identity + "identity" core-identity "constantly" core-constantly "complement" core-complement "comp" core-comp