Clojure执行递归循环时出现Null pointer exception的原因是什么?
报错根因
- 核心错误是你在 cond 分支额外多套了一层括号,违反了 Clojure 的括号语义:Clojure 里括号不是普通的代码块分隔符,每一层括号都代表一次函数调用。
你写的((println x) (my-loop (- x 1)))会被解析为两步执行:
- 先执行
(println x),打印 x 后返回nil - 把第一步返回的
nil当做函数,传入(my-loop (- x 1))的求值结果作为参数调用nil本身不具备函数能力,调用就会直接抛出空指针异常。
- 你的写法不属于 Clojure 的合法多表达式写法:如果要在 cond 分支按顺序执行多个表达式,需要用
do包裹,do 会依次执行所有内部表达式,返回最后一个表达式的结果,符合你「先打印、再递归」的预期。
修复后的正常递归写法
(defn my-loop [x] (cond (> x 1) (do (println x) (my-loop (- x 1)))))
优化建议
你当前的写法是普通递归,当传入的初始值过大时会出现栈溢出问题,Clojure 原生支持尾递归优化,推荐用 loop/recur 改写:
(defn my-loop [x] (loop [n x] (when (> n 1) (println n) (recur (- n 1)))))
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

