(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
这是预期的行为吗?
答案 0 :(得分:3)
我说这不是因为手册中从未提及您使用:or
的方式。它应该用在像这样的表达式中:
[4 (:or 5 6 7) _] :a1
所以你的代码应该看起来像
(match
[[1 2 3]]
[[_ _ 2]] :a0
[[3 _ _]] :a0
[[_ _ 1]] :a1
[[1 _ _]] :a1
:else :else)
但也许你应该咨询作者。很难说出初衷是什么。
答案 1 :(得分:2)
我认为这是specialize-or-pattern-row
中的错误。我相信groupable?
测试是错误的,因为在您的情况下,它会成功用于您的两个OrPattern
,因此第二个OrPattern
将替换为第一个ps
的扩展({ {1}}是第一个OrPattern
的子模式。
您可以通过向第二个:or
添加虚拟模式来解决此问题,这会强制groupable?
返回false:
(match
[[1 2 3]]
[(:or [_ _ 2]
[1 _ _])] :a0
[(:or [_ _ 1]
[3 _ _]
:dummy)] :a1
:else :else)
可能会更好specialize-or-pattern-row
copy-as
通过将: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])))
答案 2 :(得分:0)
看起来像core.match中的错误。我使用了一个稍微简单的语句来解决同样的问题。
(match
[[1]]
[(:or [3] [])] :a0
[(:or [1] [])] :a1
:else :else)
这也会返回:else。我通过macroexpand运行它并提取逻辑。它变成了这样的东西。
(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.由于某种原因,它采用第一个:或模式而不是第二行值的值。
似乎这个patch解决了这个问题。
谢谢大家!
P.S。:我还没有对这个补丁进行测试。