specter 2026-08-25

Hello! Thank you for the library! It is great 🙂 Recently I upgraded Clojure on one of our projects that uses Specter and noticed that one test case failed with a compilation error when it tried to build a path containing nil?

Unable to resolve var: clojure.lang.Util/identical in this context
It might be related to https://insideclojure.org/2024/02/12/method-values/
(riddley/macroexpand-all '(nil? nil)) ;; => (clojure.lang.Util/identical nil nil)
before 1.12.0-alpha6 nil? expanded to (. clojure.lang.Util identical nil nil) I don’t fully understand how magic-precompilation works and what is expected there. This little patch where I try to resolve on symbol’s namespace fixes the compilation issue but I’m not confident it is the right solution:
diff --git a/src/clj/com/rpl/specter.cljc b/src/clj/com/rpl/specter.cljc
index e83bf43..5f2aed2 100644
--- a/src/clj/com/rpl/specter.cljc
+++ b/src/clj/com/rpl/specter.cljc
@@ -199,17 +199,19 @@
          (symbol? path)
          (if (contains? locals-set path)
            (let [s (get locals-set path)
                  embed (i/maybe-direct-nav path (-> s meta :direct-nav))]
              `(com.rpl.specter.impl/->LocalSym ~path (quote ~embed)))
            ;; var-get doesn't work in cljs, so capture the val in the macro instead
            `(com.rpl.specter.impl/->VarUse
               ~path
-              ~(if-not (instance? Class (resolve path)) `(var ~path))
+              ~(if-not (instance? Class (or (resolve path)
+                                            (some-> path namespace symbol resolve)))
+                 `(var ~path))
               (quote ~path)))


          (i/fn-invocation? path)
          (let [[op & params] path]
            ;; need special case for 'fn since macroexpand does NOT
            ;; expand fn when run on cljs code, but it's also not considered a special symbol
            (if (or (= 'fn op) (special-symbol? op))
--

can you provide code that reproduces the issue?

I haven't seen this using it with 1.12.4, and using nil? in a path is very common

Hello! This is the exact function which failed to compile on with Clojure newer than 1.12.0-alpha5:

(defn convert-ignore-case-flag
  [ignore-case? new-operator condition]
  (transform
   (constantly (not (nil? ignore-case?)))
   (fn [condition]
     (if (= new-operator :matches-regex)
       (transform [:params (must 1) (must :values) ALL]
                  make-regex-case-insensitive
                  condition)
       (setval [:ignore-case?] ignore-case? condition)))
   condition))

ah I see, it's a bad interaction between Clojure inlining nil? and the inline compiler for Specter

you can work around it with something like (let [f (constantly (not (nil? ignore-case?)))] (transform (pred f) ...

Awesome, it will do! Thanks for putting your work into the library :)