Got my feet wet with Clojure

I started hardcode coding on Project Plugh. I’m working on moving a bunch of Lift concepts over to Clojure as I build Lift’s comet facilities in Clojure so I can stream data to the browser.

Background… PartialFunction

In Scala, there’s a PartialFunction

The key take-away for PartialFunctions is “… is a unary function where the domain does not necessarily include all values of type A.”
 
 
The ability to test a PartialFunction to see if the domain includes a particular value is very helpful. pf.isDefinedAt(x) allows testing to see if the function is defined at a given value of x.

But a PartialFunction is a subclass of Function, so PartialFunctions can be applied:

pf(x)

The Scala compiler will take a pattern and turn it into a PartialFunction:

def pf: PartialFunction[String, Number] = 
{
  case "" => 0 // special case blank to zero
  case x if isInt(x) => x.toInt
  case x if isDouble(x) => x.toDouble
  case x if isBigInt(x) => asBigInt(x)
}

Another property of PartialFunction is they can be composed:

pf = pf1 orElse pf2 orElse pf3 // pf isDefinedAt any place 
                               // any of the partial functions are defined

We use PartialFunctions extensively in Lift to allow choosing if a particular URL should be served by Lift, if it should be served by a particular REST handler, etc. For example, defining a REST route in Lift:

serve {
  case "api" :: "user" :: AsLong(userId) :: _ GetJson _ => 
       User.find(userId).map(_.toJson)
}

As I’ve been learning Clojure in preparation for a presentation at Strange Loop and as part of a new project I’ve been working on, I am looking to bring the best things in Lift into the Clojure code I write.

Into Clojure

Clojure’s pattern matching stuff is pretty nifty. I especially like how you can extract values out of a Map (this is so much more powerful that Scala’s pattern matching, even with unapply… but I digress).

So, I wrote a macro:

(defmacro match-func [& body] `(fn [~'x] (match [~'x] ~@body)))

This creates a function that is the application of the match to a parameter, so:

((match-func [q :guard even?] (+ 1 q) [z] (* 7 z)) 33)
;; 231

Turns out the Clojure pattern matcher will extract values into unbound variables. But bound variables are tested… this means that:

((match-func [[x y]] (+ x y)) [4 5])

Turns out this is a problem because x is bound in the match-func macro… so we need to change x to something else. So, we have to change the variable x to something else:

(defmacro match-func [& body]
    "Create a function that does pattern matching."
    `(fn [x#] (match [x#] ~@body)))

isDefinedAt

So, how do we test to see if the pattern matches at a particular value?

This became a challenge for me to wrap my brain around how things are done in Clojure. How do I have a function that represents the pattern match and be able to query it to see if it’s defined at a point without invoking the computation on the right-side which can be side-effecting.

The answer is arity. Scala has functions with defined arity. Turns out that Clojure can have a single function that behaves differently depending on the arity of the invocation. Yay!

So, the macro looks like:

(defmacro match-pfunc [& body]
  "Create a partial function that does pattern matching."
  (let [rewrite (mapcat (fn [x] [(first x) true]) (partition 2 body))]
  `(fn ([x#] (match [x#] ~@body))
       ([x# y#]
         (cond
           (= :defined? x#)
           (match [y#] ~@rewrite)
           (= :body x#)
           '(~@body))))))

What this gives us is a function than can be invoked with a single parameter:

(pf 44)

And it can be invoked with 2 parameters:

(pf :defined? 44)

And I added the ability to get the body of the original so that I can add an orElse function that will actually build a new PartialFunction that is the compilation of the composed patterns so that the patterns will be compiled more efficiently.

First toe in the water

Yep. I think Clojure is pretty powerful. With macros, I’ve added one of the most amazingly powerful language feature of Scala to Clojure in a few lines. The water feels pretty good so far.
 

Reference: Got my feet wet with Clojure from our JCG partner David Pollak at the DPP’s Blog blog.

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

Leave a Reply


6 × four =



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close