Working with BatResult catch

Hi,

I am trying to run a function and catch exception using -
let res = BatResult.catch f t

According to documentation of catch - (** Execute a function and catch any exception as a result. This
function encapsulates code that could throw an exception and returns
that exception as a value.
@since 1.0
*)
it returns an exception as a value. How can I use this result in if else? I want to print success if the function is executed successfully without any exception or failure if there is any exception.

Try something like:

let res = BatResult f t in

match res with
| Ok _ -> print_endline "success"
| Bad _ -> print_endline "failure"

Actually, the return type of the function is ('b, exn) t. You should look at the definition of the type t in the BatResult module.

1 Like

To me, this idiom is much less useful now that we can match on exceptions.

Before:

match BatResult.catch f t with
| Ok _ -> print_endline "success"
| Bad _ -> print_endline "failure"

Nowadays:

match f t with
| exception _ -> print_endline "failure"
| _ -> print_endline "success"

which is simpler, nicer and likely faster.

Note that you are then sacrificing the compiler help to “force” you to handle the error branch, so it’s less safe.

1 Like

Any of the above approaches work for me but I want to do one more check. f returns true or false and I want to call some function if it returns true. How can I achieve that?

It depends on the type the function you want to call.

(* you call a function with side effect *)
let case1 f (g : 'a -> unit) x y = if f x then g y

(* you call a function of type 'a -> 'a *)
let case2 f (g: 'a -> 'a) x y = (if f x then g else fun x -> x) y

(* you call a function of type 'a -> 'b *)
let case3 f (g : 'a -> 'b) d x y = (if f x then g else fun _ -> d) y

For case 3, it might be easier to just do if f x then g y else d :wink: .

For case 2, do you happen to know if there’s any runtime cost from evaluating (fun x -> x) y?

Yes, and for case2 I could have written if f x then g y else y. But I choose a form one can use in a pipeline:

y |> a_function |> (if f x then g else fun x -> x) |> another_function

(* and with side effect *)
let (|-) x f = (f x : unit); x

y |> a_function |- (if debug then log else ignore) |> another_function

I don’t think so, the compiler should inline the application.

1 Like

Ah, that thing with the pipeline is cool.