Clojure:具有递归的nullpointerException

Clojure: nullpointerexception with recursion

我正在创建一个将数字列表作为参数的重载函数(以及重载签名中的数字列表和单个数字)。 必须从此列表中找到并返回最大值。 我知道可用的"排序"方法会自动为您排序列表,但我尝试使用递归发现最高价值。 以下是我正在使用的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
32    (defn my-max
33      ([list]
34        (if (empty? list)
35          -1
36          (my-max (pop list) (first list))) ; recursive call
37        )
38      ([list high]
39        (if (empty? list) ; base case
40          high)
41        (if (> (first list) high)
42          (my-max (pop list) (first list)))
43        (my-max (pop list) high))
44      )
45    
46    (println (my-max '(1 2 3)))

如您所见,我对包含1、2和3的列表进行了硬编码,其中应该返回3。 运行代码时,我收到一个错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Exception in thread"main" java.lang.NullPointerException
    at clojure.lang.Numbers.ops(Numbers.java:942)
    at clojure.lang.Numbers.gt(Numbers.java:227)
    at user$my_max.invoke(HelloWorld.clj:41)
    at user$my_max.invoke(HelloWorld.clj:42)
    at user$my_max.invoke(HelloWorld.clj:42)
    at user$my_max.invoke(HelloWorld.clj:36)
    at user$eval2.invoke(HelloWorld.clj:46)
    at clojure.lang.Compiler.eval(Compiler.java:6619)
    at clojure.lang.Compiler.load(Compiler.java:7064)
    at clojure.lang.Compiler.loadFile(Compiler.java:7020)
    at clojure.main$load_script.invoke(main.clj:294)
    at clojure.main$script_opt.invoke(main.clj:356)
    at clojure.main$main.doInvoke(main.clj:440)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at clojure.lang.Var.invoke(Var.java:415)
    at clojure.lang.AFn.applyToHelper(AFn.java:161)
    at clojure.lang.Var.applyTo(Var.java:532)
    at clojure.main.main(main.java:37)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

在最后的递归调用中发生了此错误,其中从列表中"弹出"了3,并将其作为"高"传递回my-max,列表为空,并且:

1
(if (empty? list) ; line 39, base case

应该评估为true,但评估为false。 您对此问题有任何想法/解决方案吗?


该语句(第39-40行)没有任何作用。 无论其计算结果如何(highnil),都不会使用该值。 然后执行第41行,如果列表为空,则(first list)为nil,因此为空指针异常。


<函数只能比较数字,因此一种非常简单的方法是使用or来确保它们是数字。 同样,第二个和第三个if语句在错误的位置以)结尾。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
user> (defn my-max
       ([list]
         (if (empty? list)
          -1
           (my-max (pop list) (first list))))

       ([list high]
        (if (empty? list) ; base case
          high
         (if (> (or (first list) 0) (or high 0))
            (my-max (pop list) (first list))
            (my-max (pop list) high)))))
      #'user/my-max
      user> (println (my-max '(1 2 3)))
      3
      nil