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

Reply via email to