我正在努力构建一个宏,让我以向量的形式将模式和结果传递给core.match/match。我希望能够做到这一点:
(let [x {:a 1}
patterns [[{:a 2}] :high
[{:a 1}] :low]]
(my-match x patterns))
> :low我已经尝试了下面和其他几种方法,除非我将模式作为文字传递,否则这些方法都不起作用。
(defmacro my-match [e ems]
`(m/match [~e] ~@ems))
(let [x {:a 1}
patterns [[{:a 2}] :high
[{:a 1}] :low]]
(my-match x patterns))
=> CompilerException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol, compiling:(*cider-repl kontrakt*:106:10)
(let [x {:a 1}]
(my-match x [[{:a 2}] :high
[{:a 1}] :low]))
=> :low发布于 2016-05-16 03:20:20
宏是在编译时展开的,因此在展开期间不能依赖运行时信息(参数值)。问题的根源在于,你不能像应用函数一样应用宏。
In clojure, how to apply a macro to a list?
因此,您必须使用eval:
(defmacro functionize [macro]
`(fn [& args#] (eval (cons '~macro args#))))
(defmacro my-match [e ems]
`(apply (functionize m/match) [~e] ~ems))或者以不同的方式处理问题(执行运行时模式匹配,而不是编译时模式匹配)。
发布于 2016-05-16 06:39:39
解决问题的最简单方法是使用简单的旧地图:
(ns clj.core
(:use tupelo.core))
(def x {:a 1} )
(def patterns { {:a 2} :high
{:a 1} :low } )
(spyx (get patterns x))
;=> (get patterns x) => :low因为没有“通配符值”,所以根本不需要core.match。如果您想匹配通配符的值,请参阅函数wild-match? in the Tupelo library. Samples:
(wild-match? {:a :* :b 2}
{:a 1 :b 2}) ;=> true
(wild-match? [1 :* 3]
[1 2 3]
[1 9 3] )) ;=> true
(wild-match? {:a :* :b 2}
{:a [1 2 3] :b 2}) ;=> truehttps://stackoverflow.com/questions/37240405
复制相似问题