简体   繁体   English

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

[英]Clojure pattern matching macro with variable arity that goes beyond explicit match cases

I'm in the process of translating some code from Scheme to Clojure. 我正在将一些代码从Scheme转换为Clojure。 The Scheme code uses a macro called pmatch ( https://github.com/webyrd/quines/blob/master/pmatch.scm ) to pattern match arguments to output expressions. Scheme代码使用一个名为pmatch的宏( https://github.com/webyrd/quines/blob/master/pmatch.scm )来将匹配参数模式pmatch输出表达式。 Specifically, it allows for variable capture as follows: 具体来说,它允许变量捕获如下:

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

In this use example, some input expression to eval-expr , '(zero? 0) , should match the the first case. 在此用例中, eval-expr某些输入表达式'(zero? 0)应与第一种情况匹配。 The car of the list matches to zero? 列表的车匹配zero? and the arity of the input matches. 并且输入的arity匹配。 As a consequence, 0 is bound to ,e and passed to (zero? (eval-expr e)) , and this expr is evaluated recursively. 结果,0被绑定到e并传递给(zero? (eval-expr e)) ,并且递归地计算该expr。 In Haskell, which supports pattern matching natively, the code might translate to something like the following: 在本机支持模式匹配的Haskell中,代码可能会转换为如下所示:

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

In Clojure, I first tried to substitute pmatch with core.match ( https://github.com/clojure/core.match ), which was written by David Nolen and others, but, to my knowledge, this macro seems to 在Clojure中,我首先尝试用core.match( https://github.com/clojure/core.match )替换pmatch,这是由David Nolen和其他人编写的,但据我所知,这个宏看起来似乎

  1. only support a single arity of arguments per use 每次使用只支持一个参数arity
  2. only support explicit matching, rather than property based matching (available as guards) 仅支持显式匹配,而不是基于属性的匹配(可用作警卫)

Another option I'm trying is a lesser known macro called defun ( https://github.com/killme2008/defun ), which defines pattern matching functions. 我正在尝试的另一个选项是一个鲜为人知的宏,称为defunhttps://github.com/killme2008/defun ),它定义了模式匹配函数。 Here's an example: 这是一个例子:

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

I'm still exploring defun to see if it gives me the flexibility I need. 我还在探索defun,看看它是否给了我所需的灵活性。 Meanwhile, does anyone have suggestions of how to pattern match in Clojure with 1. flexible arity 2. variable capture? 同时,是否有人建议如何在Clojure中进行模式匹配1.灵活的arity 2.变量捕获?

Ignoring recursive application: 忽略递归应用程序:

(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]

See https://github.com/clojure/core.match/wiki/Overview for more details. 有关详细信息,请参阅https://github.com/clojure/core.match/wiki/Overview

Additionally, I suggest you have a close look at Clojure destructuring . 另外,我建议你仔细看看Clojure解构 Lots of things can be done with it without resorting to core.match , actually your use case is covered. 可以使用它完成很多事情而无需求助于core.match ,实际上你的用例已经涵盖了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM