Thanks Mike - So I was doing a little more digging on this and came across an interesting blog posting:
http://formpluslogic.blogspot.com/2009/07/clojure-lazy-seq-and-recursion.html discussing the use of recursion vs lazy sequences. To mimic Brent from his posting I created 2 fn's: (defn date-seq [d1 d2] (let [start (-> d1 (.dayOfMonth) (.withMinimumValue))] (cons start (if (joda/before? start d2) (date-seq (.plusMonths start 1) d2))))) (defn lazy-date-seq [d1 d2] (let [start (-> d1 (.dayOfMonth) (.withMinimumValue))] (lazy-seq (cons start (if (joda/before? start d2) (lazy-date-seq (.plusMonths start 1) d2)))))) The lazy version worked like a champ and appears (to me) to be more in the vain of Lisp (with a touch of Haskell). Is the author of the blog correct about using lazy seq in this way? Assuming that he is correct and I converted date-seq to a loop/recur format to use TCO, would one of these be preferable over the other in terms of idiomatic clojure? Thanks Bassel On May 17, 5:27 pm, Mike Meyer <mwm-keyword-googlegroups. 620...@mired.org> wrote: > On Mon, 17 May 2010 14:36:23 -0700 (PDT) > > Base <basselh...@gmail.com> wrote: > > Hi All - > > > I am trying convert a function to use loop/recur and am getting the > > dreded > > > "java.lang.UnsupportedOperationException: Can only recur from tail > > position (repl-1:414)" error > > > (at least dreded for newbies...) > > The "tail" position means it's the last call at the top level of the > loop. I.e. - you can't call anything after the recur. In your case > > > > > The function takes 2 joda dates and returns a sequence of dates > > starting at the first of the month until it is past the second date. > > This works using standard recursion but I wanted to use TCO. > > > Any help is most appreciated (as usual...!) > > > Thanks > > > Base > > > (def date-seq > > (fn [d1 d2] > > (loop [b (-> d1 > > (.dayOfMonth) > > (.withMinimumValue)) > > e d2] > > (cons b (if (time/before? b e) > > (recur (.plusMonths b 1) e)))))) > > In this case, you're calling cons with the result of the recur, which > means it happens "after" the recur, which is the error. > > I suspect your original wasn't tail recursive, since the two loop > arguments are two dates (assuming my guesses about time/before? are > correct), and the values in the list you returns would be stored on > the call stack, to be pasted together by the string of conses you've > left to run after each recursive call. > > To make it tail recursive, you need to make the list you're going to > return one of the arguments of the loop, adjust the code for that, > then push the cons into the if, sort of like so: > > (defn date-seq > [d1 d2] > (loop [b (-> d1 > (.dayOfMonth) > (.withMinimumValue)) > e [d2]] > (if (time/before? b (first e)) > (recur (.plusMonths b 1) (conj e b)) > (reverse b)))) > > This is just a swag; I'm not familiar enough with Java to reconstruct > your arguments... > > <mike > -- > Mike Meyer <m...@mired.org> http://www.mired.org/consulting.html > Independent Network/Unix/Perforce consultant, email for more information. > > O< ascii ribbon campaign - stop html mail -www.asciiribbon.org > > -- > 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 > athttp://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