Reputation: 5759
I have a problem providing an edge case for the following recursive function that searches hash maps and other similar key,value storage.
(def hashbrownies
{"Mary","Dave"
"Dave","Anne"
"Anne","Tim"})
current approach
(defn recursive-lookup
[key-lst search-func conditional]
(let [next-key (search-func (first key-lst))]
(if (conditional next-key)
(reverse key-lst)
(recur (cons next-key key-lst) search-func conditional))))
examples that are working
>> (recursive-lookup ["Mary"] #(hashbrownies %) (partial = nil))
=> ("Mary" "Dave" "Anne" "Tim")
>> (recursive-lookup ["Mary"] #(hashbrownies %) #(< (.length %) 4))
=> ("Mary" "Dave" "Anne")
Problematic:
>> (recursive-lookup ["Mary"] #(hashbrownies %) #(> (.length %) 4))
=> NullPointerException clojure.lang.Reflector.invokeNoArgInstanceMember (Reflector.java:296)
I can see what the problem is: as the condition can not be met, the function #(> (.length %) 4)
takes nil
(the last possible return value) as an argument. But being new to Clojure I am not sure how to cover for this. Is there an idiomatic way?
solution:
(defn recursive-lookup
[key-lst search-func conditional]
(let [next-key (search-func (first key-lst))]
(if (or (nil? next-key)
(conditional next-key))
(reverse key-lst)
(recur (cons next-key key-lst) search-func conditional))))
Upvotes: 2
Views: 1214
Reputation: 15434
You need to handle nil
in your conditional function. You can use fnil for that. fnil
replaces nil with some default value. So you can try:
(fnil #(> (.length %) 4) "")
If this conditional function receives nil
it replaces nil
with empty string "" and then call your function #(> (.length %) 4)
.
Also you can use count
instead .length
. Count returns 0 for nil:
(count "123") => 3
(count nil) => 0
Upvotes: 2