On May 30, 7:56 pm, Ken Wesson <kwess...@gmail.com> wrote: > On Mon, May 30, 2011 at 6:15 PM, iz bash <killernemesisbl...@gmail.com> wrote: > > so clojures like my first programming language. most of the time > > now ,i use map /reduce/.. with lazy sequences but sometimes i just > > cant seem to find a solution other than using loop-recur. then i read > > somewhere almost all loop recur situations can be translated into > > reduce. so ive posted a function below...how'd you implement it using > > only higher order functions? > > > (defn rem-dup [stri] > > (loop [[x y & z] (seq stri) ,bui []] > > (cond (nil? x) bui > > (= x y \space) (recur (cons y z) bui) > > :else (recur (cons y z) (conj bui x))))) > > Any loop/recur can be trivially turned into a use of iterate: > > (defn rem-dup-iter [stri] > (first > (first > (drop-while (comp nil? first) > (iterate > (fn [[_ [x y & z] bui]] > (cond > (nil? x) [bui nil nil] > (= x y \space) [nil (cons y z) bui] > :else [nil (cons y z) (conj bui x)])) > [nil (seq stri) []]))))) > > but I'm guessing you want more. Loops that grow a collection and add > to it can generally be turned into map, for, or reduce expression. > > Here's your loop as a map call: > > (defn rem-dup-map [stri] > (let [stri (seq (concat stri [(char 0)]))] > (filter identity > (map > (fn [x y] > (if-not (= x y \space) x)) > stri > (next stri))))) > > It relies, in its use of "filter identity", on strings never > containing nil as a character. In other circumstances you might need > to use a dedicated sentinel value guaranteed to be unique, e.g. (let > [sentinel (Object.)] (remove #{sentinel} (map ... (if ... foo > sentinel)))). It also appends a NUL to the end of the string because > otherwise the map will stop one character short of the end. > > As a for loop: > > (defn rem-dup-for [stri] > (for [[x y] (partition 2 1 [] stri) > :when (not= x y \space)] > x)) > > Short and sweet! > > As a reduce: > > (defn rem-dup-reduce [stri] > (reduce > (fn [bui [x y]] > (if (= x y \space) bui (conj bui x))) > [] > (partition 2 1 [] stri))) > > Last, but not least, if none of the above seem to be workable and you > want it to be lazy (the iterate, map, and for versions above are lazy, > while the loop and reduce versions are not), you might resort to > direct use of the lazy-seq macro: > > (defn rem-dup-lazy-seq [stri] > (lazy-seq > (let [[x y & z] stri] > (if x > (if (= x y \space) > (rem-dup-lazy-seq (cons y z)) > (cons x (rem-dup-lazy-seq (cons y z))))))))
(filter identity (map f xs)) is more clearly written as (keep f xs), unless you're relying on the former to retain false (not nil) elements. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en