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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en