On Thu, Feb 16, 2012 at 14:06 -0600, Michael Gardner wrote: > On Feb 16, 2012, at 11:08 AM, Wolodja Wentland wrote: > > > Thanks for the explanation. What would be a good way to ensure that the > > subseqeuence are lazy too? > > I can't think of a good way to do this with higher-order functions, so > you'll probably have to write a recursive function that "manually" iterates > over the collection, looking ahead as necessary to figure out when to split. > To make the result lazy, just wrap your function's body in a call to > lazy-seq.
Just for the sake of completeness and in the case somebody stumbles over this thread in the future. I solved the problem for now and have a lazy implementation of split-at-subsequence that behaves like split does for strings: --- snip --- user> (split-at-subsequence [0] (range 10)) ((1 2 3 4 5 6 7 8 9)) user> (split-at-subsequence [1 2] (range 10)) ((0) (3 4 5 6 7 8 9)) user> (split-at-subsequence [1 2] [1 2 0 1 2 1 1 2 3) ; Evaluation aborted. user> (split-at-subsequence [1 2] [1 2 0 1 2 1 1 2 3]) ((0) (1) (3)) user> (split-at-subsequence [1 2] [1 2 0 1 2 1 1 2 2]) ((0) (1) (2)) user> (split-at-subsequence [1 2] [1 2 1 2 1 2]) () user> (first (second (split-at-subsequence [1 2] (range)))) 3 (defn prefix? "Return true if sub is a prefix of s" [sub s] (loop [sub (seq sub), s (seq s)] (or (nil? sub) (and s (= (first sub) (first s)) (recur (next sub) (next s)))))) (defn replace-subsequence "Replaces all instances of sub with replacement in s" [sub replacement s] {:pre [(seq sub)]} (when-let [s (seq s)] (lazy-seq (if (prefix? sub s) (cons replacement (replace-subsequence sub replacement (drop (count sub) s))) (cons (first s) (replace-subsequence sub replacement (next s))))))) (defn replace-first-subsequence "Replaces the first instance of sub with replacement in s" [sub replacement s] {:pre [(seq sub)]} (when-let [s (seq s)] (lazy-seq (if (prefix? sub s) (cons replacement (drop (count sub) s)) (cons (first s) (replace-first-subsequence sub replacement (next s))))))) (defn- splitter [delimiter s] (lazy-seq (when-let [s (seq s)] (let [data? #(not (identical? delimiter %))] (if (not (identical? delimiter (first s))) (cons (take-while data? s) (splitter delimiter (drop-while data? s))) (splitter delimiter (rest s))))))) (defn split-at-subsequence "Splits s at instances of sub" [sub s] (let [delimiter (Object.)] (splitter delimiter (replace-subsequence sub delimiter s))) --- snip --- I'd also like to thank all the people in #clojure who discussed this problem with me and in particular TimMc for his valuable remarks and help. Due to me being quite new to Clojure I would appreciate any feedback on the code above and wonder if something like this should be part of the standard library. -- Wolodja <babi...@gmail.com> 4096R/CAF14EFC 081C B7CD FF04 2BA9 94EA 36B2 8B7F 7D30 CAF1 4EFC
signature.asc
Description: Digital signature