bensentropy
bensentropy

Reputation: 1443

Get partial results of map after exception

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

Answers (4)

user2609980
user2609980

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

ClojureMostly
ClojureMostly

Reputation: 4713

Use keep:

(let [numbers [3 3 0 3]]
  (keep #(try 
          (/ 3 %)
          (catch RuntimeException _ nil)) numbers))

Upvotes: 1

leetwinski
leetwinski

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

Michiel Borkent
Michiel Borkent

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

Related Questions