Re: every-nth

2010-11-25 Thread Sunil S Nandihalli
Thanks Meikel for such an insightfull feedback. Its hard to imagine so much
thought goes into writing trivial looking functions.
Sunil.

On Thu, Nov 25, 2010 at 1:00 PM, Meikel Brandmeyer m...@kotka.de wrote:

 Hi,

 On 25 Nov., 05:06, Sunil S Nandihalli sunil.nandiha...@gmail.com
 wrote:

  (defn every-nth [n coll]
(letfn [(evn [cn s]
  (when s
(if (= cn 1)
  (lazy-seq (cons (first s) (evn n (next s
  (evn (dec cn) (next s)]
  (evn n coll)))

 Since you want to learn how lazy-seq works here some feedback.

 * Make the lazy-seq the outer-most part of your function
  to allow as much laziness as possible. There other
  opinions out there about the placement of lazy-seq, but
  there are also a lot of people complaining about eg. a
  filter doing an expensive predicate call because the
  input sequence is not as lazy as it could be. By placing
  lazy-seq outermost you leave the decision to them when
  to realize an element.

 * You should call seq on coll before passing it to evn.
  Think of [] as input. It will be truthy in the when check
  and we do some unnecessary loop, where we actually could
  short circuit.

 * Don't call next in the true branch of the if. It realises
  an element of the input sequence where it is not
  necessary. Use rest.

 * Don't call evn in the false branch of the if. It will be
  true recursion and might blow the stack for large n. You
  Use recur.

 Here is the version I would write in this case.

 (defn every-nth
  [n coll]
   (let [step (fn step [s]
   (lazy-seq
 (loop [s   (seq s)
cnt n]
   (when s
 (if (= cnt 1)
   (cons (first s) (step (rest s)))
   (recur (next s) (dec cnt)))]
(step coll)))

 * lazy-seq is outer-most.
 * The recur is turned into a loop to avoid stacking lazy-seq
  on lazy-seq.
 * The input sequence is only realised inside the lazy-seq.
  Also in the true branch we use rest to defer realisation
  of the next seq step. In the false branch we use next,
  because we need the value anyway.

 As a rule of thumb: write your generating function with
 normal recursion first. Then simply wrap a lazy-seq
 around it.

 Hope that helps.

 Sincerely
 Meikel

 --
 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.comclojure%2bunsubscr...@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: every-nth

2010-11-25 Thread Meikel Brandmeyer
Hi,

On 25 Nov., 09:40, Sunil S Nandihalli sunil.nandiha...@gmail.com
wrote:

 Thanks Meikel for such an insightful feedback. Its hard to imagine so much
 thought goes into writing trivial looking functions.

There are several interpretations of the word trivial. One is easy
or simple (where one could dispute whether simple is always
easy). Another one is the mathematical trivial. When a
mathematician says, that something is trivial, this does not mean,
that this something is easy. But simply well understood. The
understanding itself is maybe a PhD, but was already done by someone.

Here it is basically the same: this issues re-occur every time you
power-up lazy-seq. Then you have to understand the implications once.
From this you derive some rules which let you operate in auto-pilot
mode when working on a similar problems in the future.

The catalogue of rules you end up with is then called best
practices. Best practices are frowned upon. But this is stupid. It
means one repeats the same mistakes again and again, which others did
before.

So - as a beginner - follow best practises. If you deviate, give a
good reason for the deviation. But understand the practises as you
dive in further into the language. Why are they the way they are? Are
they maybe obsolete? c.

The art is to turn off the autopilot, before crashing into the
cliff. :)

Oh! And no one claimed that things are easy. ;)

Sincerely
Meikel

PS: This is also true for other fields. Take for example Joseki in Go
(the game, not the prog. language). Joseki are sequences of moves
developed by professional players over years. Deviating from such a
sequence is likely to be punished in some way. So you should know what
you are doing. Nevertheless Joseki are always refined, obsoleted,
modified as time advances and play styles change.

Best practises and Joseki are tools. Use them well, and they will
serve you. Use them blindly, and they will cut off your foot.

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


every-nth

2010-11-24 Thread Sunil S Nandihalli
Hello everybody,
 I just needed a function for every-nth element in a sequence.. I know it
can be trivially implemented as ..

(defn every-nth [n coll]
  (letfn [(evn [cn s]
(when s
  (if (= cn 1)
(lazy-seq (cons (first s) (evn n (next s
(evn (dec cn) (next s)]
(evn n coll)))

But I remember seeing inbuilt function .. can anybody help me find it?
Sunil.

-- 
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: every-nth

2010-11-24 Thread Baishampayan Ghose
  I just needed a function for every-nth element in a sequence.. I know it
 can be trivially implemented as ..
 (defn every-nth [n coll]
   (letfn [(evn [cn s]
             (when s
               (if (= cn 1)
                 (lazy-seq (cons (first s) (evn n (next s
                 (evn (dec cn) (next s)]
     (evn n coll)))
 But I remember seeing inbuilt function .. can anybody help me find it?

take-nth should do the job -
http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/take-nth

Regards,
BG

-- 
Baishampayan Ghose
b.ghose at gmail.com

-- 
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: every-nth

2010-11-24 Thread Ken Wesson
On Wed, Nov 24, 2010 at 11:11 PM, Baishampayan Ghose b.gh...@gmail.com wrote:
  I just needed a function for every-nth element in a sequence.. I know it
 can be trivially implemented as ..
 (defn every-nth [n coll]
   (letfn [(evn [cn s]
             (when s
               (if (= cn 1)
                 (lazy-seq (cons (first s) (evn n (next s
                 (evn (dec cn) (next s)]
     (evn n coll)))
 But I remember seeing inbuilt function .. can anybody help me find it?

 take-nth should do the job -
 http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/take-nth

And it can be even more trivially implemented as (map first (partition
n coll)). :)

-- 
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: every-nth

2010-11-24 Thread David Sletten

On Nov 24, 2010, at 11:45 PM, Ken Wesson wrote:

 On Wed, Nov 24, 2010 at 11:11 PM, Baishampayan Ghose b.gh...@gmail.com 
 wrote:
  I just needed a function for every-nth element in a sequence.. I know it
 can be trivially implemented as ..
 (defn every-nth [n coll]
   (letfn [(evn [cn s]
 (when s
   (if (= cn 1)
 (lazy-seq (cons (first s) (evn n (next s
 (evn (dec cn) (next s)]
 (evn n coll)))
 But I remember seeing inbuilt function .. can anybody help me find it?
 
 take-nth should do the job -
 http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/take-nth
 
 And it can be even more trivially implemented as (map first (partition
 n coll)). :)
 

(map first (partition 1 n coll))


 -- 
 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: every-nth

2010-11-24 Thread Ken Wesson
On Wed, Nov 24, 2010 at 11:53 PM, David Sletten da...@bosatsu.net wrote:

 On Nov 24, 2010, at 11:45 PM, Ken Wesson wrote:

 On Wed, Nov 24, 2010 at 11:11 PM, Baishampayan Ghose b.gh...@gmail.com 
 wrote:
  I just needed a function for every-nth element in a sequence.. I know it
 can be trivially implemented as ..
 (defn every-nth [n coll]
   (letfn [(evn [cn s]
             (when s
               (if (= cn 1)
                 (lazy-seq (cons (first s) (evn n (next s
                 (evn (dec cn) (next s)]
     (evn n coll)))
 But I remember seeing inbuilt function .. can anybody help me find it?

 take-nth should do the job -
 http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/take-nth

 And it can be even more trivially implemented as (map first (partition
 n coll)). :)

 (map first (partition 1 n coll))

Yes, that seems to work too, but it's also two characters longer. :)

-- 
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: every-nth

2010-11-24 Thread David Sletten
I stand corrected. I thought it required another arg. Yours was right already.

On Nov 24, 2010, at 11:53 PM, David Sletten wrote:

 
 On Nov 24, 2010, at 11:45 PM, Ken Wesson wrote:
 
 On Wed, Nov 24, 2010 at 11:11 PM, Baishampayan Ghose b.gh...@gmail.com 
 wrote:
 I just needed a function for every-nth element in a sequence.. I know it
 can be trivially implemented as ..
 (defn every-nth [n coll]
  (letfn [(evn [cn s]
(when s
  (if (= cn 1)
(lazy-seq (cons (first s) (evn n (next s
(evn (dec cn) (next s)]
(evn n coll)))
 But I remember seeing inbuilt function .. can anybody help me find it?
 
 take-nth should do the job -
 http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/take-nth
 
 And it can be even more trivially implemented as (map first (partition
 n coll)). :)
 
 
 (map first (partition 1 n coll))
 
 
 -- 
 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

-- 
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: every-nth

2010-11-24 Thread Ken Wesson
Eh. This is weird. It seems that (partition n coll) drops the last
part of coll if it's not a multiple of n in size; e.g. (partition 3 [1
2 3 4 5]) yields ((1 2 3)) and not ((1 2 3) (4 5)). (partition n n []
coll) does do that though.

OTOH,

(mapcat identity (partition 1 n coll))
(apply concat (partition 1 n coll))
(keep-indexed (fn [i x] (if (= 0 (rem i n)) x)) coll)
(map first (partition-all n coll))
(mapcat identity (partition-all n coll))
(apply concat (partition-all n coll))

and the winner is:

(flatten (partition 1 n coll))

Only 30 characters. :)

-- 
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: every-nth

2010-11-24 Thread Sunil S Nandihalli
Thanks everybody,
 Clojure community is awesome .. and also I just wanted to learn to use
lazy-seq that is why it was written in the way I showed you all.

Thanks again.
Sunil.

On Thu, Nov 25, 2010 at 11:26 AM, Ken Wesson kwess...@gmail.com wrote:

 Eh. This is weird. It seems that (partition n coll) drops the last
 part of coll if it's not a multiple of n in size; e.g. (partition 3 [1
 2 3 4 5]) yields ((1 2 3)) and not ((1 2 3) (4 5)). (partition n n []
 coll) does do that though.

 OTOH,

 (mapcat identity (partition 1 n coll))
 (apply concat (partition 1 n coll))
 (keep-indexed (fn [i x] (if (= 0 (rem i n)) x)) coll)
 (map first (partition-all n coll))
 (mapcat identity (partition-all n coll))
 (apply concat (partition-all n coll))

 and the winner is:

 (flatten (partition 1 n coll))

 Only 30 characters. :)

 --
 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.comclojure%2bunsubscr...@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: every-nth

2010-11-24 Thread Stuart Campbell
On 25 November 2010 16:56, Ken Wesson kwess...@gmail.com wrote:

 Eh. This is weird. It seems that (partition n coll) drops the last
 part of coll if it's not a multiple of n in size; e.g. (partition 3 [1
 2 3 4 5]) yields ((1 2 3)) and not ((1 2 3) (4 5)). (partition n n []
 coll) does do that though.


See also partition-all:

 user= (partition-all 3 [1 2 3 4 5])
((1 2 3) (4 5))

Regards,
Stuart

-- 
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: every-nth

2010-11-24 Thread Meikel Brandmeyer
Hi,

On 25 Nov., 05:06, Sunil S Nandihalli sunil.nandiha...@gmail.com
wrote:

 (defn every-nth [n coll]
   (letfn [(evn [cn s]
             (when s
               (if (= cn 1)
                 (lazy-seq (cons (first s) (evn n (next s
                 (evn (dec cn) (next s)]
     (evn n coll)))

Since you want to learn how lazy-seq works here some feedback.

* Make the lazy-seq the outer-most part of your function
  to allow as much laziness as possible. There other
  opinions out there about the placement of lazy-seq, but
  there are also a lot of people complaining about eg. a
  filter doing an expensive predicate call because the
  input sequence is not as lazy as it could be. By placing
  lazy-seq outermost you leave the decision to them when
  to realize an element.

* You should call seq on coll before passing it to evn.
  Think of [] as input. It will be truthy in the when check
  and we do some unnecessary loop, where we actually could
  short circuit.

* Don't call next in the true branch of the if. It realises
  an element of the input sequence where it is not
  necessary. Use rest.

* Don't call evn in the false branch of the if. It will be
  true recursion and might blow the stack for large n. You
  Use recur.

Here is the version I would write in this case.

(defn every-nth
  [n coll]
  (let [step (fn step [s]
   (lazy-seq
 (loop [s   (seq s)
cnt n]
   (when s
 (if (= cnt 1)
   (cons (first s) (step (rest s)))
   (recur (next s) (dec cnt)))]
(step coll)))

* lazy-seq is outer-most.
* The recur is turned into a loop to avoid stacking lazy-seq
  on lazy-seq.
* The input sequence is only realised inside the lazy-seq.
  Also in the true branch we use rest to defer realisation
  of the next seq step. In the false branch we use next,
  because we need the value anyway.

As a rule of thumb: write your generating function with
normal recursion first. Then simply wrap a lazy-seq
around it.

Hope that helps.

Sincerely
Meikel

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