(define -ayalog '())

括弧に魅せられて道を外した名前のないプログラマ

何故 do ステートメントがグルーピングするのに必要なの?

まぁそうなるよね、という例。

(defn x [] 
  (if true 
     (do (println "a") (println "b"))))

=> (x) 
a
b
nil

do を使えば正常に動くけど、 do を抜かすと…

(defn x [] 
  (if true 
     ((println "a") (println "b"))))

=> (x) 
a
b
NullPointerException   user/x (NO_SOURCE_FILE:3)

NPE になる。なんで?という話。

回答にあるように、

((println "a") (println "b"))

先の (println "a") が評価されると nil が返り…

(nil (println "b"))

となってしまうのでお馴染みのように、開き括弧の次にくる先頭の S 式は「関数」として扱われるので NPE となるわけですね。

なのでまぁこういうときは when という別のイディオムが用意されているのでそちらを使ったほうが楽だしいいよという話。