Reputation: 1443
How can you get the partial results from a map when an exception happens during execution?
i.e
(let [numbers [3 3 0 3]
results (map #(/ 3 %) numbers)]
results)
and return:
[3 3]
Upvotes: 3
Views: 222
Reputation: 10514
Here's an approach using the cats library's exception monad:
(ns your-project.core
(:require [cats.monad.exception :as e]))
(let [numbers [3 3 0 3]
results (->> numbers
(map #(e/try-on (/ 3 %))) ; wrap division result in a try
(take-while e/success?) ; take values while successful
(mapv e/extract))] ; unwrap the values from the trys
results)
;; => [1 1]
And if you want to keep the values that come after the exception:
(let [numbers [3 3 0 3]
results (->> numbers
(map #(e/try-on (/ 3 %)))
(filter e/success?) ; filter all successful values
(mapv e/extract))]
results)
;; => [1 1 1]
Upvotes: 2
Reputation: 4713
Use keep
:
(let [numbers [3 3 0 3]]
(keep #(try
(/ 3 %)
(catch RuntimeException _ nil)) numbers))
Upvotes: 1
Reputation: 17849
since thrown exception unwinds the stack up to the place where exception is caught (in your case it goes up to the top level), you can't operate on result
after if. What you can do, is to manually put some value where the error was caught:
(let [numbers [3 3 0 3]
results (take-while number?
(map #(try
(/ 3 %)
(catch Throwable ex :error))
numbers))]
results)
Upvotes: 3
Reputation: 34850
For example:
(let [numbers [3 3 0 3]
results (map
#(try (/ 3 %)
(catch Exception e e))
numbers)]
(take-while #(not (instance? Exception %)) results))
Upvotes: 4