(reader-conditional? value)
Return true if the value is the data representation of a reader conditional
(reader-conditional? (read-string {:read-cond :preserve} "#?(:clj (Math/exp 1))"))
;;=> true
(reader-conditional? (reader-conditional '(:clj (Math/exp 1)) false))
;;=> true
(reader-conditional? "#?(:clj (Math/exp 1))")
;;=> false
(reader-conditional? '#?(:clj (Math/exp 1)))
;;=> false
;;;; Let's say we have the source code for a Clojure program:
(def source-code
"(defn str-to [type s]
(case type
:int #?(:clj (Integer/parseInt s) :cljs (js/parseInt s))
#?@(:clj [:long (Long/parseLong s)])
:float #?(:clj (Float/parseFloat s) :cljs (js/parseFloat s))
#?@(:clj [:double (Double/parseDouble s)])))")
;;;; Here's a function that finds all the reader conditionals
;;;; in a given source code which contain a specific platform tag:
(defn find-reader-conditionals [code tag]
(->> code
(read-string {:read-cond :preserve}) ;; read into Clojure data structures
(tree-seq seqable? identity) ;; lazy seq of all forms
(filter reader-conditional?) ;; keep only reader conditionals
(filter #(some #{tag} (:form %))))) ;; keep only reader conds with tag
(pprint (find-reader-conditionals source-code :clj))
;;=> (#?(:clj (Integer/parseInt s) :cljs (js/parseInt s))
;; #?@(:clj [:long (Long/parseLong s)])
;; #?(:clj (Float/parseFloat s) :cljs (js/parseFloat s))
;; #?@(:clj [:double (Double/parseDouble s)]))
(pprint (find-reader-conditionals source-code :cljs))
;;=> (#?(:clj (Integer/parseInt s) :cljs (js/parseInt s))
;; #?(:clj (Float/parseFloat s) :cljs (js/parseFloat s)))