Clojure exception not caught - exception

I am learning Clojure, and I would like to create a macro that works like Javas try-catch.
If an exception is thrown, the exception should be returned. Otherwise, the result should be returned.
Any resource that is open should also be closed in the finally section (Without the use of with-open). However, I do have one problem except not being caught that I don't know how to solve. Any help or suggestion would be appreciated!
Here is my code:
(defmacro my-try
([expression]
`(try
~expression
(catch Exception e# e#)
)
)
([[value variable] expression]
`(let [~value ~variable]
(try
~expression
(catch Exception e# e#)
(finally (if (instance? java.io.Closeable ~value) (.close ~value)))
)
)
)
)
When I try to open and read from a file that does not exist:
(def v (my-try [s (FileReader. (File. "missing-file"))] (. s read)))
(println v)
I get the following error:
Execution error (FileNotFoundException) at java.io.FileInputStream/open0 (FileInputStream.java:-2).
missing-file (Det går inte att hitta filen)
I suspect that this error message is an uncaught exception because (1) it does not follow the structure of other exceptions, and (2) if I change the format of the exception return, such as adding a specific message, the error message still does not change.
Any help in finding out what is at fault is highly appreciated!
Many thanks for considering my request.

In (let [~value ~variable], ~variable is evaluating to (FileReader. (File. "missing-file")), but that's outside of the try. It would become something like this:
(let [s (FileReader. (File. "missing-file"))]
(try
(. s read)
. . .
))
Move the let into the try, then expression into the let body.
Also, like in all languages, (catch Exception e# e#) is pretty much universally a bad idea. Throwing away errors becomes a nightmare once anything remotely non-trivial happens, since you've thrown out your only evidence of the problem.

Related

2to3 bug: tuple index out of range, fix_raise

I have found what looks like a not tested case to me. When trying to convert following code with 2to3:
def test(arg):
raise()
The execution stops ungracefully with no indication why, nor what file caused the problem, this is very annoying if you are trying to convert a whole folder of python 2 scripts. The following is thrown:
...
exc= exc.children[1].children[0].clone()
IndexError: tuple out of range
I am expecting to obtain a BadInput exception. Clearly, given the source code just above, it is expecting raise("something") and since there is no check that "children" inside the tuple of raise () is even present, this causes error.
Please correct me if I am wrong, of course raise() is incorrect, but this should not crash the execution, likewise the following:
def test(arg):
print 1.method()
Throws BadInput exception with a clear indication what happened.

Handling errors with purity in Clojure?

I'm working on a game using the big-bang style of programming where one defines the entire state as a single data structure and manages state change by swapping against a single atom.
In a game we cannot trust data sent by the client thus the server has to anticipate the possibility that some moves will be invalid and guard against it. When one writes a function for swapping world state it can start out pure; however, one must consider the possibility of invalid requests. I believe to effect the unhappy path in idiomatic Clojure one simply throws exceptions. So now functions that might have been pure are infected with side-effecting exceptions. Perhaps this is as it has to be.
(try
(swap! world update-game) ;possible exception here!
(catch Exception e
(>! err-chan e))
My aim is to defer side-effects until the last possible moment. I've hardly forayed into Haskell land but I know the concept of the Either monad. When one considers the happy and unhappy path one understands there are always these 2 possibilities. This has me thinking that swap! by itself is insufficient since it ignores the unhappy path. Here's the spirt of the idea:
(swap-either! err-chan world update-game) ;update-game returns either monad
Has the Clojure community adopted any more functional approaches for handling exceptions?
I tend to take a couple different approaches in cases like this. If the state is being updated in a single location I tend to go with:
(try
(swap! world update-game) ;possible exception here!
(catch Exception e
(>! err-chan e)
world) ;; <--- return the world unchanged
or if it's set in lots of places ad a watcher that throws the exception back to the place where swap! was called and doesn't change the state:
user> (def a (atom 1))
#'user/a
user> (add-watch a :im-a-test (fn [_ _ _ new-state]
(if (even? new-state)
(throw (IllegalStateException. "I don't like even numbers")))))
#object[clojure.lang.Atom 0x5c1dc37e {:status :ready, :val 1}]
user> (swap! a + 2)
3
user> (swap! a + 3)
IllegalStateException I don't like even numbers user/eval108260/fn--108261 (form-init8563497779572341831.clj:2)

How to catch the same exception for different functions efficiently?

The following works in REPL, in case the database is down I get the map back.
(try
(insert-table "db" "table" {:id 1 :text "text"})
(catch Exception e {:err "can't connect to database"}))
I though I could write a function that takes a db operation and wrap it with a (try).
(defn catch-db-connection-errors
[db_operation]
(try
(db_operation)
(catch Exception e {:err "can't connect to database"})))
It does not catch the exception though. I might just overlook something very simple...
The problem is that the form you pass in as an argument (e.g. (insert-table "db" "table" {:id 1 :text "text"})) is evaluated before the function is called, and the resulting value is passed into the function. To use another example, if you write (println (+ 1 1)), Clojure will first evaluate (+ 1 1) to get 2, and then will call (println 2). So if an exception is thrown in your DB code, it's before the catch-db-connection-errors function is called and thus outside the try form.
What you want is a macro, which thankfully is something Clojure is great at.
(defmacro catch-db-connection-errors [& db-operations]
`(try
~#db-operations
(catch Exception e {:err "can't connect to database"})))
This allows you to pass in however many database-handling forms you want and wraps them in your try-catch pair.
(Incidentally, you might want to catch something a little more specific than Exception, or else you could end up catching exceptions you don't intend do. But of course that's beside the point here.)

Getting the line number or full stack trace on exceptions in a gremlin-groovy script

I have a gremlin-groovy script that traverses a database which is incredibly noisy. There are lots of cases with missing edges or properties. When I assume an edge or property exists and it doesn't an exception is thrown I get a very simple output like this:
javax.script.ScriptException: java.util.IllegalFormatConversionException: d != java.lang.String
I'd like to make it so when the script encounters a fatal exception, as the one above, it provides a stack dump or at least a line number so I can debug where it happened, similar to how java can print a full stack trace on fatal exceptions.
Any suggestions on how to get a better dump?
I recommend using the Gremlin terminal for this.
gremlin$ ./gremlin.sh
\,,,/
(o o)
-----oOOo-(_)-oOOo-----
gremlin> a bad thing
No such property: bad for class: groovysh_evaluate
Display stack trace? [yN] y
groovy.lang.MissingPropertyException: No such property: bad for class: groovysh_evaluate
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:50)
If you don't have this luxury (e.g. via a REST server), then you may want to place some intelligent 'printlns' in your traversal.
my.long.traversal.sideEffect{println 'I am here'}.is.very.long

Erlang error handling philosophy - case vs throw

I'm writing a REST service in Erlang and need to verify the received data before passing it to other internal functions for further processing; in order to do that, I'm currently using nested case expressions like this:
case all_args_defined(Args) of
true ->
ActionSuccess = action(Args),
case ActionSuccess of
{ok, _} -> ...;
{fail, reason} -> {fail, reason}
end,
_ ->
{fail, "args not defined"}
end,
...
I realize this is kind of ugly, but this way I can provide detailed error messages. Additionally, I don't think the usual make it crash philosophy is applicable here - I don't want my REST service to crash and be restarted every time somebody throws invalid arguments at it.
However, I'm considering abandoning all those cases in favor of an umbrella try/catch block catching any badmatch errors - would this work?
fun() ->
true = all_args_defined(Args),
{ok, _} = action(Args).
%% somewhere else
catch fun().
Since what you want to achieve is error reporting, you should structure the thing around the execution of actions and reporting of the result. Perhaps something like this:
execute(Action, Args) ->
try
check_args(Args),
Result = action(Action, Args),
send_result(Result)
catch
throw:{fail, Reason} ->
report_error(Reason);
ExceptionClass:Term ->
%% catch-all for all other unexpected exceptions
Trace = erlang:get_stacktrace(),
report_error({crash, ExceptionClass, Term, Trace})
end.
%% all of these throw {fail, Reason} if they detect something fishy
%% and otherwise they return some value as result (or just crash)
action(foo, [X1, X2]) -> ...;
action(foo, Args) -> throw({fail, {bad_arity, foo, 2, Args}});
action(...) -> ...
%% this handles the formatting of all possible errors
report_error({bad_arity, Action, Arity, Args}) ->
send_error(io_lib:format("wrong number of arguments for ~w: "
"expected ~w, but got ~w",
[Action, Arity, length(Args)]));
report_error(...) -> ...;
report_error({crash, Class, Term, Trace}) ->
send_error(io_lib:format("internal error: "
"~w:~w~nstacktrace:~n~p~n",
[Class, Term, Trace])).
I've had this problem while developing an application that create users.
I first come with a solution like this:
insert() ->
try
check_1(), % the check functions throw an exception on error.
check_2(),
check_3(),
do_insert()
catch
throw:Error1 ->
handle_error_1();
throw:Error2 ->
handle_error_2();
_:Error ->
internal_error()
end.
The problem with this solution is that you lose the stack trace with the try...catch block.
Instead of this, a better solution is:
insert() ->
case catch execute() of
ok -> all_ok;
{FuncName, Error} ->
handle_error(FuncName, Error);
{'EXIT', Error} ->
internal_error(Error)
end.
execute() ->
check_1(), % the check functions throw an exception on error.
check_2(),
check_3(),
do_insert().
This way you have the full error stack on Error.
I have faced exactly the same question when writing my own REST services.
Let's start with the philosophy:
I like to think of my applications like a box. On the inside of the box are all of the parts I built and have direct control over. If something breaks here, it's my fault, it should crash, and I should read about it in an error log. On the edge of the box are all of the connection points to the outside world - these are not to be trusted. I avoid exception handling in the inside parts and use it as needed for the outer edge.
On similar projects I have worked on:
I usually have about a dozen checks on the user input. If something looks bad, I log it and return an error to the user. Having a stack trace isn't particularly meaningful to me - if the user forgot a parameter there is nothing in my code to hunt down and fix. I'd rather see a text log that says something like: “at 17:35, user X accessed path Y but was missing parameter Z”.
I organize my checks into functions that return ok or {error, string()}. The main function just iterates over the checks and returns ok if they all pass, otherwise it returns the first error, which is then logged. Inside of my check functions I use exception handling as needed because I can't possibly consider all of the ways users can screw up.
As suggested by my colleagues, you can alternatively have each check throw an exception instead of using a tuple.
As for your implementation, I think your idea of using a single exception handler is a good one if you only have the single check. If you end up needing more checks you may want to implement something like I described so that you can have more specific logging.