Clojure-为什么是;“做”;分组所需的语句?

Clojure-为什么是;“做”;分组所需的语句?,clojure,Clojure,我知道do块将按顺序执行语句并返回最后一个语句的值。我认为如果我不需要返回值,那么do就没有必要了。不考虑返回值,我不理解这两个函数的不同行为: 使用“do”: 没有“做”: 第二个示例中出现空指针的原因是什么 因为 (function argument) …是函数调用语法 ((println "a") (println "b")) …期望(println“a”)返回一个函数,它可以调用该函数,并将(println“b”)的结果作为其第一个参数传递 相反,(println“a”)没有返回值(

我知道do块将按顺序执行语句并返回最后一个语句的值。我认为如果我不需要返回值,那么do就没有必要了。不考虑返回值,我不理解这两个函数的不同行为:

使用“do”:

没有“做”:

第二个示例中出现空指针的原因是什么

因为

(function argument)
…是函数调用语法

((println "a") (println "b"))
…期望
(println“a”)
返回一个函数,它可以调用该函数,并将
(println“b”)
的结果作为其第一个参数传递

相反,
(println“a”)
没有返回值(返回nil,也称为null),尝试将此null值作为函数调用会导致NullPointerException


顺便说一句,这里惯用的做法是用
when
替换
if
,它将扩展为隐式包含
do

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

谢谢-这让我发疯了。顺便说一句——这是一个可怕的、可怕的做法,我为自己提到它感到羞愧,但是:
(如果是真的[(println“a”)(println“b”)])
会做一些与您所寻找的基本相似的事情(在构建向量的过程中评估向量的每个元素,从而产生副作用);因为这不是函数调用语法,所以不会发生空指针异常。我很高兴不能以错误的方式编写它-只是想弄清楚它为什么会以这种方式运行。@charlesduff,谢谢你的评论,包括前言。每个人都喜欢更深层次的理解,即使是通过“可怕的,可怕的”的说明“把戏。是的,很酷。我永远不会用它。
((println "a") (println "b"))
(defn x [] 
  (when true 
     (println "a")
     (println "b")))