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:

3 comments:

  1. Very Informative blog thank you for sharing. Keep sharing.

    Best software training institute in Chennai. Make your career development the best by learning software courses.

    informatica course in chennai
    power bi training in chennai
    rpa training in chennai

    ReplyDelete
  2. Thanks a lot very much for the high quality and results-oriented help.
    I won’t think twice to endorse your blog post to anybody who wants
    and needs support about this area.
    Best C# Course in Chennai
    best hadoop training in chennai

    ReplyDelete
  3. Grab the Oracle Training in Chennai from Infycle Technologies the best software training and placement center in Chennai which is providing technical software courses such as Data Science, Artificial Intelligence, Cyber Security, Big Data, Java, Hadoop, Selenium, Android, and iOS Development, DevOps, etc with 100% hands-on practical training.

    ReplyDelete