kfrisbie
kfrisbie

Reputation: 896

Clojure: nullpointerexception with recursion

I am creating an overloaded function that takes a list of numbers as a parameter (as well as a list of numbers and a single number in the overloaded signature). From this list the highest value must be found and returned. I am aware of the available "sort" method which automatically sorts the list for you but I am attempting to discover the highest value using recursion. Below is the code I am working with.

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)))

As you can see, I have hard-coded a list containing 1, 2, and 3 for which 3 should be returned. when running the code I receive an error:

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)

This error occurs on the final recursive call where 3 has been "popped" from the list and is passed back to my-max as "high" the list is empty and:

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

should evaluate true but is instead evaluating as false. Do you have any thoughts/solutions on this problem?

Upvotes: 1

Views: 1491

Answers (2)

Arthur Ulfeldt
Arthur Ulfeldt

Reputation: 91557

the < function can only compare numbers so a very straightforward approach is to use an or to ensure they are numbers. Also the second and third if statements had the closing ) in the wrong spots.

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

Upvotes: 4

Diego Basch
Diego Basch

Reputation: 13079

That statement (line 39-40) does nothing. No matter what it evaluates to (either high or nil), the value is not used. Then line 41 evaluates, and (first list) is nil if your list is empty, hence the null pointer exception.

Upvotes: 6

Related Questions