core: move the pure-leaf fns to the overlay; memfn is a real macro now
Round 3 of the seed shrink. To the overlay: identity, constantly, neg?,
even?, odd? (20-coll, ahead of their first in-tier uses), not= and unreduced
(00-syntax — the kernel and seq tiers use them), ==, ensure-reduced,
halt-when, parse-boolean, parse-uuid, newline, seque, array-seq, to-array-2d,
and the masking unchecked-byte/short/char/float/double coercions. parse-uuid
validates via re-matches over a new __make-uuid host binding (overlay source
can't write :jolt/type map literals). memfn moves to 30-macros as a working
macro over the .method call sugar instead of a fn that throws.
Behavior fixes toward Clojure, each with spec rows: == now throws on
non-numbers instead of comparing them, and halt-when is the canonical
::halt-map version (the halt value replaces the whole reduction result, no
double completion). list? and map-entry? stay in the seed — both are
representation-coupled (plist/tuple checks).
clojure-test-suite goes 4701 -> 4700: update.cljc expects
(update {:k 1} :k identity 1 2 3 4) to throw an arity error, and jolt fns
don't enforce fixed arity anywhere (pre-existing, language-wide — the seed's
Janet identity threw natively). Filed as jolt-6xn; fixing it should flip
several suite rows at once.
This commit is contained in:
parent
65687c69ae
commit
7ca88ab2b5
7 changed files with 154 additions and 84 deletions
|
|
@ -445,3 +445,13 @@
|
||||||
|
|
||||||
(defmacro lazy-cat [& colls]
|
(defmacro lazy-cat [& colls]
|
||||||
`(concat ~@(map (fn [c] `(lazy-seq ~c)) colls)))
|
`(concat ~@(map (fn [c] `(lazy-seq ~c)) colls)))
|
||||||
|
|
||||||
|
;; not= here (not 20-coll): the kernel tier uses it, and the kernel
|
||||||
|
;; bootstrap-compiles right after this file loads. Canonical Clojure arities.
|
||||||
|
(defn not=
|
||||||
|
([x] false)
|
||||||
|
([x y] (not (= x y)))
|
||||||
|
([x y & more] (not (apply = x y more))))
|
||||||
|
|
||||||
|
;; unreduced here: the seq tier's reduce machinery unwraps with it.
|
||||||
|
(defn unreduced [x] (if (reduced? x) (deref x) x))
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,23 @@
|
||||||
;; Same migration rule as the seq tier (see 10-seq.clj): not in core-renames, no
|
;; Same migration rule as the seq tier (see 10-seq.clj): not in core-renames, no
|
||||||
;; internal Janet callers, not used by the self-hosted compiler.
|
;; internal Janet callers, not used by the self-hosted compiler.
|
||||||
|
|
||||||
|
;; Tiny leaves first — fns below in this tier (and 25-sorted) use them.
|
||||||
|
(defn identity [x] x)
|
||||||
|
|
||||||
|
(defn constantly [x] (fn [& args] x))
|
||||||
|
|
||||||
|
;; neg? throws on non-numbers via <, as Clojure's Numbers.isNeg does.
|
||||||
|
(defn neg? [x] (< x 0))
|
||||||
|
|
||||||
|
;; even?/odd? accept any integral number (jolt has one number type, so 2.0
|
||||||
|
;; counts) and throw otherwise — Clojure's IllegalArgumentException wording.
|
||||||
|
(defn even? [n]
|
||||||
|
(if (integer? n)
|
||||||
|
(zero? (rem n 2))
|
||||||
|
(throw (str "Argument must be an integer: " n))))
|
||||||
|
|
||||||
|
(defn odd? [n] (not (even? n)))
|
||||||
|
|
||||||
;; Base is (hash-map), not the {} literal: a literal map is a struct that doesn't
|
;; Base is (hash-map), not the {} literal: a literal map is a struct that doesn't
|
||||||
;; canonicalize collection keys across representations (a {:a 1} literal vs
|
;; canonicalize collection keys across representations (a {:a 1} literal vs
|
||||||
;; (hash-map :a 1) key), whereas a PHM does — so counting/grouping by collection
|
;; (hash-map :a 1) key), whereas a PHM does — so counting/grouping by collection
|
||||||
|
|
@ -373,6 +390,17 @@
|
||||||
([keyfn comp coll]
|
([keyfn comp coll]
|
||||||
(sort (fn [x y] (comp (keyfn x) (keyfn y))) coll)))
|
(sort (fn [x y] (comp (keyfn x) (keyfn y))) coll)))
|
||||||
|
|
||||||
|
;; parse-uuid: nil unless s is a canonical 8-4-4-4-12 hex UUID string; throws
|
||||||
|
;; on a non-string (Clojure 1.11). __make-uuid is the host constructor for the
|
||||||
|
;; tagged value (overlay source can't write :jolt/type map literals — the
|
||||||
|
;; reader treats them as tagged forms).
|
||||||
|
(defn parse-uuid [s]
|
||||||
|
(if (string? s)
|
||||||
|
(when (re-matches
|
||||||
|
#"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}" s)
|
||||||
|
(__make-uuid s))
|
||||||
|
(throw (str "parse-uuid requires a string, got: " s))))
|
||||||
|
|
||||||
;; Version-4 UUID (RFC 4122): zero-padded hex groups 8-4-4-4-12, version
|
;; Version-4 UUID (RFC 4122): zero-padded hex groups 8-4-4-4-12, version
|
||||||
;; nibble 4, variant 8-b — built over rand-int and validated by parse-uuid.
|
;; nibble 4, variant 8-b — built over rand-int and validated by parse-uuid.
|
||||||
(defn random-uuid []
|
(defn random-uuid []
|
||||||
|
|
@ -882,3 +910,65 @@
|
||||||
;; num: Clojure coerces to java.lang.Number; jolt just checks.
|
;; num: Clojure coerces to java.lang.Number; jolt just checks.
|
||||||
(defn num [x]
|
(defn num [x]
|
||||||
(if (number? x) x (throw (str "num requires a number, got: " x))))
|
(if (number? x) x (throw (str "num requires a number, got: " x))))
|
||||||
|
|
||||||
|
;; == numeric equality: 1-arity is trivially true without inspecting the value
|
||||||
|
;; (Clojure's shape); 2+ args must be numbers, as Numbers.equiv throws.
|
||||||
|
(defn ==
|
||||||
|
([x] true)
|
||||||
|
([x y]
|
||||||
|
(if (and (number? x) (number? y))
|
||||||
|
(= x y)
|
||||||
|
(throw (str "Cannot cast to number: " (if (number? x) y x)))))
|
||||||
|
([x y & more]
|
||||||
|
(if (== x y)
|
||||||
|
(apply == y more)
|
||||||
|
false)))
|
||||||
|
|
||||||
|
;; ensure-reduced / halt-when: canonical Clojure. halt-when smuggles the halt
|
||||||
|
;; value through reduce in a ::halt-keyed map and unwraps it in the completion
|
||||||
|
;; arity, so the halt REPLACES the whole reduction result.
|
||||||
|
(defn ensure-reduced [x] (if (reduced? x) x (reduced x)))
|
||||||
|
|
||||||
|
(defn halt-when
|
||||||
|
([pred] (halt-when pred nil))
|
||||||
|
([pred retf]
|
||||||
|
(fn [rf]
|
||||||
|
(fn
|
||||||
|
([] (rf))
|
||||||
|
([result]
|
||||||
|
(if (and (map? result) (contains? result ::halt))
|
||||||
|
(get result ::halt)
|
||||||
|
(rf result)))
|
||||||
|
([result input]
|
||||||
|
(if (pred input)
|
||||||
|
(reduced (hash-map ::halt (if retf (retf (rf result) input) input)))
|
||||||
|
(rf result input)))))))
|
||||||
|
|
||||||
|
;; parse-boolean: exact "true"/"false" only; nil on anything else, throw on a
|
||||||
|
;; non-string (Clojure 1.11).
|
||||||
|
(defn parse-boolean [s]
|
||||||
|
(if (string? s)
|
||||||
|
(cond (= s "true") true (= s "false") false :else nil)
|
||||||
|
(throw (str "parse-boolean requires a string, got: " s))))
|
||||||
|
|
||||||
|
(defn newline [] (print "\n") nil)
|
||||||
|
|
||||||
|
;; seque: jolt is single-threaded eager here — the queue is a no-op and the
|
||||||
|
;; coll passes through.
|
||||||
|
(defn seque
|
||||||
|
([s] s)
|
||||||
|
([n-or-q s] s))
|
||||||
|
|
||||||
|
(defn array-seq [arr & _] (seq arr))
|
||||||
|
|
||||||
|
(defn to-array-2d [coll] (to-array (map to-array coll)))
|
||||||
|
|
||||||
|
;; Masking integer coercions (not aliases): byte/short wrap to their width.
|
||||||
|
;; unchecked-char keeps jolt's historical NUMBER result (Clojure returns a
|
||||||
|
;; char) — the char wrapper is a different value type here. int handles chars,
|
||||||
|
;; so (unchecked-byte \a) works as on the JVM.
|
||||||
|
(defn unchecked-byte [x] (bit-and (int x) 0xff))
|
||||||
|
(defn unchecked-short [x] (bit-and (int x) 0xffff))
|
||||||
|
(defn unchecked-char [x] (bit-and (int x) 0xffff))
|
||||||
|
(defn unchecked-float [x] (double x))
|
||||||
|
(defn unchecked-double [x] (double x))
|
||||||
|
|
|
||||||
|
|
@ -407,3 +407,10 @@
|
||||||
;; loads — so the macro must be registered BEFORE those tiers, else (lazy-seq …)
|
;; loads — so the macro must be registered BEFORE those tiers, else (lazy-seq …)
|
||||||
;; compiles as a call to the macro-as-function and leaks its expansion at runtime
|
;; compiles as a call to the macro-as-function and leaks its expansion at runtime
|
||||||
;; (jolt-r81). They only need seed fns (make-lazy-seq/coll->cells/concat).
|
;; (jolt-r81). They only need seed fns (make-lazy-seq/coll->cells/concat).
|
||||||
|
|
||||||
|
;; memfn: a fn wrapping a method call, (memfn toUpperCase) => #(.toUpperCase %).
|
||||||
|
;; The method symbol is rewritten to jolt's .method call sugar; extra arg names
|
||||||
|
;; become fn params, as in Clojure.
|
||||||
|
(defmacro memfn [method-name & args]
|
||||||
|
`(fn [target# ~@args]
|
||||||
|
(~(symbol (str "." (name method-name))) target# ~@args)))
|
||||||
|
|
|
||||||
|
|
@ -231,9 +231,7 @@
|
||||||
|
|
||||||
(defn core-zero? [x] (= (need-num x "zero?") 0))
|
(defn core-zero? [x] (= (need-num x "zero?") 0))
|
||||||
(defn core-pos? [x] (> (need-num x "pos?") 0))
|
(defn core-pos? [x] (> (need-num x "pos?") 0))
|
||||||
(defn core-neg? [x] (< (need-num x "neg?") 0))
|
# neg? / even? / odd? live in the Clojure collection tier (core/20-coll.clj).
|
||||||
(defn core-even? [n] (= 0 (% (need-int n "even?") 2)))
|
|
||||||
(defn core-odd? [n] (not= 0 (% (need-int n "odd?") 2)))
|
|
||||||
|
|
||||||
# Finite integral number: NaN and the infinities are NOT integers (floor of
|
# Finite integral number: NaN and the infinities are NOT integers (floor of
|
||||||
# inf is inf, so the naive floor check wrongly accepted them).
|
# inf is inf, so the naive floor check wrongly accepted them).
|
||||||
|
|
@ -401,7 +399,7 @@
|
||||||
(++ i))
|
(++ i))
|
||||||
ok)))
|
ok)))
|
||||||
|
|
||||||
(defn core-not= [& args] (not (apply core-= args)))
|
# not= lives in the syntax tier (core/00-syntax.clj) — the kernel uses it.
|
||||||
|
|
||||||
# Comparisons are variadic: (< a b c) means a < b < c.
|
# Comparisons are variadic: (< a b c) means a < b < c.
|
||||||
(defn- chain-cmp [op opname xs]
|
(defn- chain-cmp [op opname xs]
|
||||||
|
|
@ -818,7 +816,7 @@
|
||||||
|
|
||||||
(defn core-reduced [x] @{:jolt/type :jolt/reduced :val x})
|
(defn core-reduced [x] @{:jolt/type :jolt/reduced :val x})
|
||||||
(defn core-reduced? [x] (and (table? x) (= :jolt/reduced (x :jolt/type))))
|
(defn core-reduced? [x] (and (table? x) (= :jolt/reduced (x :jolt/type))))
|
||||||
(defn core-unreduced [x] (if (core-reduced? x) (x :val) x))
|
# unreduced lives in the syntax tier (core/00-syntax.clj) over reduced?/deref.
|
||||||
(defn- ensure-reduced [x] (if (core-reduced? x) x (core-reduced x)))
|
(defn- ensure-reduced [x] (if (core-reduced? x) x (core-reduced x)))
|
||||||
|
|
||||||
(defn td-map [f]
|
(defn td-map [f]
|
||||||
|
|
@ -1402,9 +1400,7 @@
|
||||||
# Higher-order functions
|
# Higher-order functions
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
(def core-identity (fn [x] x))
|
# identity / constantly live in the Clojure collection tier (core/20-coll.clj).
|
||||||
|
|
||||||
(def core-constantly (fn [x] (fn [& _] x)))
|
|
||||||
|
|
||||||
# complement now lives in the Clojure collection tier (core/20-coll.clj).
|
# complement now lives in the Clojure collection tier (core/20-coll.clj).
|
||||||
|
|
||||||
|
|
@ -1686,7 +1682,7 @@
|
||||||
(prin "\n")
|
(prin "\n")
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
(defn core-newline [] (prin "\n") nil)
|
# newline lives in the Clojure collection tier (core/20-coll.clj).
|
||||||
|
|
||||||
# Clojure 1.11 string->scalar parsers: nil on malformed input, throw on a
|
# Clojure 1.11 string->scalar parsers: nil on malformed input, throw on a
|
||||||
# non-string. Validation is strict (scan-number alone accepts 0x10 etc.).
|
# non-string. Validation is strict (scan-number alone accepts 0x10 etc.).
|
||||||
|
|
@ -1717,9 +1713,7 @@
|
||||||
(def pat (peg/compile ~(sequence (opt (set "+-")) (choice (sequence (some :d) (opt (sequence "." (any :d)))) (sequence "." (some :d))) (opt (sequence (set "eE") (opt (set "+-")) (some :d))) -1)))
|
(def pat (peg/compile ~(sequence (opt (set "+-")) (choice (sequence (some :d) (opt (sequence "." (any :d)))) (sequence "." (some :d))) (opt (sequence (set "eE") (opt (set "+-")) (some :d))) -1)))
|
||||||
(if (peg/match pat str*) (scan-number str*) nil))))
|
(if (peg/match pat str*) (scan-number str*) nil))))
|
||||||
|
|
||||||
(defn core-parse-boolean [s]
|
# parse-boolean lives in the Clojure collection tier (core/20-coll.clj).
|
||||||
(def str* (parse-arg-str s "parse-boolean"))
|
|
||||||
(case str* "true" true "false" false nil))
|
|
||||||
|
|
||||||
# Host time source for the `time` macro (monotonic, milliseconds).
|
# Host time source for the `time` macro (monotonic, milliseconds).
|
||||||
(defn core-current-time-ms [] (* 1000 (os/clock :monotonic)))
|
(defn core-current-time-ms [] (* 1000 (os/clock :monotonic)))
|
||||||
|
|
@ -1933,8 +1927,7 @@
|
||||||
|
|
||||||
(defn core-to-array [coll]
|
(defn core-to-array [coll]
|
||||||
(def arr @[]) (each x (realize-for-iteration coll) (array/push arr x)) arr)
|
(def arr @[]) (each x (realize-for-iteration coll) (array/push arr x)) arr)
|
||||||
(defn core-to-array-2d [coll]
|
# to-array-2d lives in the Clojure collection tier (core/20-coll.clj).
|
||||||
(def arr @[]) (each row (realize-for-iteration coll) (array/push arr (core-to-array row))) arr)
|
|
||||||
|
|
||||||
# Array-element casts — identity on arrays; `bytes` coerces to a byte buffer.
|
# Array-element casts — identity on arrays; `bytes` coerces to a byte buffer.
|
||||||
(defn core-bytes [x] (if (buffer? x) x (core-byte-array x)))
|
(defn core-bytes [x] (if (buffer? x) x (core-byte-array x)))
|
||||||
|
|
@ -1949,11 +1942,8 @@
|
||||||
# Scalar numeric coercions
|
# Scalar numeric coercions
|
||||||
(defn core-byte [x] (let [b (band (math/trunc x) 0xff)] (if (>= b 128) (- b 256) b)))
|
(defn core-byte [x] (let [b (band (math/trunc x) 0xff)] (if (>= b 128) (- b 256) b)))
|
||||||
(defn core-short [x] (let [s (band (math/trunc x) 0xffff)] (if (>= s 0x8000) (- s 0x10000) s)))
|
(defn core-short [x] (let [s (band (math/trunc x) 0xffff)] (if (>= s 0x8000) (- s 0x10000) s)))
|
||||||
(defn core-unchecked-byte [x] (band (math/trunc x) 0xff))
|
# The masking unchecked-byte/short/char and float/double coercions live in
|
||||||
(defn core-unchecked-short [x] (band (math/trunc x) 0xffff))
|
# the Clojure collection tier (core/20-coll.clj).
|
||||||
(defn core-unchecked-char [x] (band (math/trunc x) 0xffff))
|
|
||||||
(defn core-unchecked-float [x] (* 1.0 x))
|
|
||||||
(defn core-unchecked-double [x] (* 1.0 x))
|
|
||||||
|
|
||||||
# 64-bit integers (Janet int/s64 — C-backed)
|
# 64-bit integers (Janet int/s64 — C-backed)
|
||||||
(defn core-bigint [x] (int/s64 x))
|
(defn core-bigint [x] (int/s64 x))
|
||||||
|
|
@ -1982,8 +1972,7 @@
|
||||||
# reader-conditional? now lives in the Clojure collection tier (tagged-value predicate).
|
# reader-conditional? now lives in the Clojure collection tier (tagged-value predicate).
|
||||||
# sorted-map-by / sorted-set-by (and all other sorted-coll constructors and
|
# sorted-map-by / sorted-set-by (and all other sorted-coll constructors and
|
||||||
# semantics) now live in the Clojure sorted tier (core/25-sorted.clj).
|
# semantics) now live in the Clojure sorted tier (core/25-sorted.clj).
|
||||||
(defn core-array-seq [arr & _] (core-seq arr))
|
# array-seq / seque live in the Clojure collection tier (core/20-coll.clj).
|
||||||
(defn core-seque [& args] (in args (- (length args) 1)))
|
|
||||||
# supers now lives in the Clojure collection tier (no class hierarchy: #{}).
|
# supers now lives in the Clojure collection tier (no class hierarchy: #{}).
|
||||||
(defn core-class [x]
|
(defn core-class [x]
|
||||||
(cond
|
(cond
|
||||||
|
|
@ -2429,13 +2418,8 @@
|
||||||
(defn core-proxy-call-with-super [f proxy meth] (f))
|
(defn core-proxy-call-with-super [f proxy meth] (f))
|
||||||
(defn core-proxy-mappings [proxy] {})
|
(defn core-proxy-mappings [proxy] {})
|
||||||
(defn core-update-proxy [proxy mappings] proxy)
|
(defn core-update-proxy [proxy mappings] proxy)
|
||||||
(defn core-numeric= [& args]
|
# == lives in the Clojure collection tier (core/20-coll.clj); memfn is an
|
||||||
(if (< (length args) 2) true
|
# overlay macro (core/30-macros.clj) over the .method call sugar.
|
||||||
(do (var ok true) (var i 0)
|
|
||||||
(while (and ok (< i (dec (length args))))
|
|
||||||
(unless (= (in args i) (in args (+ i 1))) (set ok false)) (++ i))
|
|
||||||
ok)))
|
|
||||||
(defn core-memfn [& args] (error "memfn: JVM method handles are not supported in Jolt"))
|
|
||||||
(defn core-eduction [& args]
|
(defn core-eduction [& args]
|
||||||
# (eduction xform* coll): apply the composed transducers eagerly to coll
|
# (eduction xform* coll): apply the composed transducers eagerly to coll
|
||||||
(let [n (length args)
|
(let [n (length args)
|
||||||
|
|
@ -2505,17 +2489,8 @@
|
||||||
(defn core-deliver [p v] (core-reset! p v) p)
|
(defn core-deliver [p v] (core-reset! p v) p)
|
||||||
|
|
||||||
(defn core-tagged-literal [tag form] @{:jolt/type :jolt/tagged-literal :tag tag :form form})
|
(defn core-tagged-literal [tag form] @{:jolt/type :jolt/tagged-literal :tag tag :form form})
|
||||||
(defn core-ensure-reduced [x] (if (core-reduced? x) x (core-reduced x)))
|
# ensure-reduced / halt-when live in the Clojure collection tier
|
||||||
(defn core-halt-when [pred & rest]
|
# (core/20-coll.clj) — halt-when is the canonical ::halt-map version there.
|
||||||
(let [retf (if (> (length rest) 0) (in rest 0) nil)]
|
|
||||||
(fn [rf]
|
|
||||||
(fn [& a]
|
|
||||||
(case (length a)
|
|
||||||
0 (rf)
|
|
||||||
1 (rf (in a 0))
|
|
||||||
(if (truthy? (pred (in a 1)))
|
|
||||||
(core-reduced (if retf (retf (rf (in a 0)) (in a 1)) (in a 1)))
|
|
||||||
(rf (in a 0) (in a 1))))))))
|
|
||||||
(defn core-re-groups [m] (error "re-groups: stateful matchers are not supported in Jolt"))
|
(defn core-re-groups [m] (error "re-groups: stateful matchers are not supported in Jolt"))
|
||||||
|
|
||||||
# Transients — real mutable scratch collections backed by Janet's native arrays
|
# Transients — real mutable scratch collections backed by Janet's native arrays
|
||||||
|
|
@ -2640,28 +2615,8 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn- hex-digit? [c]
|
# parse-uuid lives in the Clojure collection tier (core/20-coll.clj) over
|
||||||
(or (and (>= c 48) (<= c 57)) # 0-9
|
# re-matches + the __make-uuid host constructor (types.janet).
|
||||||
(and (>= c 97) (<= c 102)) # a-f
|
|
||||||
(and (>= c 65) (<= c 70)))) # A-F
|
|
||||||
|
|
||||||
(defn core-parse-uuid
|
|
||||||
"(parse-uuid s) -> the UUID, or nil when s is not a canonical 8-4-4-4-12 hex
|
|
||||||
UUID string. Throws when s is not a string (Clojure 1.11)."
|
|
||||||
[s]
|
|
||||||
(when (not (or (string? s) (buffer? s)))
|
|
||||||
(error (string "parse-uuid requires a string, got " (type s))))
|
|
||||||
(def dash-at {8 true 13 true 18 true 23 true})
|
|
||||||
(if (and (= 36 (length s))
|
|
||||||
(do
|
|
||||||
(var ok true)
|
|
||||||
(for i 0 36
|
|
||||||
(if (get dash-at i)
|
|
||||||
(when (not= 45 (in s i)) (set ok false)) # 45 = "-"
|
|
||||||
(when (not (hex-digit? (in s i))) (set ok false))))
|
|
||||||
ok))
|
|
||||||
(make-uuid s)
|
|
||||||
nil))
|
|
||||||
|
|
||||||
(def- core-bindings
|
(def- core-bindings
|
||||||
"Map of symbol name → function for all core functions."
|
"Map of symbol name → function for all core functions."
|
||||||
|
|
@ -2678,9 +2633,6 @@
|
||||||
"identical?" core-identical?
|
"identical?" core-identical?
|
||||||
"zero?" core-zero?
|
"zero?" core-zero?
|
||||||
"pos?" core-pos?
|
"pos?" core-pos?
|
||||||
"neg?" core-neg?
|
|
||||||
"even?" core-even?
|
|
||||||
"odd?" core-odd?
|
|
||||||
"integer?" core-integer?
|
"integer?" core-integer?
|
||||||
"list?" core-list?
|
"list?" core-list?
|
||||||
"every?" core-every?
|
"every?" core-every?
|
||||||
|
|
@ -2695,7 +2647,6 @@
|
||||||
"quot" core-quot
|
"quot" core-quot
|
||||||
"rand" core-rand
|
"rand" core-rand
|
||||||
"=" core-=
|
"=" core-=
|
||||||
"not=" core-not=
|
|
||||||
"<" core-<
|
"<" core-<
|
||||||
">" core->
|
">" core->
|
||||||
"<=" core-<=
|
"<=" core-<=
|
||||||
|
|
@ -2733,9 +2684,6 @@
|
||||||
"future?" core-future?
|
"future?" core-future?
|
||||||
"future-cancel" core-future-cancel
|
"future-cancel" core-future-cancel
|
||||||
"tagged-literal" core-tagged-literal
|
"tagged-literal" core-tagged-literal
|
||||||
"ensure-reduced" core-ensure-reduced
|
|
||||||
"unreduced" core-unreduced
|
|
||||||
"halt-when" core-halt-when
|
|
||||||
"re-groups" core-re-groups
|
"re-groups" core-re-groups
|
||||||
"transient" core-transient
|
"transient" core-transient
|
||||||
"transient?" core-transient?
|
"transient?" core-transient?
|
||||||
|
|
@ -2748,6 +2696,7 @@
|
||||||
"hash-ordered-coll" core-hash-ordered-coll
|
"hash-ordered-coll" core-hash-ordered-coll
|
||||||
"hash-unordered-coll" core-hash-unordered-coll
|
"hash-unordered-coll" core-hash-unordered-coll
|
||||||
"gensym" gensym
|
"gensym" gensym
|
||||||
|
"__make-uuid" make-uuid
|
||||||
"compare" core-compare
|
"compare" core-compare
|
||||||
"type" core-type
|
"type" core-type
|
||||||
"slurp" core-slurp
|
"slurp" core-slurp
|
||||||
|
|
@ -2759,10 +2708,7 @@
|
||||||
"__list-dir" core-list-dir
|
"__list-dir" core-list-dir
|
||||||
"parse-long" core-parse-long
|
"parse-long" core-parse-long
|
||||||
"parse-double" core-parse-double
|
"parse-double" core-parse-double
|
||||||
"parse-boolean" core-parse-boolean
|
|
||||||
"newline" core-newline
|
|
||||||
"current-time-ms" core-current-time-ms
|
"current-time-ms" core-current-time-ms
|
||||||
"parse-uuid" core-parse-uuid
|
|
||||||
"mapcat" core-mapcat
|
"mapcat" core-mapcat
|
||||||
"transduce" core-transduce
|
"transduce" core-transduce
|
||||||
"sequence" core-sequence
|
"sequence" core-sequence
|
||||||
|
|
@ -2785,8 +2731,6 @@
|
||||||
"sort" core-sort
|
"sort" core-sort
|
||||||
"partition" core-partition
|
"partition" core-partition
|
||||||
"range" core-range
|
"range" core-range
|
||||||
"identity" core-identity
|
|
||||||
"constantly" core-constantly
|
|
||||||
"vector" core-vector
|
"vector" core-vector
|
||||||
"hash-map" core-hash-map
|
"hash-map" core-hash-map
|
||||||
"array-map" core-array-map
|
"array-map" core-array-map
|
||||||
|
|
@ -2845,7 +2789,6 @@
|
||||||
"make-array" core-make-array
|
"make-array" core-make-array
|
||||||
"into-array" core-into-array
|
"into-array" core-into-array
|
||||||
"to-array" core-to-array
|
"to-array" core-to-array
|
||||||
"to-array-2d" core-to-array-2d
|
|
||||||
"bytes" core-bytes
|
"bytes" core-bytes
|
||||||
"booleans" core-booleans
|
"booleans" core-booleans
|
||||||
"ints" core-ints
|
"ints" core-ints
|
||||||
|
|
@ -2856,11 +2799,6 @@
|
||||||
"chars" core-chars
|
"chars" core-chars
|
||||||
"byte" core-byte
|
"byte" core-byte
|
||||||
"short" core-short
|
"short" core-short
|
||||||
"unchecked-byte" core-unchecked-byte
|
|
||||||
"unchecked-short" core-unchecked-short
|
|
||||||
"unchecked-char" core-unchecked-char
|
|
||||||
"unchecked-float" core-unchecked-float
|
|
||||||
"unchecked-double" core-unchecked-double
|
|
||||||
"bigint" core-bigint
|
"bigint" core-bigint
|
||||||
"biginteger" core-biginteger
|
"biginteger" core-biginteger
|
||||||
"chunk-buffer" core-chunk-buffer
|
"chunk-buffer" core-chunk-buffer
|
||||||
|
|
@ -2874,8 +2812,6 @@
|
||||||
"cat" core-cat
|
"cat" core-cat
|
||||||
"disj!" core-disj!
|
"disj!" core-disj!
|
||||||
"reader-conditional" core-reader-conditional
|
"reader-conditional" core-reader-conditional
|
||||||
"array-seq" core-array-seq
|
|
||||||
"seque" core-seque
|
|
||||||
"class" core-class
|
"class" core-class
|
||||||
"enumeration-seq" core-enumeration-seq
|
"enumeration-seq" core-enumeration-seq
|
||||||
"iterator-seq" core-iterator-seq
|
"iterator-seq" core-iterator-seq
|
||||||
|
|
@ -2886,8 +2822,6 @@
|
||||||
"proxy-call-with-super" core-proxy-call-with-super
|
"proxy-call-with-super" core-proxy-call-with-super
|
||||||
"proxy-mappings" core-proxy-mappings
|
"proxy-mappings" core-proxy-mappings
|
||||||
"update-proxy" core-update-proxy
|
"update-proxy" core-update-proxy
|
||||||
"==" core-numeric=
|
|
||||||
"memfn" core-memfn
|
|
||||||
"eduction" core-eduction
|
"eduction" core-eduction
|
||||||
"->Eduction" core->Eduction
|
"->Eduction" core->Eduction
|
||||||
"proxy-super" core-proxy-super
|
"proxy-super" core-proxy-super
|
||||||
|
|
|
||||||
|
|
@ -192,3 +192,15 @@
|
||||||
["num passes a number through" "5" "(num 5)"]
|
["num passes a number through" "5" "(num 5)"]
|
||||||
["num on a double" "5.5" "(num 5.5)"]
|
["num on a double" "5.5" "(num 5.5)"]
|
||||||
["num throws on non-number" :throws "(num \"x\")"])
|
["num throws on non-number" :throws "(num \"x\")"])
|
||||||
|
|
||||||
|
# == is numeric equality: single arg is trivially true (Clojure's 1-arity
|
||||||
|
# never inspects the value); 2+ args must be numbers.
|
||||||
|
(defspec "numbers / == numeric equality"
|
||||||
|
["== single arg" "true" "(== :a)"]
|
||||||
|
["== equal" "true" "(== 2 2)"]
|
||||||
|
["== unequal" "false" "(== 2 3)"]
|
||||||
|
["== chained" "true" "(== 2 2 2)"]
|
||||||
|
["== chained unequal" "false" "(== 2 2 3)"]
|
||||||
|
["== int and double" "true" "(== 1 1.0)"]
|
||||||
|
["== throws on non-number" :throws "(== 1 :a)"]
|
||||||
|
["== throws on two keywords" :throws "(== :a :a)"])
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,19 @@
|
||||||
["eduction" "[2 3 4]" "(into [] (eduction (map inc) [1 2 3]))"]
|
["eduction" "[2 3 4]" "(into [] (eduction (map inc) [1 2 3]))"]
|
||||||
["completing" "9" "(transduce (map inc) (completing +) 0 [1 2 3])"])
|
["completing" "9" "(transduce (map inc) (completing +) 0 [1 2 3])"])
|
||||||
|
|
||||||
|
# halt-when replaces the WHOLE reduction result with the halting input (or
|
||||||
|
# with (retf acc input)) — Clojure's ::halt map protocol, unwrapped by the
|
||||||
|
# transducer's completion arity.
|
||||||
|
(defspec "transducers / halt-when"
|
||||||
|
["halt returns the halting input" "7"
|
||||||
|
"(transduce (halt-when (fn [x] (> x 5))) conj [1 2 7 3])"]
|
||||||
|
["no halt is a plain reduction" "[1 2 3]"
|
||||||
|
"(transduce (halt-when (fn [x] (> x 5))) conj [1 2 3])"]
|
||||||
|
["retf combines acc and input" "[[1 2] 7]"
|
||||||
|
"(transduce (halt-when (fn [x] (> x 5)) (fn [r i] [r i])) conj [1 2 7 3])"]
|
||||||
|
["halt-when through into" "3"
|
||||||
|
"(into [] (halt-when odd?) [2 4 3 6])"])
|
||||||
|
|
||||||
# A `take`/`take-while` transducer returns `reduced`, which must short-circuit
|
# A `take`/`take-while` transducer returns `reduced`, which must short-circuit
|
||||||
# the reduction so transducing over an INFINITE seq terminates rather than
|
# the reduction so transducing over an INFINITE seq terminates rather than
|
||||||
# realizing it eagerly.
|
# realizing it eagerly.
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,11 @@
|
||||||
["update-proxy" "nil" "(update-proxy nil {})"]
|
["update-proxy" "nil" "(update-proxy nil {})"]
|
||||||
["proxy-mappings" "{}" "(proxy-mappings nil)"]
|
["proxy-mappings" "{}" "(proxy-mappings nil)"]
|
||||||
["proxy-call-with-super calls" "1" "(proxy-call-with-super (fn [] 1) nil \"m\")"]
|
["proxy-call-with-super calls" "1" "(proxy-call-with-super (fn [] 1) nil \"m\")"]
|
||||||
["memfn throws" :throws "((memfn count) \"abc\")"]
|
["memfn upper" "\"ABC\"" "((memfn toUpperCase) \"abc\")"]
|
||||||
|
["memfn with args" "2" "((memfn indexOf needle) \"hello\" \"l\")"]
|
||||||
|
["memfn length" "3" "((memfn length) \"abc\")"]
|
||||||
|
["array-seq" "(quote (1 2 3))" "(array-seq (to-array [1 2 3]))"]
|
||||||
|
["array-seq empty" "nil" "(array-seq (to-array []))"]
|
||||||
["proxy-super throws" :throws "(proxy-super count [1])"]
|
["proxy-super throws" :throws "(proxy-super count [1])"]
|
||||||
["re-groups throws" :throws "(re-groups (re-matcher #\"a\" \"b\"))"]
|
["re-groups throws" :throws "(re-groups (re-matcher #\"a\" \"b\"))"]
|
||||||
["re-matcher builds" "false" "(nil? (re-matcher #\"a\" \"abc\"))"]
|
["re-matcher builds" "false" "(nil? (re-matcher #\"a\" \"abc\"))"]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue