doto

added
1.0

ns
clojure.core

type
macro

(doto x & forms)

Evaluates x then calls all of the methods and functions with the
value of x supplied at the front of the given arguments.  The forms
are evaluated in order.  Returns x.

(doto (new java.util.HashMap) (.put "a" 1) (.put "b" 2))

                ;; Note that even though println returns nil, doto still returns the HashMap object
user> (doto (java.util.HashMap.)
            (.put "a" 1)
            (.put "b" 2)
            (println))
#<HashMap {b=2, a=1}>
{"b" 2, "a" 1}

;; Equivalent to
user> (def m (java.util.HashMap.))
user> (.put m "a" 1)
user> (.put m "b" 2)
user> m
{"a" 1, "b" 2}
user> (println m)
#object[java.util.HashMap 0x727fcc37 {a=1, b=2}]
            
                ;; quick demonstration of using a Collections function on the resulting ArrayList

user=> (def al (doto (java.util.ArrayList.) (.add 11) (.add 3) (.add 7)))
#'user/al
user=> al
#<ArrayList [11, 3, 7]>
user=> (java.util.Collections/sort al)
nil
user=> al
#<ArrayList [3, 7, 11]>
user=>
            
                ;; careful when calling 'dotimes' from within a 'doto' statement
user=> (doto (java.util.ArrayList.)
             (.add -2)
             (.add -1)
             (dotimes [i 3] (.add i)))
java.lang.IllegalArgumentException: dotimes requires a vector for its binding (NO_SOURCE_FILE:1)

; what has happened is that (java.util.ArrayList.) has secretly
; become the first argument to 'dotimes' and thus the exception
; informs us that it can't find the binding vector required for
; 'dotimes' to expand. You can cure this behaviour by simply using
; 'do' instead of 'doto' or by wrapping the call to 'dotimes' in
; a function. e.g:

;using 'let' with implicit 'do' instead of 'doto'
user=> (let [al (java.util.ArrayList.)]
         (.add al -2)
         (.add al -1)
         (dotimes [i 3] (.add al i))
         al);return the ArrayList
#<ArrayList [-2, -1, 0, 1, 2]>  ;exactly what we intended

;wrapping 'dotimes' in a function literal
user=>(doto (java.util.ArrayList.)
            (.add -2)
            (.add -1)
            (#(dotimes [i 3] (.add % i))))
#<ArrayList [-2, -1, 0, 1, 2]>  ;exactly what we intended again