July 13, 2020

Clojure Goodness: Create And Initialize Object Based On Java Class With doto

It is very easy to work with Java classes in Clojure. If we want to create a new object based on a Java class and invoke methods to initialize the object directly we can use the doto macro. The first argument is an expression to create a new object and the rest of the arguments are functions to invoke methods on the newly created object. The object returned from the first argument is passed as first argument to the method invocations. The doto function returns the object that is created with the first argument.

In the following example code we use the doto function in several cases:

(ns mrhaki.core.doto
  (:require [clojure.test :refer [is]]))

;; With doto we can invoke functions on object returned
;; by the first argument, where the object is passed
;; before the given arguments.
(def sb (doto (StringBuilder.)
          (.append "one")
          (.append "two")

(is (= "owteno" (.toString sb)))

;; We can use functions in doto. For example
;; to create a value for the function invocation
;; on the type of the first argument.
(def sample (doto (new StringBuilder)
              (.append "{")
              (.append (apply str (repeat 10 "a")))
              (.append "}")))

(is (= "{aaaaaaaaaa}" (.toString sample)))

;; Type returned is the same as result of evaluation
;; of first argument, not the last argument.
(is (instance? StringBuilder (doto (StringBuilder.) (.toString))))

Written with Clojure 1.10.1.