See the source of clojure.contrib.duck-streams/read-lines http://clojuredocs.org/clojure_contrib/clojure.contrib.duck-streams/read-lines
For the second question: Use read-lines directly. If you want a lazy-seq that doesn't close the stream when it's empty, ; untested (defn take-bytes [rdr] (lazy-seq (cons (.take rdr) (take-bytes rdr)))) which will produce an "infinite" sequence. Jonathan On Thu, May 19, 2011 at 11:50 AM, timc <timgcl...@gmail.com> wrote: > Hello > I wonder if I could ask for advice on how to construct a lazy sequence. My > application might be of interest to some of you. > > The context for this is that I have an embedded system with very limited > facilities for proper debugging. > I have inserted a 'trace' facility in the embedded code that is able to > emit binary bytes that I can capture over a serial comm channel. > So, what I get is a stream of bytes that is a sort of mini-language. > > For example, I might get the values as in this seq: > > (def bSeq [1 20 30 4 1 7 8 5 60 5 70]) > > where the 'sentences' of this language are as follows: > > 1 a b (that is, a 1 is followed by two values), > 4 (that is, a 4 is on its own) > 5 x (that is, a 5 is followed by one value), and so on. > > Now, examining this stream of values is tedious to say the least, so I want > to parse it and print meaningful versions of the sentences (after all, I > know what they really mean :). > So, I construct a set of specifications for the sentences, like this: > > (defstruct Spec :nArgs :fmt) > > (def specs { > 1 (struct Spec 2 "[1] a=%d b=%d\n") > 4 (struct Spec 0 "[4]\n") > 5 (struct Spec 1 "[5] z=%d\n") > }) > > The map of Specs is keyed by the value that starts the sentence. > The Spec itself comprises :nArgs (how many values follow) > and :fmt (a string for the format function, expecting :nArgs values, which > will render the sentence in a useful way). > > I want to do the parsing of the byte sequence as follows, using the magic > of reduce: > > (reduce parser {} bSeq) > > where the parser function is this: > > (defn parser [m a] > (if (empty? m) > (if-let [spec (specs a)] > (if (zero? (spec :nArgs)) > (do > (print (format (spec :fmt))) > {}) > {:spec spec :args []}) > (throw (Error. (format "Input %d has no format spec" a)))) > (let [newArgs (conj (m :args) a)] > (if (= ((m :spec) :nArgs) (count newArgs)) > (do > (print (apply format ((m :spec) :fmt) newArgs)) > {}) > (assoc m :args newArgs))))) > > To explain a bit: the args to parser are m, a map with keys: > :spec -- the spec of the sentence that is currently being parsed > :args -- a vector of the args to this sentence > or the empty map if the next thing expected is the start value of a > sentence; > and a the next value in the sequence. > > Lo and behold, this produces formatted output like this: > > [1] a=20 b=30 > [4] > [1] a=7 b=8 > [5] z=60 > [5] z=70 > > So far so good, but here comes the real question of this post. > The data arrives from the serial port in variable sized byte arrays at > unpredictable moments in time; these are placed in a queue, like this: > > (def inputQ (java.util.concurrent.LinkedBlockingQueue.)) > (defn inputArrives [byteArray] (.put inputQ byteArray)) > > It is of course very easy to read the things out of the queue by means of > (.take inputQ), and then read the bytes one-by-one; of course this may block > waiting for more inputs. > > So - how do I make a function that returns a lazy sequence that internally > is getting the byte arrays off this queue and feeding the bytes contained > therein to the caller of the lazy sequence - one byte at a time? > > And - a similar question (easier to answer I imagine) how do I construct a > lazy sequence from the bytes read from a file (possibly with some > translation between reading the raw bytes from the file and handing them > over to the caller of the lazy sequence)? > > Of course, I could (and have) implemented all the above in a much more > procedural kind of way, but it is so much more elegant (and easier to > understand) with a lazy sequence :) > > Looking forward to some remarkable, simple solutions :) > > Regards, Tim > > PS Thinking about this makes me wonder about the existence, or > non-existence of a 'super-reduce' function that could do context-free > grammar parsing. > Is such a thing possible? Is there-such a thing as a lazy back-trackable > sequence? Now that I've asked - I'm not even sure what that means :)) > > -- > 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