首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将模式和结果作为向量传递给core.match/match的宏

将模式和结果作为向量传递给core.match/match的宏
EN

Stack Overflow用户
提问于 2016-05-15 23:53:28
回答 2查看 106关注 0票数 3

我正在努力构建一个宏,让我以向量的形式将模式和结果传递给core.match/match。我希望能够做到这一点:

代码语言:javascript
复制
(let [x {:a 1}
      patterns [[{:a 2}] :high
                [{:a 1}] :low]]
     (my-match x patterns))

> :low

我已经尝试了下面和其他几种方法,除非我将模式作为文字传递,否则这些方法都不起作用。

代码语言:javascript
复制
(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
EN

回答 2

Stack Overflow用户

发布于 2016-05-16 03:20:20

宏是在编译时展开的,因此在展开期间不能依赖运行时信息(参数值)。问题的根源在于,你不能像应用函数一样应用宏。

In clojure, how to apply a macro to a list?

因此,您必须使用eval:

代码语言:javascript
复制
(defmacro functionize [macro]
  `(fn [& args#] (eval (cons '~macro args#))))

(defmacro my-match [e ems]
  `(apply (functionize m/match) [~e] ~ems))

或者以不同的方式处理问题(执行运行时模式匹配,而不是编译时模式匹配)。

票数 2
EN

Stack Overflow用户

发布于 2016-05-16 06:39:39

解决问题的最简单方法是使用简单的旧地图:

代码语言:javascript
复制
(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:

代码语言:javascript
复制
(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})   ;=> true
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37240405

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档