A couple questions on design decisions or perhaps requesting new helper functions.
First, why does safe
return a fun instead of branching at the point of call to be used as normal. Right now at https://github.com/expede/exceptional/blob/master/lib/exceptional/safe.ex#L86 it is doing a large branching and an apply
call for every call. If instead if it (or a new name) were made a macro, then it could be fully inlined instead as a calling site, so you could do this for the examples in the README.md instead:
[1,2,3] |> safe(Enum.fetch!(1))
#=> 2
[1,2,3] |> safe(Enum.fetch!(999))
#=> %Enum.OutOfBoundsError{message: "out of bounds error"}
safe(Enum.fetch!([1,2,3], 999))
#=> %Enum.OutOfBoundsError{message: "out of bounds error"}
This could help readability and especially the usage while piping. Easily implementable as well.
Second, if_exception
and such have a similar setup, they take functions, where if they were macro's then the if_exception
last example could become:
ArgumentError.exception("error message")
|> if_exception do
%{message: msg} -> msg
else
value # if the default variable name was value, could always make it configurable
end
#=> "error message"
Also easily implementable, just stuff the do body in a case statement (maybe with a default to continue passing unmatched exceptions) and the else as normal. Could even optimize it so if the do body macro list has only one element and it is not keyed on a :->
then it could be a simple pass-through, so these would both work:
ArgumentError.exception("error message")
|> if_exception do
%{message: msg} -> msg
else
value
end
#=> "error message"
# Or this, if the passed in variable was named something like 'exc', could give an option to rename it too if you want:
ArgumentError.exception("error message")
|> if_exception do
handle_error(exc)
else
value
end
#=> "error message"
Or a configurable variable name could be used like:
ArgumentError.exception("error message")
|> if_exception myvar, do
%{message: msg} -> msg
else
myvar
end
#=> "error message"
# Or this, if the passed in variable was named something like 'exc', could give an option to rename it too if you want:
ArgumentError.exception("error message")
|> if_exception myvar, do
handle_error(myvar)
else
myvar
end
#=> "error message"
And of course the else clause could be optional if it is just a pass-through anyway.
And so forth on the other parts, just to help reduce the typing required and increasing readability by removing all sorts of things like .()
from many calls.