clojure.string toString coercion; some-fn/ifn? reference semantics; misc host gaps
The clojure.string case fns and searches now take any Object s through its toString like the reference's ^CharSequence signatures ((upper-case :kw) is ":KW", (capitalize 1) is "1"); nil throws, and a nil substr in starts-with?/ends-with? throws. some-fn re-ported with the reference arities: (some-fn) is an arity error and a no-match result is the last predicate's own falsy value (false, not nil). ifn? covers multimethods, promises (which are now invocable — calling one delivers, via a cold-path invoke-arm registry that costs the hot dispatch nothing), and deftypes implementing IFn's invoke. One structural find on the way: defmulti/defmethod deferred inside a fn body (the deftest pattern) interned/resolved in whatever namespace was current when they RAN, not the one they were written in — the macros now bake their expansion ns and the setups honor it. Also: Boolean/Integer/Double wrapper ctors, primitive TYPE statics (Integer/TYPE etc.), .reduce on collections (IReduce), and Long/TYPE. cts baseline 5857 -> 5904 pass, 58 -> 28 errors, 57 baselined namespaces — the string cluster, some-fn, ifn-qmark, boolean-qmark, and reduce namespaces are all fully clean. 7 JVM-certified corpus rows; spec entry.
This commit is contained in:
parent
a9542077fc
commit
e17bcfd0af
15 changed files with 1100 additions and 941 deletions
|
|
@ -155,8 +155,43 @@
|
|||
(when-let [s (seq coll)]
|
||||
(or (pred (first s)) (recur pred (next s)))))
|
||||
|
||||
(defn some-fn [& preds]
|
||||
(fn [& xs] (some (fn [p] (some p xs)) preds)))
|
||||
;; Reference arities: at least one predicate ((some-fn) is an arity error), and
|
||||
;; the returned fn chains with or — a no-match result is the last predicate's
|
||||
;; own falsy value (false stays false, not nil).
|
||||
(defn some-fn
|
||||
([p]
|
||||
(fn sp1
|
||||
([] nil)
|
||||
([x] (p x))
|
||||
([x y] (or (p x) (p y)))
|
||||
([x y z] (or (p x) (p y) (p z)))
|
||||
([x y z & args] (or (sp1 x y z)
|
||||
(some p args)))))
|
||||
([p1 p2]
|
||||
(fn sp2
|
||||
([] nil)
|
||||
([x] (or (p1 x) (p2 x)))
|
||||
([x y] (or (p1 x) (p1 y) (p2 x) (p2 y)))
|
||||
([x y z] (or (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z)))
|
||||
([x y z & args] (or (sp2 x y z)
|
||||
(some (fn [q] (or (p1 q) (p2 q))) args)))))
|
||||
([p1 p2 p3]
|
||||
(fn sp3
|
||||
([] nil)
|
||||
([x] (or (p1 x) (p2 x) (p3 x)))
|
||||
([x y] (or (p1 x) (p2 x) (p3 x) (p1 y) (p2 y) (p3 y)))
|
||||
([x y z] (or (p1 x) (p2 x) (p3 x) (p1 y) (p2 y) (p3 y) (p1 z) (p2 z) (p3 z)))
|
||||
([x y z & args] (or (sp3 x y z)
|
||||
(some (fn [q] (or (p1 q) (p2 q) (p3 q))) args)))))
|
||||
([p1 p2 p3 & ps]
|
||||
(let [ps (cons p1 (cons p2 (cons p3 ps)))]
|
||||
(fn spn
|
||||
([] nil)
|
||||
([x] (some (fn [p] (p x)) ps))
|
||||
([x y] (or (spn x) (spn y)))
|
||||
([x y z] (or (spn x) (spn y) (spn z)))
|
||||
([x y z & args] (or (spn x y z)
|
||||
(some (fn [p] (some p args)) ps)))))))
|
||||
|
||||
(defn not-any? [pred coll] (not (some pred coll)))
|
||||
|
||||
|
|
|
|||
|
|
@ -183,10 +183,16 @@
|
|||
([x y z & args] (f (apply g x y z args)))))
|
||||
([f g & fs] (reduce comp (comp f g) fs)))
|
||||
|
||||
;; Canonical IFn set: fns, keywords, symbols, maps (sorted incl.),
|
||||
;; sets, vectors, and vars — NOT lists ((ifn? '(1 2)) is false in Clojure).
|
||||
;; Canonical IFn set: fns, keywords, symbols, maps (sorted incl.), sets,
|
||||
;; vectors, vars — NOT lists ((ifn? '(1 2)) is false in Clojure) — plus the
|
||||
;; host callables (multimethods, promises) and a deftype/record implementing
|
||||
;; clojure.lang.IFn's invoke.
|
||||
(defn ifn? [x]
|
||||
(or (fn? x) (keyword? x) (symbol? x) (map? x) (set? x) (vector? x) (var? x)))
|
||||
(if (or (fn? x) (keyword? x) (symbol? x) (map? x) (set? x) (vector? x) (var? x)
|
||||
(jolt.host/callable-host? x)
|
||||
(jolt.host/jrec-method? x "invoke"))
|
||||
true
|
||||
false))
|
||||
|
||||
;; Auto-promoting (') and unchecked arithmetic. Jolt numbers don't overflow,
|
||||
;; so all of these are the checked ops; fixed arities mirror Clojure's
|
||||
|
|
|
|||
|
|
@ -28,11 +28,18 @@
|
|||
(let [args (if (string? (first args)) (rest args) args)
|
||||
args (if (and (map? (first args)) (not (symbol? (first args)))) (rest args) args)
|
||||
dispatch (first args)
|
||||
opts (rest args)]
|
||||
`(defmulti-setup (quote ~name) ~dispatch ~@opts)))
|
||||
opts (rest args)
|
||||
;; qualify with the EXPANSION ns: a defmulti deferred inside a fn (a
|
||||
;; deftest body) must still define in the ns it was written in.
|
||||
qname (symbol (str (clojure.core/ns-name clojure.core/*ns*))
|
||||
(clojure.core/name name))]
|
||||
`(defmulti-setup (quote ~qname) ~dispatch ~@opts)))
|
||||
|
||||
(defmacro defmethod [mm dispatch-val & fn-tail]
|
||||
`(defmethod-setup (quote ~mm) ~dispatch-val (fn ~@fn-tail)))
|
||||
;; the expansion ns rides along so a deferred defmethod resolves its multifn
|
||||
;; against the ns it was written in (aliases and refers included).
|
||||
`(defmethod-setup (quote ~mm) ~dispatch-val (fn ~@fn-tail)
|
||||
~(str (clojure.core/ns-name clojure.core/*ns*))))
|
||||
|
||||
;; Multimethod table ops: a multimethod's method table lives on its
|
||||
;; VAR (the value is just the dispatch closure), so these pass the name quoted
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue