How to convert an expression to a predicate? (Clojure)

Given that I have an expression of the form

'(map? %)

How to convert it to something like

'#(map? %)

So that I can eventually deploy it into something like

'(apply #(map? %) value)

I think I should somehow use the macro, but not sure how to do it.

+5
source share
2 answers

#causes the reader macro and reader macros to expand before the regular macro expands. To do what you mentioned, you need to go through the reader in your macro using read-string, as shown below.

(defmacro pred [p v] 
     (let [s# (str \# (last p))] 
         `(apply ~(read-string s#) ~v)))



user=> (pred '(map? %) [{}])
true
user=> (pred '(map? %) [[]])
false

If the data, that is, the predicate expression is available at run time, you need to use a function (which is more flexible than a macro).

(defn pred [p v] 
   (let [s (read-string (str \# p))] 
      (eval `(apply ~s ~v))))

user=> (map #(pred % [12]) ['(map? %)'(even? %)])
(false true)
+6
source

#(...) - . , . , '#(map? %) (fn* [p1__352#] (map? p1__352#)) - .

.

? :

'([arg1] (map? arg1))

:

(cons 'fn '([arg1] (map? arg1)))

(def pred (eval (cons 'fn '([p](map? p)))))
#'predicate.core/pred

(pred {})
true

(pred 10)
false

, , , . :

(defn get-args [p]
  (filter #(.matches (str %) "%\\d*")
          (flatten p)))

(defn gen-args [p]
  (into [] 
        (into (sorted-set) 
              (get-args p))))

(defmacro simulate-reader [p]
  (let [arglist (gen-args p)
        p (if (= (str (first p)) "quote")
            (second p)
            p)]
    (list 'fn (gen-args p) p)))

:

((simulate-reader '(map? %)) {}) ; -> true
; or without quote
((simulate-reader (map? %)) {})

; This also works:
((simulate-reader '(+ %1 %2)) 10 5) ; -> 15

, @Ankur:

  • . , .
  • , .
+3

All Articles