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

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

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

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

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

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