re-seq creates a lazy sequence of every match for a regular expression in a string or other CharSequence. Use it when re-find's first match is insufficient. section 9.3.5 section 19.10
The pattern must be a java.util.regex.Pattern, commonly written with a #"regex" reader literal; the input must be a CharSequence. Nil for either argument raises NullPointerException. An empty input returns nil. Without capturing groups, matches are strings; with groups, each match includes the captured values. section 9.3.5
Extracting captured fields
A capturing group can turn a larger match into useful fields: (let [people (re-seq #"(\\w+) (\\d{3}) \\d{3}-\\d{4}" signed-up)] {:names (map second people) :area (map last people)}) ;; {:names ("Jack" "Anna" "Charlie" "Hugo" "Jane" "Ron") ;; :area ("221" "221" "661" "661" "661" "555")}
Consuming only needed matches
Laziness supports partial consumption: (take 20 (re-seq #"\\d" pi-digits)) Only the requested portion of the match sequence needs to be produced, although the source string must already be loaded in memory. section 9.3.5
(import '[java.io InputStream]
'[java.net URL]
'[java.util Scanner]
'[java.util.regex Pattern])
(defn restream-seq [^Pattern re ^InputStream is] ; #1
(let [s (Scanner. is "UTF-8")]
((fn step []
(if-let [token (.findInLine s re)]
(cons token (lazy-seq (step)))
(when (.hasNextLine s) (.nextLine s) (step)))))))
(defn pi-seq [is] ; #2
(sequence
(comp
cat
(map int)
(map #(mod % 48)))
(restream-seq #"\d{10}" is)))
(def pi-digits (URL. "https://tinyurl.com/pi-digits"))
(with-open [is (.openStream pi-digits)] ; #3
(doall (take 20 (pi-seq is))))
;; (1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 2 3 8 4 6)
Shows a stream-oriented rework for inputs too large to load as one string; ordinary re-seq itself remains string-based. section 9.3.5
