4
(match
   [[1 2 3]]
   [(:or [_ _ 2] 
         [3 _ _])] :a0

   [(:or [_ _ 1] 
         [1 _ _])] :a1
   :else :else)

=> :else

在第一个片段中,我希望它返回:a1

奇怪的。

这有效:

(match
   [[1 2 3]]
   [(:or [_ _ 2] 
         [1 _ _])] :a0

   [(:or [_ _ 1] 
         [3 _ _])] :a1
   :else :else)

=> :a0

这是预期的行为吗?

4

3 回答 3

3

我会说这不是因为:or手册中从未提及您使用的方式。它应该用在这样的表达式中:

[4 (:or 5 6 7) _] :a1

所以你的代码应该看起来像

(match
         [[1 2 3]]
         [[_ _ 2]] :a0
         [[3 _ _]] :a0

         [[_ _ 1]] :a1
         [[1 _ _]] :a1
         :else :else)

但也许你应该咨询作者。很难说初衷是什么。

于 2017-05-04T15:38:41.973 回答
2

我相信这是specialize-or-pattern-row. 我相信groupable?那里的测试是错误的,因为在您的情况下,它对您的两个OrPatterns 成功,因此第二个OrPattern被第一个的扩展替换(它们是第一个ps的子模式OrPattern)。

您可以通过在您的第二个中添加一个虚拟模式来解决此问题,:or这将强制groupable?返回 false:

(match
   [[1 2 3]]
   [(:or [_ _ 2] 
         [1 _ _])] :a0

   [(:or [_ _ 1] 
         [3 _ _]
         :dummy)] :a1
   :else :else)

可能更好specialize-or-pattern-rowcopy-as是否通过将 on 复制到每个子模式来保留:as整体上的任何元数据):OrPattern:as

(defn copy-as [dest src]
  (if-let [as (-> src meta :as)]
    (vary-meta dest assoc :as as)
    dest))

(defn specialize-or-pattern-row [row pat ps]
  (let [p (first row)]
    (if (identical? p pat)
      (map (fn [p] (update-pattern row 0 (copy-as p pat))) ps)
      [row])))
于 2017-05-04T17:45:28.697 回答
0

引用reddit 的回答

似乎是 core.match 中的一个错误。我使用了一个稍微简单的语句,它有同样的问题。

(match
 [[1]]
 [(:or [3] [])] :a0
 [(:or [1] [])] :a1
 :else :else)

这也返回 :else。我通过宏扩展运行它并提取了逻辑。它变成了这样的东西。

(let
 [x [1]]
  (cond (and (vector? x) (== (count x) 1) (= (nth x 0)  3)) :a0
        (and (vector? x) (== (count x) 0)) :a0
        (and (vector? x) (== (count x) 1) (= (nth x 0) 3)) :a1
        (and (vector? x) (== (count x) 0)) :a1))

在第 5 行,您可以看到错误,它是 3 而不是 1。由于某种原因,它采用第一个 :or 模式中的值而不是第二行值。

看来这个补丁解决了这个问题。

谢谢大家!

PS:不过,我还没有测试过补丁。

于 2017-05-07T00:17:21.687 回答