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, *, +, ?, keys*, &。
...