Clojure NullPointerException with loop and repeat
I am new to Clojure and I am currently sticking with the code below which throws a NullPointerException when I run it like this:
(mapset inc [1 1 2 2])
(defn mapset
[fn v]
(loop [[head & tail] v result-set (hash-set)]
(if (nil? head)
result-set)
(conj result-set (fn head))
(recur tail result-set)))
When I print the result set in the if block, it prints an empty set, whereas I expect a set like this: # {2 3}
After an attempt to interpret the stacktrace I guess NullPointerException has some relationship to the next line
(conj result-set (fn head))
. The stop trace and the fact that the result set is empty leads me to believe that the inc operation was somehow called with zero as its input.
I'm glad I explained the reason for this error
The specified (shortend) stacktrace looks like this:
java.lang.NullPointerException
Numbers.java: 1013 clojure.lang.Numbers/ops
Numbers.java: 112 clojure.lang.Numbers/inc
core.clj: 908 clojure.core/inc
core.clj: 903 clojure.core/inc
REPL: 6 user/mapset
REPL: 1 user/mapset
source to share
Made small changes:
(defn mapset [f v]
(loop [[head & tail] v
result-set (hash-set)]
(if (nil? head)
result-set
(let [res (f head)]
(recur tail (conj result-set res))))))
(defn x-1 []
(mapset inc [1 1 2 2]))
(x-1)
;;=> #{3 2}
So now mapset
will call a function f
on each of your inputs from v
, then put the result of that call into the hash-set
one that was created at the beginning.
The problem was your operator's flow control logic if
. The flow of execution continued after if
. This way the function fn
(which I renamed to f
, rather than leaving it as a macro name) was called even when it head
was nil
, which was not what you intended.
As originally pointed out if
(which would have been clearer it was when
) did nothing useful. But as soon as I realized what you want to have if
, but closed the pack too early, then the answer fell into place. Hence, minor changes fixed the problem - your logic was sound and the patched function just worked.
source to share