Re: using reduce instead of loop recur

2011-06-01 Thread Jonathan Fischer Friberg
Maybe not what you're looking for, but this is my take on this particular
problem:

(defn rem-dup [str]
   (-
  str
  (partition-by (partial = \space))
  (map #(if (= (first %) \space) \space %))
  flatten))

I find partition-by the 'weapon of choice' when a sequence contains values
that needs to be distinguished from the rest (such as spaces). This makes
the code pretty simple to understand. The partition-by statement clearly
says that spaces should be in one group, and the rest should be in another
group.

Jonathan

On Tue, May 31, 2011 at 12:15 AM, iz bash killernemesisbl...@gmail.comwrote:

 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)


 (rem-dup   bb cc)  =[\a \a \a \a \space \b
 \b \space \c \c]

 also itd be great if you guys could give some pointers on using higher
 order functions and lazy sequences in place of a loop recur.

 Thanks!!
 and btw clojures totally awesome :)

 --
 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

-- 
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

Re: using reduce instead of loop recur

2011-05-31 Thread George Bennett
On May 30, 6:15 pm, iz bash killernemesisbl...@gmail.com wrote:
 how'd you implement it using only higher order functions?
 (rem-dup                   bb cc)  =    [\a \a \a \a \space \b \b 
 \space \c \c]

(defn rem-dup [stri]
  (- stri
(partition-all 2 1)
(filter (partial apply not= \space))
(map first)
vec))

For a lazy version, remove vec to leave it as a lazy list.
Vectors are fully-realized, so no laziness.

 also itd be great if you guys could give some pointers on using higher
 order functions and lazy sequences in place of a loop recur.

I'm fond of the - macro - it encourages thinking in terms of
transformation of a data flow.  When it is suitable, the result is
also often pleasingly terse.

-- 
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


Re: using reduce instead of loop recur

2011-05-31 Thread Stuart Campbell
For this particular case, you could also use regexps:

user (require '[clojure.string :as s])
nil
user (s/replace   bb cc # +  )
 bb cc

Regards,
Stuart

On 31 May 2011 08:15, 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)


 (rem-dup   bb cc)  =[\a \a \a \a \space \b
 \b \space \c \c]

 also itd be great if you guys could give some pointers on using higher
 order functions and lazy sequences in place of a loop recur.

 Thanks!!
 and btw clojures totally awesome :)

 --
 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

-- 
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

Re: using reduce instead of loop recur

2011-05-31 Thread iz bash

thanks everyone!! that was really great help.

-- 
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


Re: using reduce instead of loop recur

2011-05-31 Thread Ken Wesson
On Tue, May 31, 2011 at 3:45 PM, iz bash killernemesisbl...@gmail.com wrote:

 thanks everyone!! that was really great help.

You're welcome.

