Monday, February 9, 2009

Doing it wrong, fun with Clojure

I certainly take a liberal approach to programming, some may call it quantity over quality but I like to enjoy everything I do. This may include doing it wrong, but sometimes I like the end result.

I am working on a SWT GUI tool and could not figure out a clean way to avoid SWT's illegal thread exceptions. When a user clicked a menu option on the gui, I needed to first take text from an edit box field and then use that data to pass to a long running thread. This is what I ended up with:

;; Define the clojure 'agent', save the state of our search box
(def *search-text-state* (agent nil))

;; Define an implementation of 'SelectionAdapter/Interface'
;; SelectionAdapter requires one method 'widgetSelected'
;; With display.syncExec, pass an implementation of java.lang.Runnable
;; The thread updates the 'agent' search-text-state text.
;; After we get this text value, then launch another thread 'start-findgrep'
(def findgrep-listener
(proxy [SelectionAdapter] []
(widgetSelected [event]
;; With the async call, set the agent value
;; based on the search box value
(. display syncExec
(proxy [Runnable] []
(run []
(let [val (. search-box getText)]
(send *search-text-state* (fn [_] val))))))
(let [widg-str (str (. event widget))]
(. (new Thread
(start-findgrep-thread widg-str @*search-text-state* true)) start)))))

Basically, in 10 lines of Clojure Lisp code, we implemented two method class (proxy) bodies and invoked a thread. It doesn't look pretty, but that is still pretty powerful that you are able to do that.

No comments: