Clojure: Forgetting the brackets
I’ve been playing around with macros over the last few days and while writing a simple one forgot to include the brackets to make it evaluate correctly:
(defmacro say-hello [person]
println "Hello" person)
This macro doesn’t even expand like I thought it would:
user=> (macroexpand-1 '(say-hello blah))
blah
That seemed a bit strange to me but I eventually realised that I’d missed off the brackets around 'println' and the arguments following it which would have resulted in 'println' being evaluated with those arguments.
I was a bit curious as to why that happened so I tried the following expression without any brackets to see what would happen:
user=> println "hello" "mark"
#<core$println__5440 clojure.core$println__5440@681ff4>
"mark"
"random"
It seems to just evaluate each thing individually and when we put this type of expression into a function definition the function will do the same thing but also return the last thing evaluated:
(defn say-hello [] println "hello" "mark")
user=> (say-hello)
"mark"
A. J. Lopez pointed out that this is quite like progn in other LISPs and is the same as doing the following:
user=> (do println "hello" "mark")
"mark"
do is defined as follows:
(do exprs*) Evaluates the expressions in order and returns the value of the last. If no expressions are supplied, returns nil.
The way to write a function which passes those two arguments to 'println' is of course to put brackets around the statement:
(defn say-hello [] (println "hello" "mark"))
user=> (say-hello)
hello mark
nil
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.