2024年 Clojure 状态调查!中分享您的想法。

欢迎!请查看关于页面以了解更多关于如何使用本页面的信息。

0
Spec

我有一系列字符,并试图使用 (s/cat ...) 和 (s/or) 使其匹配序列。

输入可能看起来像 [0 1 2 3][\a \b \c \d],我正在尝试使用此规范。

(s/conform (s/cat :top (s/or :nums (s/+ #{0 1 2 3 4})
                             :letters (s/+ #{\a \b \c \d})
                  ... more stuff))
           [0 1 2 3])
=> :clojure.spec.alpha/invalid

如果不使用 (s/or),如果选择 :nums:letters 之一,则可以正常工作。

(s/conform (s/cat :first-set (s/+ #{0 1 2 3 4}))
           [0 1 2 3])
=> {:first-set [0 1 2 3]}

初始示例如果整个序列被另一个 vec 包裹也会正常工作,但这不是我想要的。

(s/conform (s/cat :first-set (s/or :nums (s/+ #{0 1 2 3 4})
                                   :letters (s/+ #{\a \b \c \d})))
           [[0 1 2 3]])
=> {:first-set [:nums [0 1 2 3]]}

使用 (or ...) 似乎只能在 (s/keys) 中工作。我猜这是因为 (or 总是取第一个规范,因为它不是假值。

(s/conform (s/cat :first-set (or (s/+ #{0 1 2 3 4})
                                 (s/+ #{\a \b \c \d})))
           [0 1 2 3])
=> {:first-set [0 1 2 3]}

(s/conform (s/cat :first-set (or (s/+ #{0 1 2 3 4})
                                 (s/+ #{\a \b \c \d})))
           [\a \b \c])
=> :clojure.spec.alpha/invalid

这是我想要发生的。

(s/conform (s/cat :first-set (s/something-here (s/+ #{0 1 2 3 4})
                                               (s/+ #{\a \b \c \d})))
           [0 1 2 3])
=> {:first-set [0 1 2 3]}

(s/conform (s/cat :first-set (s/something-here (s/+ #{0 1 2 3 4})
                                               (s/+ #{\a \b \c \d})))
           [\a \b \c])
=> {:first-set [\a \b \c]}

我在想这里该怎么办。

1 个回答

+3

被选中
 
最佳答案

在正则表达式上下文中应使用 s/alt 而不是 s/or

(s/conform (s/cat :top (s/alt :nums (s/+ #{0 1 2 3 4})
                              :letters (s/+ #{\a \b \c \d})))
           [0 1 2 3])
=> {:top [:nums
          [0 1 2 3]]}

因为 s/or 不是一个正则操作符,它将匹配下一个项目而不是一个序列

(s/conform (s/cat :top (s/or :nums (s/+ #{0 1 2 3 4})
                              :letters (s/+ #{\a \b \c \d})))
           [[0 1 2 3]]) ;; note that it's wrapped vector
=> {:top [:nums
          [0 1 2 3]]}
正则运算符组合,这样它们总是匹配单个集合,而不是嵌套集合。正则运算符有cat、alt、*、+、?键*和&。
...