Merge pull request #49 from jolt-lang/leaf-shrink-batch3
core: Stage 3 — leaf batch 3: empty/assoc-in/update-in + interpose/take-nth
This commit is contained in:
commit
1ec2fa4adf
4 changed files with 107 additions and 64 deletions
|
|
@ -732,3 +732,31 @@
|
|||
([x y & more] (reduce min (min x y) more)))
|
||||
|
||||
(defn reverse [coll] (reduce conj (list) coll))
|
||||
|
||||
;; --- Phase 2 leaf batch 3 (jolt-ded) -----------------------------------------
|
||||
|
||||
;; An empty coll of the same category; sorted colls keep their comparator (the
|
||||
;; value's own :empty op). Strings and scalars are nil, as in Clojure; a lazy
|
||||
;; seq empties to () (the old kernel fn returned a host table for it).
|
||||
(defn empty [coll]
|
||||
(cond
|
||||
(nil? coll) nil
|
||||
(sorted? coll) ((get (jolt.host/ref-get coll :ops) :empty) coll)
|
||||
(map? coll) {}
|
||||
(set? coll) #{}
|
||||
(vector? coll) []
|
||||
(coll? coll) ()
|
||||
:else nil))
|
||||
|
||||
(defn assoc-in [m [k & ks] v]
|
||||
(if ks
|
||||
(assoc m k (assoc-in (get m k) ks v))
|
||||
(assoc m k v)))
|
||||
|
||||
(defn update-in [m ks f & args]
|
||||
(let [up (fn up [m ks f args]
|
||||
(let [[k & ks] ks]
|
||||
(if ks
|
||||
(assoc m k (up (get m k) ks f args))
|
||||
(assoc m k (apply f (get m k) args)))))]
|
||||
(up m ks f args)))
|
||||
|
|
|
|||
|
|
@ -138,3 +138,40 @@
|
|||
(when (seq s)
|
||||
(cons (take n s) (go (nthrest s step))))))]
|
||||
(go coll))))
|
||||
|
||||
;; --- Phase 2 leaf batch 3 (jolt-ded): canonical lazy + transducer arities ----
|
||||
|
||||
(defn interpose
|
||||
([sep]
|
||||
(fn [rf]
|
||||
(let [started (volatile! false)]
|
||||
(fn
|
||||
([] (rf))
|
||||
([result] (rf result))
|
||||
([result input]
|
||||
(if (deref started)
|
||||
(let [sepr (rf result sep)]
|
||||
(if (reduced? sepr)
|
||||
sepr
|
||||
(rf sepr input)))
|
||||
(do (vreset! started true)
|
||||
(rf result input))))))))
|
||||
([sep coll]
|
||||
(drop 1 (interleave (repeat sep) coll))))
|
||||
|
||||
(defn take-nth
|
||||
([n]
|
||||
(fn [rf]
|
||||
(let [iv (volatile! -1)]
|
||||
(fn
|
||||
([] (rf))
|
||||
([result] (rf result))
|
||||
([result input]
|
||||
(let [i (vswap! iv inc)]
|
||||
(if (zero? (rem i n))
|
||||
(rf result input)
|
||||
result)))))))
|
||||
([n coll]
|
||||
(lazy-seq
|
||||
(when-let [s (seq coll)]
|
||||
(cons (first s) (take-nth n (drop n s)))))))
|
||||
|
|
|
|||
|
|
@ -2251,19 +2251,10 @@
|
|||
(defn- ks-rest [ks]
|
||||
(if (tuple? ks) (tuple/slice ks 1) (array/slice ks 1)))
|
||||
|
||||
(defn core-assoc-in [m ks v]
|
||||
(let [ks (vview ks) k (in ks 0)]
|
||||
(if (<= (length ks) 1)
|
||||
(core-assoc m k v)
|
||||
(let [sub (core-get m k)]
|
||||
(core-assoc m k (core-assoc-in (if (nil? sub) {} sub) (ks-rest ks) v))))))
|
||||
# assoc-in / update-in now live in the Clojure collection tier (canonical
|
||||
# recursive ports).
|
||||
|
||||
|
||||
(defn core-update-in [m ks f & args]
|
||||
(let [ks (vview ks) k (in ks 0)]
|
||||
(if (<= (length ks) 1)
|
||||
(core-assoc m k (apply f (core-get m k) args))
|
||||
(let [sub (core-get m k)]
|
||||
(core-assoc m k (apply core-update-in (if (nil? sub) {} sub) (ks-rest ks) f args))))))
|
||||
|
||||
# fnil now lives in the Clojure collection tier (core/20-coll.clj), with
|
||||
# Clojure's canonical 2/3/4-arity (patch the first 1-3 args only).
|
||||
|
|
@ -2329,61 +2320,21 @@
|
|||
{:jolt/type :symbol :ns ns :name nm})
|
||||
(error "symbol expects 1 or 2 args")))
|
||||
|
||||
(defn- td-take-nth [n]
|
||||
(fn [rf]
|
||||
(var i 0)
|
||||
(fn [& a] (case (length a) 0 (rf) 1 (rf (a 0))
|
||||
(let [keep (= 0 (mod i n))] (++ i)
|
||||
(if keep (rf (a 0) (a 1)) (a 0)))))))
|
||||
(defn core-take-nth [n & rest]
|
||||
(if (= 0 (length rest)) (td-take-nth n)
|
||||
(let [coll (in rest 0)]
|
||||
# Option A: always lazy.
|
||||
(defn tstep [c]
|
||||
(fn []
|
||||
(if (seq-done? c) nil
|
||||
(let [drop-n (lazy-from (core-drop n c))]
|
||||
(if (seq-done? drop-n) @[(core-first c) nil]
|
||||
@[(core-first c) (tstep drop-n)])))))
|
||||
(make-lazy-seq (tstep (lazy-from coll))))))
|
||||
# (take-nth's transducer arity lives in the overlay now.)
|
||||
|
||||
|
||||
# filterv now lives in the Clojure collection tier (core/20-coll.clj).
|
||||
|
||||
# mapv lives in the Clojure kernel tier — core/00-kernel.clj.
|
||||
|
||||
(defn- td-interpose [sep]
|
||||
(fn [rf]
|
||||
(var started false)
|
||||
(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)]
|
||||
# Option A: always lazy.
|
||||
(defn istep [c need-sep]
|
||||
(fn []
|
||||
(if (seq-done? c) nil
|
||||
(if need-sep
|
||||
@[sep (istep c false)]
|
||||
@[(core-first c) (istep (core-rest c) true)]))))
|
||||
(make-lazy-seq (istep (lazy-from coll) false)))))
|
||||
# (interpose's transducer arity lives in the overlay now.)
|
||||
# interpose / take-nth now live in the Clojure lazy tier (core/40-lazy.clj),
|
||||
# with the canonical transducer arities.
|
||||
|
||||
# keep now lives in the Clojure lazy tier (core/40-lazy.clj).
|
||||
|
||||
(defn core-empty [coll]
|
||||
(cond
|
||||
# an empty sorted coll of the same kind, KEEPING the comparator (Clojure)
|
||||
(core-sorted? coll) ((sorted-op coll :empty) coll)
|
||||
(phm? coll) (make-phm)
|
||||
(set? coll) (make-phs)
|
||||
(plist? coll) EMPTY-PLIST
|
||||
(pvec? coll) (make-vec @[])
|
||||
(struct? coll) (struct)
|
||||
(tuple? coll) (make-vec @[])
|
||||
(array? coll) @[]
|
||||
(table? coll) @{}
|
||||
nil))
|
||||
# empty now lives in the Clojure collection tier (core/20-coll.clj); a lazy
|
||||
# seq empties to () there (this fn returned a host table for it).
|
||||
|
||||
# not-empty now lives in the Clojure collection tier (core/20-coll.clj).
|
||||
|
||||
|
|
@ -2840,7 +2791,6 @@
|
|||
"newline" core-newline
|
||||
"current-time-ms" core-current-time-ms
|
||||
"parse-uuid" core-parse-uuid
|
||||
"interpose" core-interpose
|
||||
"mapcat" core-mapcat
|
||||
"transduce" core-transduce
|
||||
"sequence" core-sequence
|
||||
|
|
@ -2851,8 +2801,6 @@
|
|||
"namespace" core-namespace
|
||||
"reduced" core-reduced
|
||||
"reduced?" core-reduced?
|
||||
"take-nth" core-take-nth
|
||||
"empty" core-empty
|
||||
"rseq" core-rseq
|
||||
"shuffle" core-shuffle
|
||||
"ifn?" core-ifn?
|
||||
|
|
@ -3030,8 +2978,6 @@
|
|||
"ThreadLocal" core-ThreadLocal
|
||||
"IllegalStateException" core-IllegalStateException
|
||||
"resolve" core-resolve
|
||||
"update-in" core-update-in
|
||||
"assoc-in" core-assoc-in
|
||||
"copy-core-var" core-copy-core-var
|
||||
"copy-var" core-copy-var
|
||||
"macrofy" core-macrofy
|
||||
|
|
|
|||
|
|
@ -102,3 +102,35 @@
|
|||
["reverse" "(quote (3 2 1))" "(reverse [1 2 3])"]
|
||||
["reverse empty" "()" "(reverse nil)"]
|
||||
["conj nil onto map" "{:a 1}" "(conj {:a 1} nil)"])
|
||||
|
||||
# Phase 2 leaf batch 3 (jolt-ded): empty/assoc-in/update-in (20-coll) and
|
||||
# interpose/take-nth (40-lazy, with canonical transducer arities). keys/vals/
|
||||
# empty? are expander-coupled (00-syntax macros call them) and stay in the
|
||||
# seed until the fast macro-expansion path lands.
|
||||
(defspec "clojure.core / leaf batch 3"
|
||||
["empty vector" "[]" "(empty [1 2])"]
|
||||
["empty list" "()" "(empty (list 1))"]
|
||||
["empty map" "{}" "(empty {:a 1})"]
|
||||
["empty set" "#{}" "(empty #{1})"]
|
||||
["empty nil" "nil" "(empty nil)"]
|
||||
["empty string" "nil" "(empty \"abc\")"]
|
||||
["empty lazy is ()" "()" "(empty (map inc [1 2]))"]
|
||||
["empty sorted keeps cmp" "[3 1]" "(vec (seq (into (empty (sorted-set-by > 1 2)) [1 3])))"]
|
||||
["assoc-in" "{:a {:b 1}}" "(assoc-in {} [:a :b] 1)"]
|
||||
["assoc-in deep" "{:a {:b {:c 2}}}" "(assoc-in {:a {:b {:c 1}}} [:a :b :c] 2)"]
|
||||
["assoc-in keeps siblings" "{:a {:b 1 :c 2}}" "(assoc-in {:a {:b 1}} [:a :c] 2)"]
|
||||
["assoc-in vector idx" "[1 9]" "(assoc-in [1 2] [1] 9)"]
|
||||
["assoc-in nested vec" "[{:a 9}]" "(assoc-in [{:a 1}] [0 :a] 9)"]
|
||||
["update-in" "{:a {:b 2}}" "(update-in {:a {:b 1}} [:a :b] inc)"]
|
||||
["update-in extra args" "{:a {:b 111}}" "(update-in {:a {:b 1}} [:a :b] + 10 100)"]
|
||||
["update-in fnil" "{:a {:b 1}}" "(update-in {} [:a :b] (fnil inc 0))"]
|
||||
["update-in single key" "{:a 2}" "(update-in {:a 1} [:a] inc)"]
|
||||
["interpose" "(quote (1 :s 2 :s 3))" "(interpose :s [1 2 3])"]
|
||||
["interpose empty" "()" "(interpose :s [])"]
|
||||
["interpose one" "(quote (1))" "(interpose :s [1])"]
|
||||
["interpose is lazy" "(quote (0 :s 1))" "(take 3 (interpose :s (range)))"]
|
||||
["interpose xform" "[\"a\" \",\" \"b\"]" "(vec (sequence (interpose \",\") [\"a\" \"b\"]))"]
|
||||
["take-nth" "(quote (1 3 5))" "(take-nth 2 [1 2 3 4 5 6])"]
|
||||
["take-nth lazy" "(quote (0 3 6))" "(take 3 (take-nth 3 (range)))"]
|
||||
["take-nth xform" "[1 3 5]" "(vec (sequence (take-nth 2) [1 2 3 4 5 6]))"]
|
||||
["take-nth into" "[1 4]" "(into [] (take-nth 3) [1 2 3 4 5])"])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue