Here's an idiomatic way of doing what you want;

(defn lp [col]
  (loop [ll (seq col)]
    (when ll
      (try
        (let [itm (first ll)]
          (if (= itm 'x) (throw (IllegalArgumentException.
               (str itm " not supported.")))
            (println (str "done item: " itm))))
        (catch Exception ex (println (.getMessage ex))))
      (recur (next ll))))
  (println "done loop"))

user=> (lp ['a 'b 'x 'd])
done item: a
done item: b
x not supported.
done item: d
done loop

One can use (doseq for a simple example like this, but the above
pattern is useful for doing complex things in the outer loop, eg
accumulating collections, iterating multiple reads in parallel, etc.

Here's a more complex but realistic example; Say we want to loop
through some collection, and for each item, read the next line in a
file, process it (which may throw an exception), write the result to
an output file and accumulate only the successful items in a vector
which is returned to the caller...

(defn lpx
  [col f-in f-out]
  (with-open [fin (BufferedReader. (FileReader. (File. f-in)))
              fout (PrintWriter. f-out)]
    (loop [ll (seq col) rec (.readLine fin) cum []]
      (if (and ll rec)
        (let [itm (first ll)
              cum (try
                    (if (= itm 'x) (throw (IllegalArgumentException.
(str rec " error, ignored.")))
                      (do (.println fout (str itm ":" rec))
                        (conj cum [itm rec])))
                    (catch Exception ex
                      (do (.println fout (str itm ":" (.getMessage ex))) cum)))]
          (recur (next ll) (.readLine fin) cum))
        cum))))

cat f1.txt
one
two
three
four
five

user=> (lpx ['a 'b 'c 'd] "f1.txt" "f2.txt")
[[a "one"] [b "two"] [c "three"] [d "four"]]
cat f2.txt
a:one
b:two
c:three
d:four

user=> (lpx ['a 'b 'x 'd] "f1.txt" "f2.txt")
[[a "one"] [b "two"] [d "four"]]
cat f2.txt
a:one
b:two
x:three error, ignored.
d:four

(There are functions in contrib which could also be used, but the
above illustrates reasonably core java interop, which is often
required in practice).

Just a clarification on the try/catch above - we're setting the local
cum to either the value calculated in the try or the one returned in
the catch. This is better illustrated below;

(defn xx [cum]
  (let [cum (try (if (= cum :x)
            (throw (Exception. "err"))
            cum)
            (catch Exception ex [:err (.getMessage ex)]))]
    cum))

user=> (xx :a)
:a
user=> (xx :x)
[:err "err"]

-Rgds, Adrian.

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