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!