Friday, 27 March 2009

Mac foo I learned today

Long time no post! Ho hum, been busy as ever.

Anyhow, for my own benefit just wanted to write down some Mac foo I learned today.

I was searching for the Mac equivalent of the Linux "eject" command. Lots of people online are spouting off about needing to reboot their macs and hold down keys to eject disks that aren't recognised, but what you really need is:

hdiutil eject /dev/disk1


Tuesday, 13 January 2009

Some good Clojure news, some bad Clojure news

So... first the bad news.

I've had to drop the Qt port of my little Clojure recruitment database. I was just hitting too many problems using Qt-Jambi and it was taking too long. The client needed a working database ASAP and I wasn't gonna get there. At the same time I also learned to use Apple's Core Data on Mac Os X 10.5 (which my client is running) and I managed to turn the bulk of the project around in an evening. It was one of those evenings where I couldn't sleep and in a way I am just glad to get the database out there and running - especially as "the client" is also my girlfrend :-)

The good news comes in two forms. One, getting the DB off my plate means I have more evening time to play with more interesting Clojure projects; two another Beta version of Stuart Halloway's book "Programming Clojure" came out. I intend to read some of the new chapters, particularly the one on Swing (which until now I have found clunky).

Friday, 9 January 2009

So, for fun, I did this little quiz:

http://www.gotoquiz.com/do_you_have_biblical_morals

Here are the results, I am sure you'll agree, shocking results. Who knew :-)

Your morality is 0% in line with that of the bible.
 

Damn you heathen! Your book learnin' has done warped your mind. You shall not be invited next time I sacrifice a goat.

Do You Have Biblical Morals?
Take More Quizzes

Sunday, 30 November 2008

AOT problem solved

Thanks to the swift responses of the Clojure google group I have got past my little problem. It was, of course, deceptively simple, but not clear to someone who doesn't do Java programming much.

The problem was basically that whatever I did I could not get Clojure to recognise that the source files existed in the classpath.

