A lightweight `bind' macro

In my recent work I found myself writing a lot of code that looked like the following:

(destructuring-bind (x y)
    point
  (destructuring-bind (x1 y1 w h)
      frame
    (let ((x2 (+ x1 w))
          (y2 (+ y1 h)))
      (and (>= x x1) (<= x x2) (>= y y1) (<= y y2)))))

The above example is a bit contrived, for effect, but hopefully conveys the general idea.

What I wanted was a Clojure style `let' which could destructure inline. There was one Common Lisp implementation (http://common-lisp.net/project/metabang-bind/), which had some nice features, but it was bit much for my needs. So I came up with my own lightweight bind macro (see below), which lets me rewrite the above example as:

(bind (((x y) point)
       ((x1 y1 w h) frame)
       (x2 (+ x1 w))
       (y2 (+ y1 h)))
  (and (>= x x1) (<= x x2) (>= y y1) (<= y y2)))

Way better, IMHO.

Oh, here's the `bind' macro in its entirety:

(defmacro bind (clauses &body body)
  "This macro combines the behaviour of the forms `let*', `destructuring-bind',
and `multiple-value-bind', permitting the following style of binding form:
 
  (bind (((:values m n) (values 10 20))
         ((a b &key (c 10)) '(1 2))
         (x 5))
    (+ x a b c m n))
  => 48
 
This is a more limited and lightweight implementation of some ideas from
metabang-bind (http://common-lisp.net/project/metabang-bind/)."
  (cond
    ((null clauses) `(progn ,@body))
    ((and (listp (caar clauses)) (eq (caaar clauses) :values))
     `(multiple-value-bind ,(cdaar clauses)
          ,@(cdar clauses)
        (bind ,(cdr clauses) ,@body)))
    ((listp (caar clauses))
     `(destructuring-bind ,(caar clauses)
          ,@(cdar clauses)
        (bind ,(cdr clauses) ,@body)))
    (t
     `(let (,(car clauses))
        (bind ,(cdr clauses) ,@body)))))

community funded clojure

Rich Hickey posted a compelling message about funding the future development of Clojure.

I donated, and urge all Lispers to consider the same. Clojure maybe one of the best things to happen to Lisp in a long while, and it and Rich are most deserving of our continued support.

Donate at clojure.org.

ECL on iPhone (redux)

A while ago Red Daly posted about some great initial work he had done in porting ECL to the iPhone. I contacted him, and worked to clean up some of the external dependencies, and got ECL to run on the simulator and device (with SLIME). I put together an updated Git repo with all my changes, and finally got around to posting about it.

http://github.com/kriyative/ecl-iphone-builder

Hopefully, this will be of use to others.

clojure, emacs, and javadocs

In the course of my recent work, integrating various java libraries with clojure, I spent a lot of time going back and forth between emacs and firefox, just to read java api documentation. I even tried loading up the "All Classes" index from the java api docs in an emacs/w3m buffer and isearch-ing through it. It was a far from optimal experience, and I decided to hack something using clojure and slime.

Bill Clementson had posted a great intro to javadoc and clojure/slime, but I was looking for something that wouldnt' require me to leave emacs just to read documentation, and that too java api docs.

Ideally, I wanted to be able able to put the cursor on any java class symbol in a clojure-mode buffer in emacs, execute M-x slime-javadoc, and have the api documentation popup in an adjacent emacs window.

Turns out the hardest part of implementing this was in resolving an unqualified class name to its fully qualified form, before looking up its documentation path. For example,

(ns example
  (:import (java.util UUID)))

(defn uuid []  (.toString (UUID/randomUUID)))

Looking up the javadoc on UUID should really be on java.util.UUID, which clojure knows. So, the core of the hack is a clojure function, which takes the symbol at point ("UUID" in this case), and the current namespace ("example") and returns a fully qualified class name "java.util.UUID". That function, implemented as a slime command looks like the following:

(swank.commands/defslimefn resolve-symbol [sym ns-name]
  (when-let [the-class (ns-resolve (find-ns (symbol ns-name))
                                   (symbol sym))]
    (.getName the-class)))

Now all we need is emacs to clean up the symbol at point, and call this function via slime.

(defun slime-javadoc (symbol-name)
  "Get JavaDoc documentation on Java class at point."
  (interactive (list (slime-read-symbol-name "JavaDoc info for: ")))
  (or symbol-name (error "No symbol given"))
  (let ((class-name (slime-eval
                     (list 'resolve-symbol
                           (first
                            (split-string (trim-trailing-dot symbol-name)
                                          "/"))
                           (slime-current-package)))))
    (if class-name
        (browse-url
         (concat (javadoc-root class-name)
                 (subst-char-in-string ?$
                                       ?.
                                       (subst-char-in-string ?.
                                                             ?/
                                                             class-name))
                 ".html"))
      (message "No javadoc found for %s" symbol-name))))

The javadoc-root function is just a way to dispatch to different javadoc paths (local or online), based on the package names. For example, by defining:

(setq javadoc-alist
      '(("^\\(java[x]?\.\\|org\.ietf\.\\|org\.omg\.\\|org\.w3c\.\\|org\.xml\.\\)" .
         "file://opt/java/docs/api/")
        ("^org\.jets3t" . "file://opt/java/jets3t-0.7.0/api-docs/")
        ("^com\.xerox\.amazonws" . "file://opt/java/typica-1.5.2a/apidocs/")
        ("^org\.mortbay" . "http://www.mortbay.org/apidocs/")))

Now, emacs/w3m will load the right documentation, based on the class package prefix.

The code is available on github.

Unity.

cynojure.aws -- amazon web services from clojure

I've been using Amazon EC2, S3, and SQS services in various projects at work. For one project, I needed to build a little tool that integrated SQS and S3 services, and I decided to build it in Clojure. In the course of building the tool, I learned a bit about the various open source Java libraries for working with Amazon AWS, and the issues with integrating them with Clojure.

The libraries I used are:

Having been away from Java development for some time now, I'd forgotten about the convoluted mess of Classpaths and Class loaders. I had a "crash" refresher course in the last week. And, it's all still a bloody mess. I did come across one-jar, which made it pretty easy to package up the various jar dependencies into a single deliverable jar file.

In the end, the tool worked out well and served its purpose. Plus, it was rewarding to be able to write code like this:

(defun process-loop [:key
                     aws-access-key
                     aws-secret-key
                     geo-db-path
                     [message-count 5]
                     [sleep 5000]
                     sqs-queue]
  (with-geo-service (geo-get-service :path geo-db-path)
    (with-sqs-queue (sqs-get-queue aws-access-key aws-secret-key sqs-queue)
      (with-connection *db*
        (let [process (fn [msgs]
                        (if (empty? msgs)
                          (Thread/sleep sleep)
                          (try
                            (transaction
                             (doseq [msg msgs] (process-message msg)))
                            (doseq [msg msgs] (sqs-delete-message msg))
                            (catch java.sql.BatchUpdateException ex
                              (println "* process error:"
                                       (.getNextException ex))))))]
          (while true
            (try
              (process (sqs-receive-messages message-count))
              (catch Exception ex
                (println "* error:" ex)))))))))

and know it's running on the JVM.

I've committed some of the code for the Amazon integration into the cynojure git repository, in case anyone else finds it useful.

Harmony.