First experience with Clojure

7 February 2010 01:22

This weekend I played with Clojure for the first time. There's no doubt it's pretty cool. I did a little bit of work with LISP before, and I do believe Clojure fixes a lot of the warts, as well as enabling use of all the Java libraries. And that's not mentioning the concurrency stuff which was the primary reason for Clojure's development.

For now, here's what I've written. I expect this code to get improved a lot, but so far it just fetches stock prices from Yahoo and maps the result into the correct data types.

(import '(java.net URL)
        '(java.lang StringBuilder)
        '(java.io BufferedReader InputStreamReader)
        '(java.util.regex Pattern)
        '(java.util Date)
        '(java.text SimpleDateFormat))

(defn fetch-url
  [address]
  (let [url (URL. address)]
       (java.io.BufferedReader. (InputStreamReader. (. url (openStream))))))

(defn yahoo-data-url
  [code from-year]
  (str "http://ichart.finance.yahoo.com/table.csv?s="
       code "&a=00&b=01&c=" from-year "&d=01&e=6&f=2010&g=d&ignore=.csv")))

(defn split ([#^Pattern re #^String s] (seq (.split re s))))

(defn str-to-date [date] (. (SimpleDateFormat. "yyyy-MM-dd") parse date))
(defn toint [s] (Integer. s))
(defn tofloat [s] (Float. s))

(defn map-values
  [line]
  (for [i (map vector [str-to-date tofloat tofloat tofloat tofloat toint tofloat] line)]
               (apply (first i) (rest i))))

(defn map-line [s] (map-values (split #"," s)))

(map map-line (rest (line-seq (fetch-url (yahoo-data-url "GOOG" 2000)))))

I can't believe how much I love syntax highlighting.

Comments

Graham wrote on 8 February 2010:

For some reason it's really hard to find out how to get a stacktrace. That could be because they're never useful. Anyway, here's a way (*e is the previous exception):

(.printStackTrace (.getCause *e))

I've been trying to simplify the map-values function above. It should be possible with just map, apply and eval, but I can't make it work, basically because of this behaviour:

user=> (defn plus [& args] (apply + args))
#'user/plus
user=> (eval (list + 1))
1
user=> (eval (list plus 1))
java.lang.ExceptionInInitializerError (NO_SOURCE_FILE:32)

Leave a comment