On Jun 7, 6:37 am, toddg <t.greenwoodg...@gmail.com> wrote:
> I'm attempting to read and understand core.clj, and I'm walking
> through methods as I run into them, trying to understand them, line by
> line. I' mostly understand read-lines (w/ the exception of the last
> line), but I do not follow lazy-seq or if-let. Could someone check my
> deconstruction of read-lines and make sure I'm getting this right?
>
> -Todd
>
> 1. read-lines

This is from clojure.contrib.duck-streams, right?

> (defn read-lines
>   "Like clojure.core/line-seq but opens f with reader.  Automatically
>   closes the reader AFTER YOU CONSUME THE ENTIRE SEQUENCE."
>   [f]
>   (let [read-line (fn this [#^BufferedReader rdr]
>                     (lazy-seq
>                      (if-let [line (.readLine rdr)]
>                        (cons line (this rdr))
>                        (.close rdr))))]
>     (read-line (reader f))))
>
> 1.1 define a function, named 'read-lines', that takes a single
> parameter, 'f'
>
> (defn read-lines [f]
>
> 1.2 create a scoped variable, 'read-line', and assign a function to it
>
>   (let [read-line (fn this [#^BufferedReader rdr]
>
> 1.3 the function is called 'this', and it takes a
> BufferedReader...note the compiler hint telling that this is a
> 'BufferedReader' (that's what the #^ is doing)
>
> 1.4 create a lazy sequence
>
>     (lazy-seq
>
> Q: what is a lazy-seq?

A lazy-seq makes a seq that's backed by functions instead of a "plain"
data structure.

the main advantage of lazy seqs is that they can present a normal
"seq" interface over data that's hard or slow to realize as a pure
list (like infinite or huge lists or disk-based data). especially when
it's expected not all of the seq is actually relevant to the "user".

> 1.5  let line equal the result of rdr.readLine
>
>     (if-let [line (.readLine rdr)]
>
> 1.6 if line is true, then insert this line at the head of a sequence
>
>     (cons line (this rdr)
>
> 1.7 if line was false, then close the reader
>
>     (.close rdr))))]
>
> 1.8 invoke the locally defined read-line function on... Q: what does
> (reader f) mean? What is 'reader'?

the reader function is defined elsewhere in duck-streams. It converts
a number of possible types into a BufferedReader.

>     (read-line (reader f))))
>
> 2. lazy-seq
>
> (defmacro lazy-seq
>   "Takes a body of expressions that returns an ISeq or nil, and yields
>   a Seqable object that will invoke the body only the first time seq
>   is called, and will cache the result and return it on all subsequent
>   seq calls."
>   {:added "1.0"}
>   [& body]
>   (list 'new 'clojure.lang.LazySeq (list* '^{:once true} fn* []
> body)))

This is mostly just a call to the constructor of clojure.lang.LazySeq
that encaptulates the expressions provided in a function. In other
words, most of the interesting stuff is in the java code.

> 3. if-let
>
> (defmacro if-let
>   "bindings => binding-form test
>
>   If test is true, evaluates then with binding-form bound to the value
> of
>   test, if not, yields else"
>   {:added "1.0"}
>   ([bindings then]
>    `(if-let ~bindings ~then nil))
>   ([bindings then else & oldform]
>    (assert-args if-let
>      (and (vector? bindings) (nil? oldform)) "a vector for its
> binding"
>      (= 2 (count bindings)) "exactly 2 forms in binding vector")
>    (let [form (bindings 0) tst (bindings 1)]
>      `(let [temp# ~tst]
>         (if temp#
>           (let [~form temp#]
>             ~then)
>           ~else)))))

Disregarding the argument checking and edge cases and the details of
prevention of multiple evaluation, the code first stores the result of
the test expression, then tests if it's true, if so: store the result
under the given binding and evaluate the then-expression. otherwise,
evaluate the else-expression.

You may want to read up on macros in clojure.

Joost.

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

Reply via email to