学习Clojure:一式三份的NullPointerException

问题描述 投票:2回答:3

我正在Clojure官方网站上使用beginner tutorial

一项练习要求您执行以下操作:

7)定义一个函数triplicate,它接受另一个函数并调用它三次,没有任何参数。

我解决了以下问题:

(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

原因是什么?

clojure
3个回答
2
投票

恕我直言,最清晰的解决方案是:

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

评估多个表达式是do的唯一目的。如果你不想重复切割,最好的方法是:

(dotimes [i 3]
  (f))

使用矢量形式会略微模糊重复目标,并暗示您需要3个(f)的返回值。


脚注:我永远不会使用juxt,因为它是一个不起眼的功能,会让大多数人挠头并跑到The Clojure CheatSheet查找其定义。


4
投票

问题出在这一部分:((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]

3
投票
(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.
© www.soinside.com 2019 - 2024. All rights reserved.