如何将表达式转换为谓词?(Clojure)

如何将表达式转换为谓词?(Clojure),clojure,expression,predicate,Clojure,Expression,Predicate,假设我有一个表达式的形式 '(map? %) 如何将其转换为类似的内容 '#(map? %) 这样我就可以最终把它扩展成 '(apply #(map? %) value) 我想我应该以某种方式使用宏,但不确定如何使用。#(…)是一个读卡器宏。我认为不能用reader宏生成表达式。例如,”#(map?%)将自动展开为(fn*[p1_uuu352#](map?p1_352#))或类似内容 这里有一个关于其他阅读器的宏 是否可以更改谓词的格式?如果它看起来像: '([arg1] (map? ar

假设我有一个表达式的形式

'(map? %)
如何将其转换为类似的内容

'#(map? %)
这样我就可以最终把它扩展成

'(apply #(map? %) value)
我想我应该以某种方式使用宏,但不确定如何使用。

#(…)
是一个读卡器宏。我认为不能用reader宏生成表达式。例如,
”#(map?%)
将自动展开为
(fn*[p1_uuu352#](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

现在请不要因为我接下来要发布的内容而恨我。我编写了一个过于简化的function reader宏版本:

(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给出的其他解决方案的区别是:

  • 我不太喜欢我的。我只是觉得这样做很有趣
  • 不需要转换为字符串,然后对其应用读取器宏
  • #
    调用读卡器宏,读卡器宏的扩展在正常宏扩展之前进行。因此,要执行您提到的操作,您需要使用
    read string
    遍历宏中的读取器,如下所示

    (defmacro pred [p v] 
         (let [s# (str \# (last p))] 
             `(apply ~(read-string s#) ~v)))
    
    
    
    user=> (pred '(map? %) [{}])
    true
    user=> (pred '(map? %) [[]])
    false
    
    如果数据(即谓词表达式)在运行时可用,则需要使用函数(比宏更灵活)


    您的意思是将
    (map?%)
    存储为数据,即作为带有两个符号的列表吗?是的,我确实在尝试在宏中执行此操作,我想我会引用所有内容来表示我想要的内容……但为什么要使用reader宏呢?为什么不直接使用
    fn
    ?可能是因为他希望输入谓词没有fn签名,并使用%1%2等作为参数名。这个问题非常具体,并没有提供可能导致更好的解决方案的整体情况好的一点,我没有看到,因为他的源数据包含对
    %
    的引用,它似乎设计用于
    #(…)
    。哇,非常有趣。我确信我遗漏了一些东西,因为我不知道如何使用正常的宏机制将#放置到位。我问这个问题的原因是因为我注意到prepost参数中的:post键是?在defn参数列表中,接受表达式向量。我很好奇表达式是如何计算的,因为它们被声明为表达式,而不是匿名函数。
    (defn pred [p v] 
       (let [s (read-string (str \# p))] 
          (eval `(apply ~s ~v))))
    
    user=> (map #(pred % [12]) ['(map? %)'(even? %)])
    (false true)