Ruby's URI for Clojure

December 13, 2008

Ruby has a nice library for working with URIs:

$ irb --simple-prompt
>> require 'uri'
=> true
>> uri = URI.parse "http://www.google.com/search?q=clojure"
=> #<URI::HTTP:0x2adb22 URL:http://www.google.com/search?q=clojure>
>> uri.scheme
=> "http"
>> uri.host
=> "www.google.com"
>> uri.path
=> "/search"
>> uri.query
=> "q=clojure"

So how do we get this same functionality in Clojure? Well, turns out Java has a library that is functionally equivalent to Ruby's. The downsize is it entirely very Java-ish:

~/src/clojure $ java -jar clojure.jar
Clojure
user=> (def uri (java.net.URI. "http://www.google.com/search?q=clojure"))
#'user/uri
user=> (.getHost uri)
"www.google.com"

It would be nice to use this in a more idiomatic Clojure way, but one of the principals of Clojure is to provide access to all the Java libraries without having to write Clojure wrappers for all of them. So one way to accomplish this is with the clojure bean function. It takes a java bean and returns a Map with the values for all of the getters in the bean. We can use this to use the URI in an idiomatic way that looks more like the Ruby version:

user=> (def uri (bean uri))
#'user/uri
user=> (uri :scheme)
"http"
user=> (uri :host)
"www.google.com"
user=> (uri :path)
"/search"
user=> (uri :query)
"q=clojure" 

Posted in Technology | Tags Clojure | 0 Comments

Stripes Book from the Pragmatic Programmers

July 23, 2008

It's really good to see a book being published by the Pragmatic Programmers on the Stripes, even if it is too little, too late. I wrote an article on Stripes a few years ago, and actually, I still like how Stripes handles mapping request parameters to an object graph, but since then I have discovered the benefits of dynamic languages like Ruby, so I would never consider using a framework like Stripes, just because it means programming in Java. When I was doing Java, I felt that Stripes was a much better framework than WebWork/Struts, but for some reason flew under the radar. In fact, this blog is built using Stripes. Stripes' creator Tim Fennell always did an excellent job answering questions on the mailing list and deserved more recognition from the Java community as a whole.

It's surprising to see this book coming out now. Frankly, straight Java as a web development language is yesterday's technology, the Cobol of our generation. The JVM is still alive an well, with many great options, such as JRuby, Groovy, Scala and the best of them all, Clojure. I would love to see a Pragmatic Programmer book on Clojure, just to give some more attention to Clojure, because it is such a great language. Anyway, congrats to Tim Fennell, Frederic Daoud and the Stripes team on finally getting some acknowledgment for building a great framework and a great community.

Posted in Technology | Tags Stripes, Java, Clojure | 8 Comments

Interactive Development with Clojure

July 11, 2008

A screencast on interactive development with Clojure.

Download original 18MB quicktime file

Posted in Technology | Tags Clojure, Lisp | 2 Comments

Getting Started with Clojure and Aquamacs

July 2, 2008

I just posted a short screencast on how to get started with Clojure and Aquamacs:

One of the fun features of Clojure, or any Lisp I suppose, is the interactive development workflow. As you can see in the video, you write code by creating expressions that define functions and then you evaluate those functions in the REPL (Read-Eval-Print-Loop). You can redefine a function at any time. You can imagine that if you had a production system running, you could connect to it via a REPL or something like that, evaluate some expressions that redefine functions that contain bugs, and the system would be fixed with no downtime.

Here's the contents of the ~/bin/clj script:

#!/bin/bash 

SRC_DIR=/Users/pbarry/src

CLOJURE_JAR=$SRC_DIR/clojure/clojure.jar
JLINE_JAR=$SRC_DIR/jline/jline-0.9.94.jar

if [ -z "$1" ]; then 
    java -cp $JLINE_JAR:$CLOJURE_JAR jline.ConsoleRunner clojure.lang.Repl    
else
    java -cp $CLOJURE_JAR clojure.lang.Script $1
fi

Posted in Technology | Tags Emacs, Clojure, Aquamacs, Lisp | 14 Comments

Getting Started with Clojure

December 22, 2007

After finding out about Clojure, I just couldn't wait work on some examples. Step one is getting it downloaded and installed. That's pretty straightforward, you just download it and follow the examples from the website.

One problem is that running it from the command line is a lot of typing and how do a run code I have saved in a file? Something better will probably come along eventually, but here's what I did. First, save closure in /usr/local/lib/closure. Then, copy JLine jar to that directory. Finally, create a shell script at /usr/local/bin/clj with the following contents:

#!/bin/bash 
CLOJURE_DIR=/usr/local/lib/clojure       
CLOJURE_JAR=$CLOJURE_DIR/target/clojure-lang-1.0-SNAPSHOT.jar
if [ -z "$1" ]; then 
    java -cp $CLOJURE_DIR/jline-0.9.93.jar:$CLOJURE_JAR \
        jline.ConsoleRunner clojure.lang.Repl    
else
    java -cp $CLOJURE_JAR clojure.lang.Script $1
fi

So with this, assuming /usr/local/bin is in your path, you can either run a script of invoke the REPL:

#run foo.clj
clj foo.clj

#start the REPL
clj

Now that we've got that out of the way, I thought I would provide a slight variation of the Runtime Polymorphism example:

(defmulti encounter (fn [x y] [(:Species x) (:Species y)])) 

(defmethod encounter [:Bunny :Lion] [b l] 
  (str (b :name) " runs away from " (l :name))) 

(defmethod encounter [:Lion :Bunny] [l b]
  (str (l :name) " eats " (b :name))) 

(defmethod encounter [:Lion :Lion] [l1 l2]
  (str (l1 :name) " fights with " (l2 :name))) 

(defmethod encounter [:Bunny :Bunny] [b1 b2]
  (str (b1 :name) " mates with " (b2 :name)))

(def bugs {:Species :Bunny, :name "Bugs"}) 
(def betty {:Species :Bunny, :name "Betty"}) 
(def simba {:Species :Lion, :name "Simba"}) 
(def scar {:Species :Lion, :name "Scar"}) 

(println (encounter bugs betty)) 
(println (encounter bugs simba)) 
(println (encounter simba bugs)) 
(println (encounter simba scar))

So refer to the documentation on Runtime Polymorphism for a full explanation of what's going on here, but here's my short summary. When you call encounter, the defmulti is called first. The defmulti returns a data structure that is then used to dispatch to a defmethod that matches that data structure. The defmulti uses the value that corresponds to the key :Species in the map to construct that data structure, but the defmethod doesn't know or care where that value came from. The first list in the defmethod for encounter is what should be matched. In other words, if the defmulti returns [:foo :bar], then it calls defmethod encounter [:foo :bar]. The second list is the declaration of the arguments that the method takes.

Another little nugget in there is that the comma is whitespace. Maps are defined as a list of alternating key values, surrounded by curly braces. So {:a 1 :b 2 3 :c :d 4} is a map, but as you can see, sometimes without the commas, it can be confusing. So you can write is as {:a 1, :b 2, 3 :c, :d 4} to make it more clear where the pairs are, but it's not required.

Posted in Technology | Tags Clojure | 2 Comments

<< Newer Articles   Older Articles >>