Thursday, 15 August 2013

Clojure & Groovy: Exposing classes and methods

I'm trying to learn a new language: Clojure. It's really different than anything I've faced before...and I like it. But eventually I'd like to use it in some other apps coded in some other JVM languages such as Groovy ;)

In order to do that I'm using a Gradle project having different modules written in different JVM languages (Java, Scala, Clojure), and a Groovy module with Spock specs to test them all.

So I came up with the following Clojure file:

 (ns polyglot.clojure.sample
     (:gen-class              
      :name polyglot.clojure.sample.ClojureUtils
      :methods [
         [lowerit [String] String]
         #^{:static true} [upperit [String] String] 
       ]                      
     )
     (:require [clojure.string :as st])
  )   
        
  (defn -lowerit [this message]
    (st/lower-case message))                                                                                                                                
  
  (defn -upperit [message]   
    (st/upper-case message))

And then I was able to test it with the following Spock specification:

package polyglot
       
   import polyglot.clojure.sample.ClojureUtils
   import spock.lang.Specification
   
   class UseClojureGromGroovySpec extends Specification{
   
     def "Getting the message using cars"(){
       setup: "Creating a car"
        def car = new Car(brand:"Seat",model:"Leon")
        def util = new ClojureUtils()   
      when: "Initializing Clojure"
        def instanceMessage = util.lowerit(car.brand)
        def staticMessage = ClojureUtils.upperit(car.brand) 
      then: "The message should be like the following"
        instanceMessage == "seat"                                                                                                                           
        staticMessage == "SEAT"
    }
  }


What I have learnt so far is:

  •  File location:

(ns polyglot.clojure.sample

Points out to the clojure file. In this sample the file was /polyglot/clojure/sample.clj

  • Class name:

:name polyglot.clojure.sample.ClojureUtils

To be able to tell Clojure which Class to create, you have to specify the whole path, the "qualified name" so to speak. It's a little bit annoying to repeat the package when it could have been guessed from the namespace (ns attribute). But maybe I'm wrong and it's just that I don't know how to do it yet. Following the docs:

"The package-qualified name of the class to be generated"

  • Specifying instance methods:

:methods [
         [lowerit [String] String]
       ] 
This line exposes the method lowerit, method having an String as parameter. It should return an String as well. The method is implemented as:

(defn -lowerit [this message]
    (st/lower-case message))      

Notice that instance and static methods, both are implemented with an "-" symbol. Following the Clojure documentation :

"...Given a generated class org.mydomain.MyClass with a method named mymethod, gen-class will generate an implementation that looks for a function named by (str prefix mymethod) (default prefix: "-")..."

  • Specifying static methods:

:methods [         
         #^{:static true} [upperit [String] String] 
       ] 

The way of exposing static methods has a different syntax in the methods: block, but same way of implementing the method.

  (defn -upperit [message]   
    (st/upper-case message))

  • Importing third party libraries:


Because I first started using Clojure with the REPL I forgot some assumptions, such as REPL imports some namespaces by default. So I first try to implement lowerit as:

(defn -lowerit [this message]
    (clojure.string/lower-case message))  

That failed because the compiler could find the String type and even less the lower-case method. So after some search I found out how to do it. Before trying to use the String class I had to import it in the required: block (You can give the library an alias in order to use it through your implementation).
(:require [clojure.string :as st])

References:

2 comments:

  1. I have read your blog its very attractive and impressive. I like it your blog.

    Java Training in Chennai Core Java Training in Chennai Core Java Training in Chennai

    Java Online Training Java Online Training JavaEE Training in Chennai Java EE Training in Chennai

    ReplyDelete
  2. This is an awesome post.Really very informative and creative contents. These concept is a good way to enhance the knowledge.I like it and help me to development very well.Thank you for this brief explanation and very nice information.Well, got a good knowledge.
    PHP Training in Chennai

    ReplyDelete