Clojure模式匹配宏具有超出显式匹配情况的变量arity



我正在将一些代码从Scheme转换为Clojure。Scheme代码使用一个名为pmatch的宏(https://github.com/webyrd/quines/blob/master/pmatch.scm)将参数模式匹配到输出表达式。具体来说,它允许变量捕获如下:

(define eval-expr
  (lambda (expr)
    (pmatch expr
      [(zero? ,e)
       (zero? (eval-expr e)))
...

在这个使用示例中,eval-expr的某些输入表达式'(zero? 0)应该与第一种情况匹配。列表中的car与zero?匹配,并且输入的arity匹配。因此,0被绑定到,e并被传递到(zero? (eval-expr e)),并且这个expr被递归地计算。在本机支持模式匹配的Haskell中,代码可能会转换为以下内容:

Prelude> let evalexpr "zero?" e = (e == 0) -- ignoring recursive application
Prelude> evalexpr "zero?" 0
True

在Clojure中,我第一次尝试用core.match代替pmatch(https://github.com/clojure/core.match),这是由David Nolen和其他人写的,但是,据我所知,这个宏在看来

  1. 每次使用仅支持单个参数arity
  2. 仅支持显式匹配,而不支持基于属性的匹配(可用作保护(

我正在尝试的另一个选项是一个鲜为人知的宏defun(https://github.com/killme2008/defun),定义了模式匹配函数。这里有一个例子:

(defun count-down
  ([0] (println "Reach zero!"))
  ([n] (println n)
     (recur (dec n))))

我仍在探索撤资,看看它是否能给我所需的灵活性同时,有人建议如何在Clojure中使用1进行模式匹配吗。灵活的arity 2。变量捕获

忽略递归应用程序:

(ns test.test
  (:require [clojure.core.match :refer [match]]))

(def v [:x 0])
(def w [:x :y 0])
(defn try-match [x]
  (match x
         [:x e] e
         [:x expr e] [expr e]
         ))
(try-match v)
;; => 0
(try-match w)
;; => [:y 0]

;; Matching on lists (actually, any sequences)
(defn try-match-2 [exp]
  (match exp
         ([op x] :seq) [op x]
         ([op x y] :seq) [op x y]))
(try-match-2 '(+ 3))
;; => [+ 3]
(try-match-2 '(+ 1 2))
;; => [+ 1 2]

请参阅https://github.com/clojure/core.match/wiki/Overview了解更多详细信息。

此外,我建议您仔细研究Clojure析构函数。使用它可以完成很多事情,而无需求助于core.match,实际上您的用例已经涵盖在内。

相关内容

最新更新