A fn def'd into a var reports a JVM-style class name (clojure.core$odd_QMARK_)
jolt fns reported (class f) = clojure.lang.IFn, so they carried no defining symbol — clojure.spec.alpha's fn-sym (which reads a fn's class name to recover its symbol) produced garbage, so explain-data's :pred for a bare-fn predicate was `/` instead of e.g. clojure.core/keyword?. Now def-var! records proc -> (ns . name) (first def of a proc wins, so an alias like (def inc' inc) doesn't rename inc), and jolt-class-name returns "ns$munged" for a known fn — matching the JVM, where (class odd?) is clojure.core$odd_QMARK_. A munged fn class's ancestors include clojure.lang.AFunction's hierarchy (IFn/AFn/Fn/Runnable/Callable), so (ancestors (class f)) still holds. Anonymous / unregistered fns stay clojure.lang.IFn (fn-sym yields :unknown, as on the JVM). This fixes explain-data / s/form / s/describe of bare-fn predicates in clojure.spec.alpha (and unblocks parts of its suite + test.check's reporter test). make test green (+1 corpus row, the (type inc) unit row updated to the JVM value), shakesmoke byte-identical, runtime only (no re-mint).
This commit is contained in:
parent
10592fa746
commit
0becba7f93
5 changed files with 43 additions and 4 deletions
|
|
@ -114,7 +114,16 @@
|
|||
;; evaluates to #'ns/name (a first-class var), so (var? (def x 1)) is true and
|
||||
;; (pr-str (def x 1)) is "#'ns/x". The prelude's def-var! forms discard the
|
||||
;; return, so this is transparent there.
|
||||
(define (def-var! ns name v) (let ((c (jolt-var ns name))) (var-cell-root-set! c v) (var-cell-defined?-set! c #t) c))
|
||||
;; proc -> (ns . name) for the var it was def'd into, so (class a-fn) can report a
|
||||
;; JVM-style class name and clojure.spec.alpha's fn-sym can recover the symbol of a
|
||||
;; bare-fn predicate. Weak so GC'd fns drop out. Last def of a given proc wins.
|
||||
(define proc-name-tbl (make-weak-eq-hashtable))
|
||||
(define (def-var! ns name v)
|
||||
;; first def of a given proc wins, so an alias like (def inc' inc) — which binds
|
||||
;; the SAME proc to a second var — doesn't rename inc.
|
||||
(when (and (procedure? v) (not (hashtable-contains? proc-name-tbl v)))
|
||||
(hashtable-set! proc-name-tbl v (cons ns name)))
|
||||
(let ((c (jolt-var ns name))) (var-cell-root-set! c v) (var-cell-defined?-set! c #t) c))
|
||||
;; jolt.host/throwable — build a typed throwable a library can throw so (class …),
|
||||
;; instance?, .getMessage and ex-message all reflect the named JVM class (e.g. an
|
||||
;; http client throwing java.net.ConnectException). Strictly better than a
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue