Thursday, 31 December 2009

ACL: Chapter 2

Here is the code I wrote while working through Chapter 2. Some comments follow below:
;; recursion example from p.16
;; note empty? instead of null
;; explicitly return true / false instead of lst / nil
(defn our-member [obj lst]
  (if (empty? lst)
    false
    (if (= (first lst) obj)
      true
      (recur obj (rest lst)))))


;; ask-number example from p.20
;; this is the closest simple version I've come up with
;; doesn't work with the same input as the example in ACL
;; e.g. entering a leads to
;; CompilerException java.lang.Exception: Unable to resolve symbol: a in this context (NO_SOURCE_FILE:111)
;; the (eval (read)) is needed because (read) by itself returns something like
;; (eval '(do a))
;; appears to be a difference with ACL
(defn ask-number []
  (print "Please enter a number. ")
  (flush)
  (let [val (eval (read))]
    (if (number? val)
      val
      (recur))))


;; version of ask-number that works for the same inputs used in ACL
;; this wouldn't work in enclojure
(defn ask-number2 []
  (print "Please enter a number. ")
  (flush)
  (let [val (try (Integer/parseInt (read-line))
      (catch NumberFormatException nfe nil))]
    (if (number? val)
    val
    (recur))))

;; exercise 3
;; 3 different cons functions that return (a b c)
(cons 'a '(b c))
(cons 'a (cons 'b '(c)))
(cons 'a (cons 'b (cons 'c ())))

;; exercise 4
;; define a function that takes two arguments and returns the greater
;; of the two
(defn greater [x y]
  (if (> x y) x y))

;; exercise 7
;; using only operators defined in this chapter
;; define a function that takes a list as an argument
;; and returns true if one of its elements is a list
(defn contains-list? [lst]
  (if (empty? lst)
    false
    (if (list? (first lst))
      true
      (recur (rest lst)))))

;; exercise 8a
;; recursive and iterative function that takes an integer
;; and prints that many dots
;; since we are using recur there isn't really a huge difference
;; between the 2 implementations. loop/recur feels very like
;; the recursive call

;; recursive
(defn dots-recur [n]
  (if (zero? n)
    (println)
    (do
      (print ".")
      (recur (dec n)))))

;; iterative
(defn dots-iter [n]
  (loop [counter n]
    (if (zero? counter)
      (println)
      (do
        (print ".")
        (recur (dec counter))))))

;; recursive no recur
;; leads to stack overflow
(defn dots-recur-naive [n]
  (if (zero? n)
    (println)
    (do
      (print ".")
      (dots-recur-naive (dec n)))))


;; exercise 8b
;; function that takes a list and counts number of times a
;; appears in it

;; recursive
;; can't use recur here because not in tail position
;; therefore prone to stack overflow for long lists
(defn counta-recursive [lst]
  (if (empty? lst)
    0
    (+ (if (= (first lst) \a) 1 0) (counta (rest lst)))))


;; iterative
;; seems more natural to write it this way
(defn counta-iterative [lst]
  (loop [sublist lst total 0]
    (if (empty? sublist)
      total
      (recur (rest sublist) (+ total (if (= (first sublist) \a) 1 0))))))
Some observations based on what I learnt while working through chapter 2:
  1. It proved difficult to implement the ask-number function in Clojure. The read function seemed to return an unevaluated form, which I rationalized as making sense since it was returning a form to pass to eval. See the comments in the code above for more detail.
  2. Enclojure seemed to have problems with the read-line function. I was only able to make the ask-number2 function work in the repl started from my bash shell.
  3. The iterative/recursive functions in chapter 8 didn't feel hugely different in Clojure due to the explicit use of recur. However I did see the benefit of using an iterative algorithm in the counta example, since I couldn't use recur in the recursive implementation, making it vulnerable to stack overflow. 
  4. We don't really need to use iteration or recursion explicitly for the counta examples. An even better way to implement this function using the Clojure sequence library would be:
(defn counta-filter [lst]
  (count (filter #(= % \a) lst)))

ACL: Chapter 1

In Chapter 1, Graham writes:
Suppose instead you want to write a function that takes a number n, and returns a function that adds n to its argument. (ANSI Common Lisp, p.1-2)
He then gives a simple lambda function that implements this functionality. The 2 Clojure alternatives that I have come up with are:
;; p.2 - form using explicit fn syntax
(defn addn [n]
  (fn [x] (+ x n)))
And the terser form:
;; p.2 - use the terse form of anonymous function
(defn addn-terse [n]
  #(+ % n))
In my first I had too many brackets in the terser form which led to a cryptic error:
;; p.2 - incorrect form of anonymous function
(defn addn-terse-incorrect [n]
  (#(+ % n)))
Leads to the error:
com.nwalex.clj.acl-chpt1=> (addn-terse-incorrect 6)
java.lang.IllegalArgumentException: Wrong number of args passed to: acl-chpt1$addn-terse-incorrect--523$fn (NO_SOURCE_FILE:0)>
In my opinion sweating blood is the best way to learn. The terse form of the anonymous function is now thoroughly embedded in my brain because I had to work out why my original attempt wasn't working. You can't learn something like that simply by reading a book.

Wednesday, 30 December 2009

Learning Clojure: Next Steps

I've finished working through "Programming Clojure" and need to work on something else to help drive home what I've learnt. So, I'm going to work through "ANSI Common Lisp" by Paul Graham and implement the exercises in Clojure. This should give me more background knowledge on Lisp, and force me to consider how Clojure differs. In addition it will get me writing Clojure code.

HP LaserJet 1022 Not Working Under Snow Leopard

I was having a problem with my printer where it would print only the first page of a job, then go offline with the status lights flashing. This made it impossible to print anything longer than 1 page.

After a bit of googling I stumbled across a HP support thread at http://h30434.www3.hp.com/t5/Mac-printing-and-scanning/LJ-1022-not-working-under-Snow-Leopard-latest-driver/td-p/122959/page/6 which provided a solution. It seems that the updated driver doesn't work under Snow Leopard. The solution is to downgrade to an older driver. Anyway, the steps to fix it are detailed at the link above as described by Cytokrom_C. I thought I would reproduce the instructions here just in case it might help someone else to fix the problem:
I had the issue with alternate pages only printing and flashing lights of the printer as many others have reported on my 1022 over USB. However, for me the old drivers (2006) seem to be working fine in Snow Leopard. They can be downloaded here:
http://h20000.www2.hp.com/bizsupport/TechSupport/SoftwareIndex.jsp?lang=en&cc=uk&prodNameId=439431&prodTypeId=18972&prodSeriesId=439424&swLang=8&taskId=135&swEnvOID=219

-Install the drivers (from the pkg-file).
-Open the printer settings in the system preferences.
-Then remove the old installation(s) by marking them and clicking on the (-)-sign
-Add a new printer by clicking on the (+)-sign
-Make sure that you chose the driver "HP LaserJet 1022"-driver and not the HP LaserJet 1022, 1.1.0.182" driver.

I don't know if there are any issues with using these old drivers yet, as I have not tested them much yet. However, I was at least successful in printing a multiple page document twosided from Firefox.
This worked for me.

Link: Setting up Clojure on Ubuntu with Emacs

I found the following links which, if worked through in order, result in a working Clojure installation on Ubuntu, complete with Emacs:
In order to run the repl using JLine (to easily access history with key UP etc) I added the following to my .bashrc:
export CLOJURE_MAIN="jline.ConsoleRunner clojure.main"
Yes, that's right, I'm dipping my toes in the Emacs waters. To help navigate and avoid Ludovicians I'm using this cheat sheet:
Update 1: I've also found the following cheat sheet which provides a (what seems to be) fairly comprehensive reference to Emacs:
Update 2: I'm reverting to my original approach - learn Clojure using Enclojure / NetBeans.  Trying to learn Emacs and Clojure at the same time is too much for my little brain.

Update 3: Just so I have all links in one place, this is a really useful Clojure cheat sheet:
Oh yeah - and I'm back to using Emacs again!

Thursday, 24 December 2009

Understanding How 'use' Works

As I was working through the "Programming Clojure" book I realized that I didn't fully understand how the 'use' function was working. For example:
(use '[clojure.contrib.repl-utils :only (source)])
Specifically, I didn't understand why the vector of args was quoted i.e. why it started with the inverted comma. So, since I want to understand the language, I decided to work it out.

It turns out that quote is a special form in Clojure: http://clojure.org/special_forms#quote. It yields the unevaluated form, which I take to mean that the evaluator in the REPL just takes the form at face value and defers evaluation. To validate that conclusion I did some experimentation at the REPL prompt:
user=> (def a 2)
#'user/a
user=> [a 1]
[2 1]
user=> '[a 1]
[a 1]
user=> (eval a)
2
Without the quote, the vector [a 1] is evaluated, meaning we get the value of a, which was set to 2. With the quoted vector the 'a' is not evaluated but I can force evaluation by calling eval directly.

So I think the reason that the vector of args to 'use' needs to be quoted is to stop the evaluator evaluating the arguments at the point of entry. Instead they will be evaluated within the context of 'use'....

Hmmm. I don't quite understand the final step yet. I think there is a gap in my knowledge that I need to fill in. Hopefully this will become clearer as I continue to work through the book.

Update 1: I may be a bit closer now. I think the point is that 'use' expects Symbols as the lib names. If I pass in Strings then I get a ClassCastException. The api documentation for 'require' (which is what the api for 'use' refers to) at http://richhickey.github.com/clojure/clojure.core-api.html#clojure.core/require says:
Lib names are symbols and each lib is associated
with a Clojure namespace and a Java package that share its name.
 And the way to pass symbols is to quote them to prevent them being evaluated:
user=> (map class '[a b c])
(clojure.lang.Symbol clojure.lang.Symbol clojure.lang.Symbol)
The vector as a whole is called a "Prefix List", defined in the 'require' api as:
It's common for Clojure code to depend on several libs whose names have
the same prefix. When specifying libs, prefix lists can be used to reduce
repetition. A prefix list contains the shared prefix followed by libspecs
with the shared prefix removed from the lib names. After removing the
prefix, the names that remain must not contain any periods.
So in the example at the top of this blog entry, I passed a prefix list to 'use', in the form of a vector. Since the vector was quoted, each item within the vector was quoted, which meant the evaluator did not evaluate the symbols. Hence the symbols were passed as the args, which is what 'use' requires.

I think I understand now.

Update 2: Reading through "ANSI Common Lisp" by Paul Graham I came across a couple of quotes (no pun intended) relevant to this:
Symbols do not (usually) evaluate to themselves, so if you want to refer to a symbol, you should quote it... (ACL, p.11)
 Then, later on the same page:
If a list is quoted, evaluation returns the list itself; if it is not quoted, the list is treated as code, and evaluation returns its value. (ACL, p.11)
 And finally:
Now that we've seen variables, it's easier to understand what symbols are. They are variable names, existing as objects in their own right. And that's why symbols, like lists, have to be quoted. A list has to be quoted because otherwise it will be treated as code; a symbol has to be quoted because otherwise it will be treated as a variable. (ACL, p.15)
The 'use' function expects a vector (sequence?) of symbols, hence the vector needs to be quoted.

Link: Rich Hickey Clojure Videos

I was going to gather together direct links to videos of Rich Hickey talking about Clojure. But actually, everything I've found is directly accessible from one of the following 2 links:
  • http://www.infoq.com/author/Rich-Hickey - all the Infoq material by Rich Hickey.
  • http://clojure.blip.tv/ - the main set of Clojure videos, linked to from the clojure.org web-site. It has titles like, "Clojure for Java Programmers", "Clojure for Lisp Programmers". I haven't had a chance to watch them all yet, but it certainly seems like a fantastic resource for a more in-depth look at Clojure.
I've already watched one of the Infoq videos, the presentation from the 2008 JVM Languages Summit. I found it really interesting, entertaining, and informative, and would recommend it to anyone wanting a quick 30 minute introduction to Clojure.

Now I'm going to work my way through the rest.

Update 1: I've just watched another of the Infoq videos, this one from the QCon conference in London in 2009. It talks about Clojure's approach to identity and state, and what goes on under the covers of ref, atom, agent etc. I found it absolutely fascinating. Next!

Update 2: The video at http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey is like an extension of the 'Philosophy' section from the the video in Update 1. Again, I found it fascinating. Having watched these videos I have a whole new appreciation of the benefits of functional programming, and the problems object oriented programming has when it comes to concurrency.

Link: Dynamic Interactive Webdevelopment Screencast

This is a link to a 12 minute video showing how to do basic web-development using Clojure, Compojure, and Emacs:

http://www.bestinclass.dk/index.php/2009/12/dynamic-interactive-webdevelopment/

As I commented on Lau's blog, it makes me think I should bite the bullet and learn Emacs. Mind you, I also think I should someday bite the bullet and read "Ulysses" by James Joyce, and I haven't quite managed that yet.

Wednesday, 23 December 2009

Link: Dabbling in Clojure

I found this article by Keith Bennett really interesing:

http://krbtech.wordpress.com/2009/03/16/same-temperature-converter-different-language-clojure/

GTD on RTM

Having settled on Remember the Milk as my Getting Things Done tool of choice, I decided to re-read the book to reacquaint myself with the system. I'm only up to Chapter 2, but have already made some changes to my RTM setup.

I now have the following lists:





These lists won't be particularly surprising for anyone familiar with GTD, though there are a few minor differences from the basic system David Allen describes in Chapter 2:
  • Instead of 'Calendar' I have a list called 'Scheduled'. This contains any tasks that have a due date associated with them. This is a legacy of using Thinking Rock which has a 'Scheduled' list.
  • The 'Sent' list is built into RTM. I don't use it, since I don't send tasks to any other RTM users, currently.
  • The 'Today' and 'Work' lists are Smart Lists that I use to give me quick access to tasks I need to complete today, and tasks I need to complete at work, respectively. I tag all work tasks with a 'work' tag. 

Weekly Review

While re-reading GTD I realized that I had forgotten a very important part of the system - the weekly review. I now have a repeating task in RTM to go through a full review of all tasks every Sunday. As part of this review I:
  • Check that the inbox is clear.
  • Check that all actions in all lists describe atomic, achievable tasks. This may lead to moving somes tasks into the 'Projects' list, and tagging them as a 'project'.
  • Check that all projects have next actions defined. I do this using ad-hoc searches on tags (every project has a unique tag e.g. pr-learn-clojure).
  • Check that all the tasks in the 'Scheduled' list have a due date.
  • Review the 'Someday' list to identify any tasks / projects that I want to start working on, and move them to either 'Next' or 'Projects' list.
  • Review tasks in the 'Waiting' list to check whether any further action is required.
I am sure the process will evolve and develop as I re-read more of GTD.

The combination of GTD and RTM is proving very powerful. Remember the Milk is making it very easy to fully integrate Getting Things Done into my life.I have noticed a massive improvement in my personal productivity and relaxation levels already.

And it's fun!

Update 1: For Xmas I got a new extension for Firefox, A Bit Better RTM. It makes using RTM even more of a delight. My particular favourite features are:
  1. The ability to hide lists. I can now hide the 'Sent' list.
  2. Keyboard shortcuts for navigating through lists.
  3. Moving the list tabs from the top to the left hand side.
All in all this is a fantastic extension.

Tuesday, 22 December 2009

Programming Clojure: Compiling to Disk

I thought I would make a note of this just in case anyone else is as bone-headed as me. In section 3.3 of Programming Clojure (Creating and Compiling Java Classes in Clojure) I couldn't work out how to compile the reader.tasklist library:
(compile 'reader.tasklist)
What I didn't realize, and what I don't think the book makes particularly clear, is that you can't enter the code into the REPL and then compile it. Instead you need to start with the file reader/tasklist.clj and then add the various functions into that file. The compile function compiles the .clj file into Java .class files just as javac compiles .java files in to .class files.

I can't believe it took me so long to work this out. Fortunately I didn't tear out all my hair. I still have a few tufts left.

Making Enclojure Respect My Authoritah

I discovered yesterday that Enclojure does not respect the netbeans_default_userdir setting I have defined in %NETBEANS_HOME%/etc/netbeans.conf. This was a problem because I have a roaming profile with limited space for files. I keep my NetBeans profiles on a non-networked directory so that I don't run out of space.

In order to force Enclojure to use the same directory I had to create a little batch file to override my USERPROFILE environment variable, like so:

Problem solved.

Update 1: I hit a problem with this hack. Whenever I tried to open a file dialog in NetBeans I got an IOException with the error message: "Could not get shell folder ID list". After a bit of digging around on Google I came across this bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6544857. Some discussions about it suggested it was something to do with the Documents directory being missing. I was able to resolve the problem by copying the contents of my actual %USERPROFILE% directory onto the C: drive, then updating the script to point at the mock profile directory. File choosers now work again. There must be something in the profile directory that Java is using to open a file dialog.

Link: The Appeal of Lisp

This essay by Paul Graham describes well the appeal of Lisp.

The Appeal of Clojure

Lisp has always intrigued me. A few years ago I bought "Practical Common Lisp" by Peter Seibel and "On Lisp" by Paul Graham. I read the Paul Graham book but never got round to working through PCL. There were a couple of reasons for this:
  1. Emacs. Now I appreciate that Emacs is an incredibly versatile and powerful program. But my god, it's a daunting one to begin using. My attempt to learn Lisp quickly became an attempt to learn Emacs, and at some point along the way I lost interest in shaving that particular yak.
  2. I also had the feeling that Lisp would never be a language that I would be able to incorporate into my life as a corporate programmer. I couldn't forsee being able to write little scripts, or tests, or personal apps to use at work in Lisp.
And so the Lisp books went back onto my bookshelf.

Clojure is a Lisp built on top of an environment I already know. I can concentrate on learning the language without having to shave any yaks. I can develop it in NetBeans (my IDE of choice), using Enclojure. And it's built on top of the JVM, which means I have access to all the Java libraries I know and love. This means that I can forsee being able to use Clojure at work.

I'm very excited about this. The wow moment I had yesterday while working through the initial pages of "Programming Clojure" really got the juices flowing. I'm looking forward to being able to read and understand in depth blog entries like http://meshy.org/2009/12/13/widefinder-2-with-clojure.html. And more importantly, I'm really excited about using Clojure to develop my personal projects at home. It will be a very pleasant change from the endless lines of boilerplate Java code I churn out at work.

Monday, 21 December 2009

Clojure - Wow!

I started working through "Programming Clojure" by Stuart Halloway today and had a wow moment very early on. Compare the following implementations of isBlank().

In Java:
public class StringUtils {
  public static boolean isBlank(String str) {
    int strLen;
    if (str == null || (strLen = str.length()) == 0) {
      return true;
    }
    for (int i = 0; i < strLen; i++) {
            if ((Character.isWhitespace(str.charAt(i)) == false)) {
              return false;
            }
    }
    return true;
  }
}

In Clojure:
(defn blank? [s] (every? #(Character/isWhitespace %) s))

Wow!

Sunday, 13 December 2009

Getting Things Done

I read "Getting Things Done" by David Allen a couple of years ago, and quickly adopted many of his suggestions. And for a while it really seemed to help me to organize my life and, well, get things done. But then things started to drift and my productivity dropped off. Why did this happen?

When I first started to implement my GTD system, I looked around for a desktop tool that I could use at home and at work. Since I use Ubuntu and MacOS X at home, and Windows at work, it had to be a cross platform tool. That narrowed the range of options down drastically, and I eventually landed on Thinking Rock, a Java based desktop tool. This worked reasonably well, except for the fact that I had no way to automatically synchronize my task list across the various computers I was working on. I considered writing a plugin for Thinking Rock to allow me to do the synchronization but, for one reason or another, never quite got round to doing it. Instead I implemented a manual workaround.

The workaround entailed me using yet another tool, Things, for the iPhone. I divided my task list into things I had to do at work, and things I had to do outside of work. For the outside of work tasks I used Things. I had it in my pocket at all times, which meant I could refer to it, add new tasks etc whenever they came to mind. Then I set up a daily reminder on my Outlook calendar at work to prompt me to work through the inbox in Things, and re-key any work related tasks into Thinking Rock.

Like I said in the intro above, this worked well, for a while. But soon I started to get lazy. Having tasks split across 2 different tools meant I never had one consolidated list to check to see what to do next. In addition, the overhead of re-keying tasks into Thinking Rock at work, whilst fairly minimal, soon also became a problem. There are some days at work when my behind has barely had time to settle into it's chair groove before the phone starts ringing and the various demands of working in a big corporation shout to make themselves heard. So I'd miss the odd day here and there, with the here and there moving ever closer together. Until finally I removed Thinking Rock from my list of applications that automatically starts up on login, and went back to my old system of making notes in Tiddlywiki.

So, that brings us up to a couple of weeks ago, when I decided that I needed to re-assess my approach. I had read somewhere about a web-application called Remember the Milk that also had an iPhone app. On a quiet morning at work, I searched for it in Google and signed up for a free account. After playing around with the interface for a while, and adding a few test tasks to see what it could do, I decided that it had potential. I downloaded the iPhone app, played around with it, and liked it as well. Then I read this article on Lifehacker which reviewed RTM and gave an excellent introduction to its features. After reading that I took the plunge and signed up for a professional account.

I have now been using RTM for about a week and I couldn't be happier with it. It has revolutionized the way that I manage my life, and made me much more productive. I wouldn't be writing this blog now if I hadn't taken that plunge a week ago. Why? Because having all my tasks in one place, regardless of whether they are for work or for home, has greatly simplified things. I now only have one place to look to see what to work on next. I don't have any manual processes to synchronize things. It all just works. It's like the difference between dating someone whilst living apart, and moving in together. When you are in the dating phase, although you may spend every night together it's still either at your place or her place. When you move in together, it's our place. You still spend every night together, but the relationship is completely different. It's non-additive. It's greater than the sum of its parts.

Looking back I can see that the reason my GTD system broke down was because of the required manual synchronization effort. Now that I have my pro Remember the Milk account linked to an app on my iPhone, I have one consolidated task list everywhere, and I feel that I can really, seriously, get things done.

Saturday, 12 December 2009

Ubuntu on Mac Mini

For anyone else wanting to install Ubuntu on a Mac Mini, I found the following links helpful:

First Post

Right then. This here is my new blog. I say new blog because I have had other blogs. Oh yes. I am a serial starter of blogs. The first one was when I fancied myself as a bit of a chronicler of our times. Kind of a cross between Jonathan Swift, Robert Anton Wilson, and Bill Hicks but with all the talent removed. It didn't last long, and I can't even remember its name now.

I started the next one after reading and being blown away by the "Complete Prose" of Woody Allen. I decided that I would write humorous articles in the same vein. All I had to do was let my imagination off the leash, sit back and watch the genius flow from the tips of my fingers. Alas, I quickly discovered that my fingers were not attached to the hands, arms, body, or brain of a genius, and so that blog too petered out.

So why, you may ask, am I starting another? Well, this time my aim is different. This time I want to write as me, about the stuff I find interesting, and the things I am working on. Maybe that will be the last great film I watched. Maybe it will be about the last great techno album I listened to. Maybe about the last great book I read.

Or Maybe Technology.

Actually, my intention is to write about mostly technology. But I thought, if I name the blog Mostly Technology then I'll probably end up writing about anything but technology. So, 'maybe' it is.

Who knows whether this will fly? Who knows whether I will keep writing posts for longer than, ooh, let's say a month? Who knows whether anyone else will read my ramblings? Not me. And I don't really care. Right now it seems like a good idea so I'm going to run with it. If I run fast enough and flap my arms really hard, maybe it will fly. I'm not going to put myself under any pressure to write to a schedule. I'm not Jeff Atwood. I'm me. If I feel like writing, I'll write. If I don't, I won't.

So there.

Thank you for reading this First Post, hope you enjoyed it. Another may come along soon, or it may not. This could be the shortest lived blog I've ever written, or it could be the first post in a long and successful blogging career. I look forward to finding out which.