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

Reply via email to