Hopefully, reading and understanding the code posted here (not just
mine) will both get you a better grasp of the various ways these kinds
of things can be tackled using HOFs like map and reduce, but also help
you spot occasions when you can use some of the less well known
functions and techniques. (I had (partition 2 1 [] ...) as well as
(map foo bar (rest bar)) to go over pairs of successive items from a
seq; later I had mapcat for building a seq out of larger pieces;
Malloy had keep to combine map and remove nil?; Bennett had
partition-all and -; and Campbell had regexps. I'm not sure I've
previously seen (defn foo [bar] (lazy-seq (if ... (into (foo (next
bar) [some items]) used to construct a general lazy seq in chunks
before.

-- 
Protege: What is this seething mass of parentheses?!
Master: Your father's Lisp REPL. This is the language of a true
hacker. Not as clumsy or random as C++; a language for a more
civilized age.

-- 
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


using reduce instead of loop recur

2011-05-30 Thread iz bash
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)


(rem-dup   bb cc)  =[\a \a \a \a \space \b
\b \space \c \c]

also itd be great if you guys could give some pointers on using higher
order functions and lazy sequences in place of a loop recur.

Thanks!!
and btw clojures totally awesome :)

-- 
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


Re: using reduce instead of loop recur

2011-05-30 Thread Ken Wesson
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

-- 
Protege: What is this seething mass of parentheses?!
Master: Your father's Lisp REPL. This is the language of a true
hacker. Not as clumsy or random as C++; a language for a more
civilized age.

-- 
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


Re: using reduce instead of loop recur

2011-05-30 Thread Alan Malloy
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


Re: using reduce instead of loop recur

2011-05-30 Thread Ken Wesson
On Mon, May 30, 2011 at 11:29 PM, Alan Malloy a...@malloys.org wrote:
 (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.

Eh -- filter identity doesn't retain false:

= (filter identity [false nil 42 foo []])
(42 foo [])

On the other hand, keep does. So it looks like you got that backward.
When the elements are all characters extracted from a string, though,
it's moot since neither false nor nil will appear in the input seq.

Furthermore, the OP asked for implementation in terms of the basic
HOFs, of which map is a particularly common one. Additionally, in many
cases filtering on another object, such as an explicit sentinel, would
be necessary and keep would be useless; and in still more cases there
may be no filtering needed at all, if there's something in the output
for every input. Lastly, filter, identity, and map are all quite
familiar and common compared to keep.

One situation not discussed yet in this thread is the case where one
may wish to append a varying amount of material to a sequence on each
iteration, beyond just zero items or one to sometimes two or more. In
that case:

* The loop version needs (into bui [some elements])
* So do the reduce and iterate versions.
* The for version would need to produce seqable values
  and be wrapped in (apply concat ...).
* The map version becomes mapcat and produces
  seqable values.
* The explicit lazy-seq version can also use into,
  but it looks a little strange because the recursive
  call comes *before* the step-generated elements.

These can be demonstrated on the OP's problem, though, using empty or
one-element vectors in composing the result:

(defn rem-dup [stri]
  (loop [[x y  z] (seq stri) ,bui []]
(if x
  (recur
(cons y z)
(into bui (if (= x y \space) [] [x])))
  bui)))

(defn rem-dup-iter [stri]
  (first
(first
  (drop-while (comp nil? first)
(iterate
  (fn [[_ [x y  z] bui]]
(if x
  [nil (cons y z) (into bui (if (= x y \space) [] [x]))]
  [bui nil nil]))
  [nil (seq stri) []])

(defn rem-dup-mapcat [stri]
  (let [stri (seq (concat stri [(char 0)]))]
(mapcat
  (fn [x y]
(if (= x y \space) [] [x]))
  stri
  (next stri

(defn rem-dup-for [stri]
  (apply concat
(for [[x y] (partition 2 1 [] stri)]
  (if (= x y \space) [] [x]

(defn rem-dup-reduce [stri]
  (reduce
(fn [bui [x y]]
  (into bui
(if (= x y \space) [] [x])))
[]
(partition 2 1 [] stri)))

(defn rem-dup-lazy-seq [stri]
  (lazy-seq
(let [[x y  z] stri]
  (if x
(into
  (rem-dup-lazy-seq (cons y z))
  (if (= x y \space) [] [x]))

All of the above versions can be generalized to add arbitrary subseqs
on each iteration, conditionally. Every one of them has an (if ... []
[x]) clause somewhere. If you change the [] in that clause to, say,
XX, it will replace every space in a run of spaces except the last
with a pair of Xs:

(defn rem-dup-mapcat-xs [stri]
  (let [stri (seq (concat stri [(char 0)]))]
(mapcat
  (fn [x y]
(if (= x y \space) XX [x]))
  stri
  (next stri

= (rem-dup-mapcat-xs   bb cc)
(\a \a \a \a \X \X \X \X \X \X \X \X \X \X \X \X \X \X \X \X \X \X \X
\X \X \X \X \X \X \X \X \X \X \X \X \X \X \X \space \b \b \space \c
\c)
= (count (filter #{\X} (rem-dup-mapcat-xs   bb cc)))
34

Note that there are 18 spaces between the as and the bs in the
input, and the output has 34 \X characters followed by a space there
-- the 17 spaces before the last were each replaced with a pair of \X
characters.

-- 
Protege: What is this seething mass of parentheses?!
Master: Your father's Lisp REPL. This is the language of a true
hacker. Not as clumsy or random as C++; a language for a more
civilized age.

-- 
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