6

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".

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

11 Comments

What else do you want more? The code is as minimal as you can get.
I haven't read Barski's book, but CL does have arrays and hash tables. And I think that, at least at this point, Clojure might have a hard time matching the efficiency of the faster CL implementations.
But I would also say that Clojure's approach to data types is a lot more consistent than CL's. IMHO that part of Clojure is better designed than the corresponding bits of CL.
You're right that for a lot of things being ultra-efficient isn't all that important (though there are times when it is, and I'm glad to see that a lot of effort is going into making Clojure efficient.) I commented mainly because it's possible to get the wrong impression of CL from many books about it. You can program in a very list-oriented way in CL (and this will be pretty inefficient for some things,) but that's not the whole story. Production CL usually looks pretty different.
And I should add that I certainly agree with you that things like the literal syntax, and particularly the nice sequence abstraction in Clojure can indeed make many things a lot nicer in Clojure. I don't think anyone who has used CL a lot would associate it with the word "perfection" ;). CL has a lot of warts, and though many of them become pretty unimportant once you are experienced with the language, some remain annoying- very much so in some cases. But that said, for me at least, neither Clojure nor CL strictly dominates the other. CL has a lot to offer, despite the warts.
|
3

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..

1 Comment

Yes. And doc for doto has a similar example: (doto (new java.util.HashMap) (.put "a" 1) (.put "b" 2))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.