I would not use ref-set, but alterbecause you do not reset the state to a completely new value, but update it to a new value, which is obtained from the old one.
(defn block-scanner
[trigger-string]
(let [curr (ref trigger-string)
trig trigger-string]
(fn [data]
(doseq [c data]
(when (seq @curr)
(dosync
(alter curr
(rest %)
trig)))))
(empty? @curr))))
Then there is no need to use refs, since you do not need to coordinate the changes. Here the atom is better suited, as it can be changed without any STM ceremony.
(defn block-scanner
[trigger-string]
(let [curr (atom trigger-string)
trig trigger-string]
(fn [data]
(doseq [c data]
(when (seq @curr)
(swap! curr
(rest %)
trig))))
(empty? @curr))))
Next, I would get rid of the imperative style.
- , : , . .
- , - . . ( , , , .)
- . , .
(defn block-scanner
[trigger-string]
(let [state (atom trigger-string)
advance (fn [trigger d]
(when trigger
(condp = d
(first trigger) (next trigger)
; This is maybe a bug in the book. The book code
; matches "foojihad", but not "jijihad".
(first trigger-string) (next trigger-string)
trigger-string)))
update (fn [trigger data]
(if-let [data (seq data)]
(when-let [trigger (advance trigger (first data))]
(recur trigger (rest data)))
trigger))]
(fn [data]
(nil? (swap! state update data)))))