学习Clojure:一式三份的NullPoInterException



我正在使用Clojure官方网站上的初学者教程。

一个练习要求您进行以下操作:

7)定义一个函数triplicate,该功能采用另一个函数并调用3次,而无需任何参数。

我解决了如下:

(defn triplicate [f] ((f) (f) (f)))

问题在于,当使用NullPointerException时,我无法确定原因。

user=> (triplicate #(println "hello, world"))
hello, world
hello, world
hello, world
NullPointerException   user/triplicate (NO_SOURCE_FILE:115)

以下是pst的输出,如果有用:

user=> (pst)
NullPointerException
        user/triplicate (NO_SOURCE_FILE:145)
        user/triplicate (NO_SOURCE_FILE:145)
        user/eval376 (NO_SOURCE_FILE:146)
        user/eval376 (NO_SOURCE_FILE:146)
        clojure.lang.Compiler.eval (Compiler.java:7062)
        clojure.lang.Compiler.eval (Compiler.java:7025)
        clojure.core/eval (core.clj:3206)
        clojure.core/eval (core.clj:3202)
        clojure.main/repl/read-eval-print--8572/fn--8575 (main.clj:243)
        clojure.main/repl/read-eval-print--8572 (main.clj:243)
        clojure.main/repl/fn--8581 (main.clj:261)
        clojure.main/repl (main.clj:261)
nil

原因是什么?

imho,最清晰的解决方案是:

(do
  (f) 
  (f)
  (f))

评估多种表达式是do的唯一目的。如果您不希望剪切重复,最好的方法是:

(dotimes [i 3]
  (f))

使用矢量形式略微掩盖了重复目标,这意味着您需要(f)的返回值的3个。


脚注:我永远不会使用juxt,因为它是一个晦涩的功能,它会使大多数人挠头并跑到clojure备忘单以查找其定义。

(defn triplicate [f] ((f) (f) (f)))

返回: (nil nil nil)事物是 nil 不是函数。调用nil原因 nullpoInterException

您可以这样写:

(defn triplicate [f] [(f) (f) (f)])
;;=> [nil nil nil] which is fine, because you are keeping nils in a vector.

问题在此部分: ((f) (f) (f))

此表格表示:"呼叫函数f,然后将其结果称为函数,带有2个参数:f调用的结果和f调用的结果"

您可以使用[(f) (f) (f)]

修复它

或仅使用juxt

user> (def triplicate #(juxt % % %))
#'user/triplicate
user> ((triplicate #(println "hello")))
;;=> hello
;;=> hello
;;=> hello
[nil nil nil]

最新更新