When you invoke java with the
-jar
command line option it completely ignores the classpath (both the environment variable, or the
-cp
argument.

So, when compiling my code I simply switch this:


java -cp ./classes:./src -jar ${HOME}/src/clojure/clojure.jar ./compile.clj


.. to this ...


java -cp ./classes:./src:${HOME}/src/clojure/clojure/jar clojure.lang.Script ./compile.clj


For the record the contents of
compile.clj
are as follows:


(binding [*compile-path* "/home/gteale/src/aot_test/classes"]
(compile 'de.teale.test))


I plan to replace that with either ant or lancet shortly.

Caught on a Clojure roller coaster

I was hoping to make some decent progress this weekend with my Clojure code. The plan was to port it to the new AOT model of compilation.

However, my efforts have been frustrated by me not being able to get AOT working. I have posted my problem to the group, so hopefully there will be some solution soon.

Clojure is developing so rapidly it's hard to keep up, I think that's how I got into this mess with AOT. However, for every new problem people are finding solutions that blow me away. This blog post details a really elegant solution to the lack of tail call optimisation for mutually recursive functions:

http://www.windley.com/archives/2008/11/tail_optimized_mutual_recursion_in_clojure.shtml

Thursday, 27 November 2008

AOT is cool, but it breaks some of the below content.

Clojure is a young language, and as such it's developing fast. It's an exhilarating ride to be on, but sometime it means things I've written change.

So, when reading the below posts, please note that the latest revisions to Clojure include the provision of Ahead-Of-Time (AOT) compilation. This will break the compilation mechanisms I used in some of the content below. When I get round to fixing up my programs I'll try an post revised instructions for Jar creation, till then I suggest you check out the docs here for compilation notes.

Sunday, 9 November 2008

On Clojure - part 3 - Qt Designer files and custom slots.

So, as promised, here's a few notes on how I am using Qt Designer with Clojure.
Some important things to remember:

  • You must use Qt Designer with the QtJambi plugins installed. The easiest way to do this is to run designer.sh (Linux / UNIX / Mac OS X) or designer.bat (Windows) from the distribution folder that QtJambi came in. If you've got QtJambi installed as a package under Linux then you may need to check that the QtJambi plugins are correctly installed , they weren't in my case.

  • If you have the QtJambi plugins installed designer should be able to save .jui files instead of .ui files.



I don't intend to tell you how to use Qt Designer, there's a good user manual available.
Once you've put together a UI in Designer plugging it into a clojure application is relatively simple, though there are some subtleties that took me a while to work out (along with a large chunk of time trawling #clojure logs, the wiki and various blog post - thanks to all who share their work!)
What follows is the full source code for an incredibly simple app that uses a single QMainWindow with a Designer derived layout, I'll explain some more after the code:

(gen-and-load-class "foo.gen.Slot"
:methods [["slot" [] Void]])

(ns foo
(:import (foo Ui_MainWindow))
(:import (com.trolltech.qt.gui QApplication QMainWindow))
(:import (com.trolltech.qt.core QCoreApplication))
(:import (foo.gen Slot)))


(def slots
(proxy [Slot] []
(slot [] (prn "Slot Called"))))

(defn init []
(QApplication/initialize (make-array String 0)))

(defn exec []
(QApplication/exec))

(defmacro qt4 [& rest]
`(do
(try (init) (catch RuntimeException e# (println e#)))
~@rest
(exec)))


(def Foo-main
(fn [& args]
(qt4
(let [ui_main (new Ui_MainWindow)
mainWindow (new QMainWindow)]
(. ui_main (setupUi mainWindow))
(let [pushButton (. ui_main pushButton)]
(.. pushButton clicked (connect slots "slot()")))
(. mainWindow (show))))))


This code lives in the package "foo", in the file "Foo.clj". If you're familiar R.P. Dillon's guide to with making Jar's from clojure you'll know that Foo-main is the Main function of the resulting JAR. Notice that we also import Ui_MainWindow from the same package. This is the generated Java code from the Designer file Ui_MainWindow.jui. In order to generate the java code you simply run:


juic Ui_MainWindow.jui


As I want the resulting code to live in a package, "foo", I need to manually add the following line to the top of the resulting file, Ui_MainWindow.java:


package foo;


We also need to arrange for this .java file to be compiled before we can use it. How you use this depends on your build system, but you can choose to just compile it by hand when it changes (as this should be comparitevly rare). I guess you know how, but just for completeness:


javac foo/Ui_MainWindow.java


Now, the qt4 macro I've defined there is directly lifted from Brian Carper's blog posting on using Qt4 in Clojure, and again I won't go into that here. Instead lets look at Foo-main. Note that we create instances of both the Ui_MainWindow class from the generated java code and the QMainWindow class. We call the setupUI method of the Ui_MainWindow class with the QMainWindow class as it's arguement (this essentially fills out the QMainWindow with the layout you put together in designer). Note also that I reference the pushButton widget inside the Ui_MainWindow class.

The remaining interesting thing about this file is that it defines a custom slot. Signals and Slots are fundemental to the way that Qt hangs together. Wiring together the prexisting signals and slots is very easy and can be done either in Designer or in code (as R.P. Dillon's example shows). Making a custom slot turns out to be rather more difficult. I naively assumed that I could just use a proxy around the QMainWindow class and add a slot function there, but this simply doesn't work. Instead I need to use (gen-class) to make a real class and bind a clojure function to it. For convenience I use (gen-and-load-class) - this call generates the bytecode and loads it. You have to pass it a fully qualifed class name - I've found it better to make it a subpackage, so I place it in foo.gen, and therefore the classname is foo.gen.Slot. I also have to give a place holder for the slot method. Confusingly enough I've chosen to call it "slot" here. We pass a vector containing a vector for each method, which in turn contains a method name, a vector of arguements and a return type. The method name will get bound to a function in the current namespace (not foo.gen, but foo) with the name -. In my example code this is contained in the proxy "slots" as the "slot" method. It's possible to just use a normal (defn) for this mapped method, in which case the function name would be "Slot-slot", I just find the proxy cleaner. Lastly you'll see that, back in Foo-main, I connect the pushButton's clicked signal to the custom slot, "slot" in the proxy, "slots". I hope that's clear!

Now all things being equal you should be able to make your JAR and execute the code. I hope that helps someone avoid spending a lot of time trying to work this out.

When I need to implement a custom signal I'll try and write that up too. Till then, ta ta!