This function was hard to write as a Clojure newbie, and I don't like the result. Can you help me find a better (more readable) way to do it?
(defn split-seq
"Splits a seq into blocks defined by start-fn and stop-fn.
Returns a lazy seq of seqs"
[start-fn stop-fn lines]
(let [step (fn [c state]
(when-let [s (seq c)]
(if (stop-fn (first s))
(cons state (split-seq start-fn stop-fn (rest s) ))
(recur (rest s)
(if (start-fn (first s))
'()
(cons (first s) state))))))]
(lazy-seq (step lines '()))))
(defn post-start? [l] (.startsWith l "#ENTRY_START"))
(defn post-end? [l] (.startsWith l "#ENTRY_END"))
(defn split-lines
"Split a line-seq into entries based on #ENTRY_START and #ENTRY_END."
[data]
(split-seq post-start? post-end? data))
;
; Test
;
(def test-data [
"Header line"
"#ENTRY_START"
"entry line 1 "
"entry line 2"
"#ENTRY_END"
"This line should be filtered out"
"#ENTRY_START Having data here shouldn't make a difference."
"entry line 1 "
"entry line 2"
"#ENTRY_END"
"This should be gone too"])
(split-lines test-data)
; yields (("entry line 2" "entry line 1 ") ("entry line 2" "entry line 1 "))
; The order of elements doesn't matter in my case because I'm making a map with this data
With Arthurs help, the final code looks like this:
(defn entry-seq [data]
(let [[f r] (split-with #(not (post-end? %))
(rest (drop-while #(not (post-start? %)) data)))]
(when (not-empty f) (lazy-seq (cons f (entry-seq2 r))))))
Still lazy and a lot more readable!