以下对cl-format的调用导致Java级别空指针异常。
(cl-format false "
~@")
当然,那个代码示例相当没有意义。引发这个最小测试用例的实际示例如下。
(cl-format false "~&~
item=~A~@
transitions=~A~@
lhs=~A~@
rhs=~A~@"
1
2
3
4
)
据我所知,问题似乎出在与最后的~@
处理上,clojure代码似乎(我猜)会解构extract-params
返回的nil
值
在cl_format.clj中的compile-directive
函数中。
(defn- compile-directive [s offset]
(let [[raw-params [rest offset]] (extract-params s offset)
[_ [rest offset flags]] (extract-flags rest offset)
directive (first rest)
def (get directive-table (Character/toUpperCase ^Character directive))
params (if def (map-params def (map translate-param raw-params) flags offset))]
(if (not directive)
(format-error "Format string ended in the middle of a directive" offset))
(if (not def)
(format-error (str "Directive \"" directive "\" is undefined") offset))
[(struct compiled-directive ((:generator-fn def) params offset) def params offset)
(let [remainder (subs rest 1)
offset (inc offset)
trim? (and (= \newline (:directive def))
(not (:colon params)))
trim-count (if trim? (prefix-count remainder [\space \tab]) 0)
remainder (subs remainder trim-count)
offset (+ offset trim-count)]
[remainder offset])]))
以下是看到的堆栈跟踪。
1. Unhandled java.lang.NullPointerException
(No message)
cl_format.clj: 1717 clojure.pprint/compile-directive
cl_format.clj: 1861 clojure.pprint/compile-format/fn
AFn.java: 154 clojure.lang.AFn/applyToHelper
AFn.java: 144 clojure.lang.AFn/applyTo
core.clj: 665 clojure.core/apply
utilities.clj: 37 clojure.pprint/consume
cl_format.clj: 1845 clojure.pprint/compile-format
cl_format.clj: 1845 clojure.pprint/compile-format
cl_format.clj: 62 clojure.pprint/cl-format
cl_format.clj: 27 clojure.pprint/cl-format
RestFn.java: 521 clojure.lang.RestFn/invoke
REPL: 1391 clojure-rte.rte-core/eval24978
REPL: 1391 clojure-rte.rte-core/eval24978
Compiler.java: 7176 clojure.lang.Compiler/eval
Compiler.java: 7131 clojure.lang.Compiler/eval
core.clj: 3214 clojure.core/eval
core.clj: 3210 clojure.core/eval
interruptible_eval.clj: 87 nrepl.middleware.interruptible-eval/evaluate/fn/fn
AFn.java: 152 clojure.lang.AFn/applyToHelper
AFn.java: 144 clojure.lang.AFn/applyTo
core.clj: 665 clojure.core/apply
core.clj: 1973 clojure.core/with-bindings*
core.clj: 1973 clojure.core/with-bindings*
RestFn.java: 425 clojure.lang.RestFn/invoke
interruptible_eval.clj: 87 nrepl.middleware.interruptible-eval/evaluate/fn
main.clj: 414 clojure.main/repl/read-eval-print/fn
main.clj: 414 clojure.main/repl/read-eval-print
main.clj: 435 clojure.main/repl/fn
main.clj: 435 clojure.main/repl
main.clj: 345 clojure.main/repl
RestFn.java: 1523 clojure.lang.RestFn/invoke
interruptible_eval.clj: 84 nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj: 56 nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj: 152 nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
AFn.java: 22 clojure.lang.AFn/run
session.clj: 202 nrepl.middleware.session/session-exec/main-loop/fn
session.clj: 201 nrepl.middleware.session/session-exec/main-loop
AFn.java: 22 clojure.lang.AFn/run
Thread.java: 834 java.lang.Thread/run