这是ClojureScript中re-seq实现中的一个bug
(defn re-seq
"Returns a lazy sequence of successive matches of re in s."
[re s]
(let [match-data (re-find re s)
match-idx (.search s re)
match-str (if (coll? match-data) (first match-data) match-data)
post-idx (+ match-idx (max 1 (count match-str)))
post-match (subs s post-idx)]
(when match-data (lazy-seq (cons match-data (when (<= post-idx (count s)) (re-seq re post-match)))))))
问题出现在它递归地用字符串的剩余部分调用re-seq,这样做意味着^[a-f]将再次与这个新、较短的字符串匹配。
一个解决方案是将你的正则表达式设置为粘性边界匹配
(js/RegExp. #"^." "y")
这会让你的正则表达式的后续使用明白之前匹配的哪个地方,请注意,你需要准确地放置此代码,因为它需要在正确的位置创建,它不可以是全局的!如果它是全局的,你将会遇到一些奇怪的状态问题,就像这个一个。
(let [re (js/RegExp. #"^." "y")]
[(re-seq re "cccc")
(re-seq re "abbb")])
;; => [("c" "c") nil]
(我完全无法解释!)
可能有一个re-seq
的替换实现会为你克隆出这个初始的实例
(defn re-seq2
"Returns a lazy sequence of successive matches of re in s."
[re s]
(let [re-seq* (fn re-seq* [re s]
(let [match-data (re-find re s)
match-idx (.search s re)
match-str (if (coll? match-data) (first match-data) match-data)
post-idx (+ match-idx (max 1 (count match-str)))
post-match (subs s post-idx)]
(when match-data (lazy-seq (cons match-data (when (<= post-idx (count s)) (re-seq* re post-match)))))))]
(re-seq* (js/RegExp. re "y") s)))
(let [re #"^."]
[(re-seq2 re "cccc")
(re-seq2 re "abbb")])
;; => [("c") ("a")]