Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure-idiomatic way to initialize a Java object

I am trying to find a Clojure-idiomatic way to initialize a Java object. I have the following code:

(let [url-connection
      (let [url-conn (java.net.HttpURLConnection.)]
        (doto url-conn
          (.setDoInput true)
          ; more initialization on url-conn
          )
        url-conn)]
  ; use the url-connection
  )

but it seems very awkward.

What is a better way to create the HttpURLConnection object and initialize it before using it later in the code?

UPDATE: It seems that (doto ...) may come in handy here:

(let [url-connection
        (doto (java.net.HttpURLConnection.)
          (.setDoInput true)
          ; more initialization
          ))]
  ; use the url-connection
  )

According to the doto docs, it returns the value to which it is "doing".

like image 873
Ralph Avatar asked Nov 30 '10 14:11

Ralph


People also ask

Is clojure interoperable with Java?

Clojure solved this new language library problem by running on the JVM and having interoperability with Java classes. When you use Clojure, you can use Java classes and Java libraries. Clojure builds on the strength of the production-hardened and tested JVM and existing Java libraries.

Can clojure use Java libraries?

Clojure programs get compiled to Java bytecode and executed within a JVM process. Clojure programs also have access to Java libraries, and you can easily interact with them using Clojure's interop facilities.

How do you call a method in Clojure?

You can call a static method using (ClassName/methodName arguments) . However class is not a static method, it's a java keyword and you don't need it in clojure. To get the Class object associated with the String class, just use String . Save this answer.


2 Answers

As explained in the update to my question, here is the answer I came up with:

(let [url-connection
        (doto (java.net.HttpURLConnection.)
          (.setDoInput true)
          ; more initialization
          ))]
  ; use the url-connection
  )

Maybe someone can come up with a better one.

like image 183
Ralph Avatar answered Sep 22 '22 07:09

Ralph


Assuming that there is no constructor that accepts all the initialization parameters needed, then the way you did it is the only one I know.

The one thing you could do is wrap it all in a function like this:

(defn init-url-conn [doInput ...other params..] 
     (let [url-conn (java.net.HttpURLConnection.)]
        (doto url-conn
          (.setDoInput true)
          ; more initialization on url-conn
          )
        url-conn))

And call with:

(let [url-connection
      (let [url-conn (init-url-con true ...other params..)]
  ; use the url-connection
  )

However, this is specific per object and it is really useful only if you are initializing object of that class more than once.

Also you could write a macro that accepts all method names, and params and does this. But, when called, that call wouldn't be much shorter than your first example.

If anyone has a better idea, I'd like to see it, since I was asking myself the same just the other day..

like image 44
Goran Jovic Avatar answered Sep 21 '22 07:09

Goran Jovic