--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@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+u...@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 unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
In regards to your question "Why isn't this documented anywhere?", it is documented somewhere -- in the documentation string for clojure.edn/read, the very function you were attempting to use:
user=> (doc clojure.edn/read)
-------------------------
clojure.edn/read
([] [stream] [opts stream])
Reads the next object from stream, which must be an instance of
java.io.PushbackReader or some derivee. stream defaults to the
current value of *in*.
As far as why it requires a PushbackReader, I didn't design the API. Yes, some things in Clojure require using Java interop, and in many (but not all) cases, file I/O requires it.
On Monday, December 8, 2014 2:26:42 AM UTC-5, Andy Fingerhut wrote:In regards to your question "Why isn't this documented anywhere?", it is documented somewhere -- in the documentation string for clojure.edn/read, the very function you were attempting to use:
user=> (doc clojure.edn/read)
-------------------------
clojure.edn/read
([] [stream] [opts stream])
Reads the next object from stream, which must be an instance of
java.io.PushbackReader or some derivee. stream defaults to the
current value of *in*.
What's *not* documented is that io/reader doesn't output something that edn/read can use directly, nor is there documented an officially recommended workaround for this.
AFAICT just wrapping the reader output in "(java.io.PushbackReader. ...)" works.
Still, this is awkward, verbose, and prevents the (nontrivial) use of edn in a platform-neutral way by referring only to Clojure functions without direct interop. Well, except for the even more awkward workaround of slurp and read-string, with the accompanying need to hold the entire file in memory *twice* for a short time.
As far as why it requires a PushbackReader, I didn't design the API. Yes, some things in Clojure require using Java interop, and in many (but not all) cases, file I/O requires it.
Perhaps io/reader should output a PushbackReader, if only for convenience's sake.
Also, how does this work on ClojureCLR or ClojureScript? Neither of those platforms has a java.io.PushbackReader, and I'm not even sure what the equivalent of the clojure.java.io namespace is for them, unless the "java" in that name is misleading.
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@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+u...@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 unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Still, this is awkward, verbose, and prevents the (nontrivial) use of edn in a platform-neutral way by referring only to Clojure functions without direct interop. Well, except for the even more awkward workaround of slurp and read-string, with the accompanying need to hold the entire file in memory *twice* for a short time.As far as why it requires a PushbackReader, I didn't design the API. Yes, some things in Clojure require using Java interop, and in many (but not all) cases, file I/O requires it.
Perhaps io/reader should output a PushbackReader, if only for convenience's sake.io/reader is not meant to be used solely as an input to edn/read.
On 8 December 2014 at 21:17, Fluid Dynamics <a209...@trbvm.com> wrote:
> On Monday, December 8, 2014 9:32:28 AM UTC-5, Las wrote:
>> […]
>> io/reader is not meant to be used solely as an input to edn/read.
>
>
> AFAICT, PushbackReader is substitutable anywhere a reader is expected, but
> apparently a plain unwrapped BufferedReader is not.
user=> (line-seq (java.io.PushbackReader. (io/reader (io/file ".bashrc"))))
ClassCastException java.io.PushbackReader cannot be cast to
java.io.BufferedReader clojure.core/line-seq (core.clj:2955)
It works with the plain unwrapped BufferedReader that io/reader returns.
Unfortunately PushbackReader and BufferedReader are both classes
rather than interfaces and they both have methods that the other class
does not. So, there isn't a single good choice for what a "reader"
function in Clojure on the JVM should return.
--
As the original author of the function that eventually became clojure.java.io/reader, it was one of those unfortunate decisions that seemed like a good idea at the time and cannot be changed without breaking backwards compatibility.
Long before EDN existed, I wrote clojure.contrib.io https://github.com/clojure/clojure-contrib/blob/1.2.x/src/main/clojure/clojure/contrib/io.clj
This included a function `reader` that returned a java.io.BufferedReader: http://docs.oracle.com/javase/7/docs/api/java/io/BufferedReader.html
BufferedReader was a convenient type to return because it supports .readLine, which is used by clojure.core/line-seq: https://github.com/clojure/clojure/blob/1.1.x/src/clj/clojure/core.clj#L1954-L1960
However, clojure.core/read and later clojure.edn/read were written in terms of java.io.PushbackReader, because they need the ability to look ahead one character in the stream while parsing it:
http://docs.oracle.com/javase/7/docs/api/java/io/PushbackReader.html
It turns out there are some subtle issues which can cause incorrect behavior were clojure.core/read to blindly wrap a PushbackReader around its argument:
https://groups.google.com/d/msg/clojure/_tuypjr2M_A/W1EcEbMUg_cJ
How many programmers does it take to change a light bulb?!
http://dev.clojure.org/jira/browse/CLJ-1611
Also, how does this work on ClojureCLR or ClojureScript? Neither of those platforms has a java.io.PushbackReader, and I'm not even sure what the equivalent of the clojure.java.io namespace is for them, unless the "java" in that name is misleading.
It turns out there are some subtle issues which can cause incorrect behavior were clojure.core/read to blindly wrap a PushbackReader around its argument:
https://groups.google.com/d/msg/clojure/_tuypjr2M_A/W1EcEbMUg_cJ
That sounds like magic. The user wrapping a PushbackReader around a BufferedReader doesn't cause problems, but the library function doing so does? Why would where the wrapping takes place make a difference? Is the *only* problem the rare case of reading more than one object from the same stream? A docstring warning to wrap manually *in those cases* would suffice, then, no?