clojure/Java Interop: The doto macro
I recently wrote about some code I’ve been playing with to import neo4j spatial data and while looking to simplify the code I came across the http://clojure.org/java_interop#Java Interop-The Dot special form-(doto instance-expr (instanceMethodName-symbol args*)*) macro.
The doto macro allows us to chain method calls on an initial object and then returns the resulting object. e.g.
(doto (new java.util.HashMap) (.put "a" 1) (.put "b" 2))
-> {a=1, b=2}
In our case this comes in quite useful in the function used to create a stadium node which initially reads like this:~ ~lisp (defn create-stadium-node [db line] (let [stadium-node (.. db createNode)] (.. stadium-node (setProperty "wkt" (format "POINT(%s %s)" (:long line) (:lat line)))) (.. stadium-node (setProperty "name" (:stadium line))) stadium-node)) ~
Here we first create a node, set a couple of properties on the node and then return it.
Using the macro it would read like this: ~lisp (defn create-stadium-node [db line] (doto (.. db createNode) (.setProperty "wkt" (format "POINT(%s %s)" (:long line) (:lat line))) (.setProperty "name" (:stadium line)))) ~
We can also use it to close the transaction at the end of our function although we don’t actually have a need for the transaction object which gets returned:~ ~lisp # the end of our main function (.. tx success) (.. tx finish) ~
...becomes… ~lisp (doto tx (.success) (.finish)) ~
As far as I can tell this is pretty similar in functionality to the http://blog.moertel.com/posts/2007-02-07-ruby-1-9-gets-handy-new-method-object-tap.html function in Ruby: ~ruby {}.tap { |x| x[:a] = 1; x[:b] = 2 } => {:a=>1, :b=>2} ~
Either way it’s a pretty neat way of simplifying code.
About the author
I'm currently working on short form content at ClickHouse. I publish short 5 minute videos showing how to solve data problems on YouTube @LearnDataWithMark. I previously worked on graph analytics at Neo4j, where I also co-authored the O'Reilly Graph Algorithms Book with Amy Hodler.