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