Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure: multiple let bindings

Tags:

clojure

In Java, I usually do this,

MyObject o1 = new MyObject();
o1.doSomething();
MyObject o2 = new MyObject();
o2.doWith(o1);
MyObject o3 = new MyObject();
o3.doWithBoth(o1, o2);

In Clojure, if I use let bindings, it might look like,

(let [o1 (create-obj)]
  (.doSomething o1)
  (let [o2 (create-obj)]
    (.doWith o2 o1)
    (let [o3 (create-obj)]
      (.doWithBoth o3 o1 o2))))

The code grows to the right hand side which is ugly and hard to maintain. Is there a better way to do this?

like image 361
woodings Avatar asked Feb 20 '14 17:02

woodings


1 Answers

(let [o1 (doto (create-obj) (.doSomething))
      o2 (doto (create-obj) (.doWith o1))
      o3 (doto (create-obj) (.doWithBoth o1 o2))]
  ...)

See (doc doto) for details.

(Update:) This works because in each case it is the newly created object that you're calling a method on. If instead you wanted to call a function / method with the newly created object passed in in an argument position other than the first one, you'd probably be best served by the _ trick described by noisesmith, though you could use doto with as->. The latter has the advantage of not introducing an unused local which would not be cleared (last time I checked Clojure only cleared locals that were actually referred to in subsequent code), but that's of course of no consequence if you're calling void-returning methods for side effect.

like image 167
Michał Marczyk Avatar answered Nov 15 '22 09:11

Michał Marczyk