Hi, the version of repeatedly-while I submitted still takes an argument for the predicate function, that would be the value of the last generated item in the list:
(defn repeatedly-while [pred f] (take-while pred (repeatedly f))) So if you want to call it with a no-arg "predicate", you must adapt it : (repeatedly-while (fn [ _ ] (no-arg-pred)) f) instead of (repeatedly-while no-arg-pred f) (notice the underscore that emphazises the fact that we don't care about the argument). Or create a less general function that accepts only no-arg predicates: (defn repeatedly-while2 [no-arg-pred f] (take-while (fn [ _ ] (no-arg-pred) f)) (not tested) But this is a less general function ... Regards, -- Laurent 2009/5/9 Mark Reid <mark.r...@gmail.com> > > Hi Laurent, > > Thanks for the feedback. I'm still a bit stuck though since neither my > proposal nor yours work for the type of application I had in mind. > > Here's a complete program which highlights the problems: > > ; ---- Begin lazyread.clj ---- > (import '(java.io FileReader BufferedReader PrintWriter)) > > (def filename "test.data") > > ; Write out a small test file. Numbers 0 to 99, one per line. > (with-open [data (PrintWriter. filename)] > (dotimes [i 100] (.println data i))) > > ; An attempt at capturing the general idiom that doesn't work > (defn cons-while > [pred f] > (lazy-seq > (when pred > (cons f (cons-while pred f))))) > > ; Another attempt that doesn't work > (defn repeatedly-while > [pred f] > (take-while pred (repeatedly f))) > > ; A specific implementation for the problem at hand > (defn lazy-read [reader] > (lazy-seq > (when (.ready reader) > (cons (.readLine reader) (lazy-read reader))))) > > (print "lazy-read: ") > (with-open [data (BufferedReader. (FileReader. filename))] > (prn (take 10 (lazy-read data)))) > > (print "cons-while: ") > (with-open [data (BufferedReader. (FileReader. filename))] > (prn (take 10 (cons-while (.ready data) (.readLine data))))) > > (print "repeatedly-while: ") > (with-open [data (BufferedReader. (FileReader. filename))] > (prn (take 10 (repeatedly-while #(.ready data) #(.readLine data))))) > > ; ---- End lazyread.clj ---- > > Running this will write out a small test file named `test.data` in the > current directory with the numbers 0-99 one per line and then use > three techniques to lazily read in the first 10 lines. > > The first technique, `lazy-read`, is an explicit use of the `lazy-seq` > + `when` + `cons` combination I wish to generalise. The second one, > `cons-while`, is the attempt I made and the third, `repeatedly-while` > is your suggestion. > > Here's the output I get when I run this as a script from the command > line: > ---- > $ clj lazyread.clj > lazy-read: ("0" "1" "2" "3" "4" "5" "6" "7" "8" "9") > cons-while: ("0" "0" "0" "0" "0" "0" "0" "0" "0" "0") > Exception in thread "main" java.lang.RuntimeException: > java.lang.RuntimeException: java.lang.IllegalArgumentException: Wrong > number of args passed to: user$eval--38$fn (scratch.clj:0) > ---- > > Unsurprisingly, the problem-specific method seems to work fine. The > `cons-while` method returns the wrong output and the last technique > fails because of issues surrounding the macro expansion of (.ready > data) and the #(...) macro that have been discussed elsewhere. > > Is it possible to get the `repeatedly-while` version working with > calls to Java without making the calling pattern too convoluted? > > Also, can anyone explain why the `cons-while` approach only appears to > be repeatedly reading the first line? > > Finally, would a macro approach be better for this type of problem? > > Thanks, > > Mark. > -- > http://mark.reid.name > > > --~--~---------~--~----~------------~-------~--~----~ 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 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 -~----------~----~----~----~------~----~------~--~---