Clojure (and some Lisp) in 10 mins for OO developers

Notes from a short talk at xp-manchester:

No doubt the most useful slide is 3, which is a 1-slide "how to read lisp" tutorial.

We did a series of 10 minute talks on the evening, including a set of 3 on features of functional languages: Haskell's strong typing, mostly inferred; & Erlang's agents. Erlang's agents are almost like an OO language in which every 'class' (agent) gets its own process; which is what OO seemed to suggest to me when I read descriptions of the grand idea in the 80s/90s. My headlines for Clojure are largely the points made in http://clojure.org/rationale

Permission denied errors with HomeBrew & Maven / Could not resolve dependencies with lein

Like so many developers with a Mac I was pleased with the fact that homebrew at last offered package management on OS X that works as easily as it does on linuxes; but never quite managed to deal with all the issues that brew doctor listed.

Which I could ignore until I started using maven and leiningen (which uses maven). Because maven is itself a package manager, so the user id with which you brew installed it may prevent you using it later.

It starts (in my case) with

brew install maven

which failed because I didn't have write access to /usr/local/opt or something.
Undoubtedly the right step in future is to chmod /usr/local/ at this point. But I didn't, instead I

sudo brew install maven

which worked. This might not have mattered but then I also

sudo brew install leiningen

Which installed something or other into my maven repository. As root. I tested my new install with lein new at the command line and that works so I merrily plough ahead with installing clojure and leiningen plugins into my IntelliJ IDE, try the get started project and ... get errors in the ide:
ExceptionInfo: Could not resolve dependencies: Could not resolve dependencies
Back to the command line, and I realise that although lein new works, almost no other lein command does - they all fail with a million lines of output somewhere in which I find some permissions issue when trying to install a different version of clojure to the one I'd already installed:

Downloading: org/clojure/clojure/1.3.0/clojure-1.3.0.pom from repository central at http://repo1.maven.org/maven2
[WARNING] Unable to get resource 'org.clojure:clojure:pom:1.3.0' from repository central (http://repo1.maven.org/maven2): Specified destination directory cannot be created: /Users/myusername/.m2/repository/org/clojure/clojure/1.3.0
Downloading: org/clojure/clojure/1.3.0/clojure-1.3.0.pom from repository clojars at http://clojars.org/repo/
[WARNING] Unable to get resource 'org.clojure:clojure:pom:1.3.0' from repository clojars (http://clojars.org/repo/): Specified destination directory cannot be created: /Users/myusername/.m2/repository/org/clojure/clojure/1.3.0
Downloading: org/clojure/clojure/1.3.0/clojure-1.3.0.jar from repository central at http://repo1.maven.org/maven2
[WARNING] Unable to get resource 'org.clojure:clojure:jar:1.3.0' from repository central (http://repo1.maven.org/maven2): Specified destination directory cannot be created: /Users/myusername/.m2/repository/org/clojure/clojure/1.3.0
Downloading: org/clojure/clojure/1.3.0/clojure-1.3.0.jar from repository clojars at http://clojars.org/repo/
[WARNING] Unable to get resource 'org.clojure:clojure:jar:1.3.0' from repository clojars (http://clojars.org/repo/): Specified destination directory cannot be created: /Users/myusername/.m2/repository/org/clojure/clojure/1.3.0
An error has occurred while processing the Maven artifact tasks.
 Diagnosis:
Unable to resolve artifact: Missing:
----------
1) org.clojure:clojure:jar:1.3.0

  Try downloading the file manually from the project website.
..etc ... etc..

Grr. I suppose I'd better try to fix those brew doctor errors.

Fixing the homebrew brew doctor errors

I decide to ignore the errors the brew doctor gives about other *-config files installed. Why shouldn't I have? I also ignore homebrew's desire to have /usr/local/bin ahead of /usr/bin in my path as I have no idea what the impact of changing it will be. I assume Apple set it that way but then again maybe macPorts did it a decade ago.

But I do want to fix the 'no write permissions issues':

This set of errors:
Warning: /usr/local/etc isn't writable.
You should probably `chown` /usr/local/etc
...
Warning: /usr/local/include isn't writable.
You should probably `chown` /usr/local/include
...
Warning: /usr/local/share isn't writable.
You should probably `chown` /usr/local/share

I fixed this not by chowning but by adding myself to the wheel group, which might or might not have been a bad idea. But I didn't like the idea that the homebrew install on my machine was tied to my login.

# "g+u" copies all the permissions that the user has to the group
sudo chmod -R g+u /usr/local/share/
# add myself to the wheel group so that I have group access to all the stuff that homebrew installed
# actually I could have sworn I already was a member of wheel because of being an admin user but I didn't see wheel when I typed id. 
sudo /usr/sbin/dseditgroup -o edit -a myusername -t user wheel

Fixing the maven repository 'Specified destination directory cannot be created' errors

This isn't too hard. I examine the exact path in the error message and then find that my earlier sudo brew install leiningen has resulted in the org.clojure directory in my maven repository being owned by root, and I have no write permissions to it:

ls -l /user/myusername/.m2/repository/org
# rwxr-xr-x   6 myusername  staff  204 Jan  9 14:59 antlr
# drwxr-xr-x  10 myusername  staff  340 Jan 14 15:37 apache
# drwxr-xr-x   4 myusername  staff  136 Jan  9 14:58 aspectj
# drwxr-xr-x   9 myusername  staff  306 Jan  9 14:59 atmosphere
# drwxr-xr-x   3 root      staff  102 Jan 15 06:59 clojure
# aha. Bits of my repository - the clojure dir -  is owned by root and I don't have write permissions.
#
# This time I'm happy to chown because the repository is in my home directory anyway.
sudo chown -R myusername /Users/myusername/.m2/repository/

If was starting from scratch I'd probably prefer a repository for the machine, but I didn't pay attention to the
=> Caveats
Standalone jar and dependencies installed to:
$HOME/.m2/repository

message when I installed maven. Because of course I just wanted to install maven and get on with using it.

And now leiningen works. Mostly.

Now I try lein again:

lein test

Woohoo. lein can now successfully downloads its dependencies, and it works.
Back to IntelliJ and press the lein go button: that works too. Now I can run and test clojure.
But wait. Now I try to follow the palletOps quickstart instructions and I get error messages again. Eventually I find that there are files in ~/.lean which are also owned by root so I also need:

sudo chown -R myusername /Users/myusername/.lein

Remove HomeBrewed leiningen and download leiningen 2 from Github

By this time I was fed-up. And, homebrew had installed lein 1.7.1 but lein 2 is already mainstream. So I gave up on the homebrew'd install of leiningen and went native as per https://github.com/technomancy/leiningen/wiki/Upgrading. (Give or take the fact that I've got curl on OS X, not wget. Oh wait, there's a brew for that 😉 )

sudo brew uninstall lein
sudo rm -Rf ~/.lein
sudo curl https://raw.github.com/technomancy/leiningen/preview/bin/lein -o /usr/bin/local/lein
lein self-install

There. That's better. Now it works properly.

References