Home » JVM Languages » Clojure » Got my feet wet with Clojure

About David Pollak

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 our best selling eBooks for FREE!

1. JPA Mini Book

2. JVM Troubleshooting Guide

3. JUnit Tutorial for Unit Testing

4. Java Annotations Tutorial

5. Java Interview Questions

6. Spring Interview Questions

7. Android UI Design

and many more ....

 

Leave a Reply

Your email address will not be published. Required fields are marked *

*


Want to take your Java Skills to the next level?
Grab our programming books for FREE!
  • Save time by leveraging our field-tested solutions to common problems.
  • The books cover a wide range of topics, from JPA and JUnit, to JMeter and Android.
  • Each book comes as a standalone guide (with source code provided), so that you use it as reference.
Last Step ...

Where should we send the free eBooks?

Good Work!
To download the books, please verify your email address by following the instructions found on the email we just sent you.