【问题标题】:Macro to pass patterns and results to core.match/match as a vector将模式和结果作为向量传递给 core.match/match 的宏
【发布时间】:2016-05-15 15:53:28
【问题描述】:

我正在努力构建一个宏,让我可以将模式和结果以向量的形式传递给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

【问题讨论】:

    标签: clojure macros core.match


    【解决方案1】:

    宏在编译时被扩展,所以你不能在扩展过程中依赖运行时信息(参数的值)。根本问题是您不能像应用函数一样应用宏。

    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))
    

    或以不同的方式解决问题(执行运行时模式匹配而不是编译时模式匹配)。

    【讨论】:

      【解决方案2】:

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

      (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})   ;=> true
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多