Clojure - Exception handling - exception

I want my web page to behave as expected when there's an exception by a function, now (openid/validate r) doesn't return a value unless a user is redirected from /login. But since this is a home page, I want it also be visible without a problem. So I wonder why the "if" there doesn't work as I expect?
java.lang.NullPointerException at /
NullPointerException [no message]
tfs.routes.home/[fn]
home.clj, line 48
--> line 48
(if (openid/validate r)
So instead of NullPointerException, I expected (home-page r) to execute.
(openid/validate r) fails in itself and causes an exception because its not fed by the needed parameters, is that the cause? If so how can I fix it? If not, why my (home-page r) function doesn't get executed?
(if (openid/validate r)
(show-response (:params r))
(home-page r))

So I did this with try/catch, it seems to be working fine now. Just not sure if I still should use the if there or not since I'm using try/catch?
(GET "/" [:as r] (home-page r)
(try (if (openid/validate r)
(show-response (:params r))
(home-page r))
(catch Exception e (home-page r))))

Related

Emacs Lisp variables scoping

Let's consider the following functions:
(defun test (x)
"X."
(request "http://example.com"
:parser 'json-read
:complete (cl-function
(lambda (&key response &allow-other-keys)
(message "%s" x)))))
(defun test2 (x)
"X."
(funcall (cl-function (lambda (z) (message "%s" z))) x))
Calling (test2 3) Works fine and produces the desired message. Calling (test 3), however, fails with the following error:
error in process sentinel: let*: Symbol’s value as variable is void: x
error in process sentinel: Symbol’s value as variable is void: x
My guess is that request is a macro doing something weird to variable scoping. Unfortunately, the documentation does not mention anything like this. Is there a way to overcome that?
request is probably an ordinary function.
The problem is that the lambda you pass to it is not called immediately but is
saved and called later:
(defun make-function (x)
(lambda () (message "received %s" x)))
=> make-function
(defconst f (make-function 3))
=> f
(funcall f)
=> Lisp error: (void-variable x)
x that make-function bound no longer exists.
This is because by default Emacs uses dynamic binding and you need lexical binding to get the behavior you want.
If you add
;; -*- lexical-binding:t -*-
to the first line of your file, it will be compiled with lexical binding and
the code above will produce the message received 3 instead of an error.

How to catch and rethrow an exception

I have a clojure function which calls another function to update the database.
(^{PUT true
Path "/{id}"
Produces ["application/json"]
Consumes ["application/json"]
ApiOperation {:value "Update" :notes ""}}
updateFeedback [this
^{PathParam "id"} id
body]
(require 'com.xx.x.xx.xx.xx-response)
(let [doc (json/read-json body)]
(if-let [valid-doc (validate doc)]
(try+
(->>
(assoc valid-doc :modificationDate (Utilities/getCurrentDate))
(couch/update-document dbs/xx-db)
(core/ok-response))
(catch java.io.IOException ex
(log/error "line num 197"))
(catch java.lang.Exception ex
(log/error "line num 200"))))))
The update-document function throws an exception. I would like to throw it back to the caller -- in this case updateFeedback so that the content in the catch block gets executed. For some reason, clojure logs the exception and the catch block in the caller never executes.
To verify I wrapped the code in the update-document function in a try catch block. There the catch block got executed.
How do I add a throws clause to the function?
Update: I have updated the function. Apologies for the syntax issues. I have updated the code we are using. I am not familiar with clojure. This is a code which we inherited and we are asked to fix a bug. Any pointers would be really helpful.
If you are trying to catch and then re-throw an exception you can do something like this:
(defn throwing-function
[]
(/ 7 0))
(defn catching-function
[]
(try
(throwing-function)
(catch Exception e
(println "Caught exception:" e)
(println "Re-throwing ...")
(throw e))))

Handle exception with clojure

On my clojure script I have got a try/catch that should handle exception
datalayer (try (parse-dl line)
(catch Exception e []))
But when I execute my code i'have got an exception:
Caused by: com.fasterxml.jackson.core.JsonParseException: Unexpected end-of-input: was expecting closing quote for a string value
What should I do to ignore those exceptions
this is just a guess because I don't know what parse-dl does, though there is a common pattern that causes Exceptions to be thrown outside the try catch where they are expected. If you start with some lazy code in a try catch:
user> (def my-data [1 2 3])
#'user/my-data
user> (defn my-work [data]
(throw (Exception. "hi")))
#'user/my-work
user> (try
(map my-work my-data)
(catch Exception e []))
Exception hi user/my-work (form-init3735135586498578464.clj:1)
Because map returns a lazy sequence, the actual computation occurs when the REPL prints the result, so the exception is thrown after the try catch block has returned. To fix the lazy-bug, wrap the map in a call to doall
user> (try
(doall (map my-work my-data))
(catch Exception e []))
[]
Another related lazy-bug occurs when a lazy sequence is returned from a with-open expression so that by the time the computation takes place the file was already closed by the with-open macro.

Rethrowing SomeException

The function forkFinally requires you to write a handler against SomeException. What I need is a way to rethrow the unhandled exceptions. Here's a sample code, which fails to compile because on the last line the e is ambiguous:
finallyHandler :: Either SomeException () -> IO ()
finallyHandler z = case z of
Right () -> cleanUp
Left someE | Just ThreadKilled <- fromException someE -> cleanUp
| Just e <- fromException someE -> cleanUp >> throwIO e
Of course the first thing coming to mind is to simply throw the someE instead, i.e.:
...
| otherwise -> cleanUp >> throwIO someE
And indeed it will compile, but then it will result in wrapping of all of incoming exceptions in SomeException when they pass this handler. This just can't be right. And what if I have multiple such handlers down the stack - I'll get a trash like SomeException $ SomeException $ RealException.
Am I missing something? What's the proper way of handling this situation?
Are you seeing unexpected behavior? If you haven't actually triggered something undersirable then I think you are worrying over nothing. A quick test indicates that the "right thing" is already being done. That is, if you catch then throw a SomeException you can still catch the original exception. Here's an example using ErrorCall as the underlying exception:
> catch (catch (throw (SomeException (ErrorCall "hi")))
(\(e::SomeException) -> throw e))
(\(ErrorCall e) -> putStrLn e)
hi
This is because the definition of throw uses toException and toException is identity for SomeException:
instance Exception SomeException where
toException se = se
fromException = Just

How do I correctly use Control.Exception.catch in Haskell?

Can someone please explain the difference between the behavior in ghci of the following to lines:
catch (return $ head []) $ \(e :: SomeException) -> return "good message"
returns
"*** Exception: Prelude.head: empty list
but
catch (print $ head []) $ \(e :: SomeException) -> print "good message"
returns
"good message"
Why isn't the first case catching the exception? Why are they different? And why does the first case put a double quote before the exception message?
Thanks.
Let's examine what happens in the first case:
catch (return $ head []) $ \(e :: SomeException) -> return "good message"
You create thunk head [] which is returned as an IO action. This thunk doesn't throw any exception, because it isn't evaluated, so the whole call catch (return $ head []) $ ... (which is of type IO String) produces the String thunk without an exception. The exception occurs only when ghci tries to print the result afterwards. If you tried
catch (return $ head []) $ \(e :: SomeException) -> return "good message"
>> return ()
instead, no exception would have been printed.
This is also the reason why you get _"* Exception: Prelude.head: empty list_. GHCi starts to print the string, which starts with ". Then it tries to evaluate the string, which results in an exception, and this is printed out.
Try replacing return with evaluate (which forces its argument to WHNF) as
catch (evaluate $ head []) $ \(e :: SomeException) -> return "good message"
then you'll force the thunk to evaluate inside catch which will throw the exception and let the handler intercept it.
In the other case
catch (print $ head []) $ \(e :: SomeException) -> print "good message"
the exception occurs inside the catch part when print tries to examine head [] and so it is caught by the handler.
Update: As you suggest, a good thing is to force the value, preferably to its full normal form. This way, you ensure that there are no "surprises" waiting for you in lazy thunks. This is a good thing anyway, for example you can get hard-to-find problems if your thread returns an unevaluated thunk and it is actually evaluated in another, unsuspecting thread.
Module Control.Exception already has evaluate, which forces a thunk into its WHNF. We can easily augment it to force it to its full NF:
import Control.DeepSeq
import Control.Seq
import Control.Exception
import Control.Monad
toNF :: (NFData a) => a -> IO a
toNF = evaluate . withStrategy rdeepseq
Using this, we can create a strict variant of catch that forces a given action to its NF:
strictCatch :: (NFData a, Exception e) => IO a -> (e -> IO a) -> IO a
strictCatch = catch . (toNF =<<)
This way, we are sure that the returned value is fully evaluated, so we won't get any exceptions when examining it. You can verify that if you use strictCatch instead of catch in your first example, it works as expected.
return $ head []
wraps head [] in an IO action (because catch has an IO type, otherwise it would be any monad) and returns it. There is nothing caught because there is no error. head [] itself is not evaluated at that point, thanks to lazyness, but only returned.
So, return only adds a layer of wrapping, and the result of your whole catch expression is head [], quite valid, unevaluated. Only when GHCi or your program actually try to use that value at some later point, it will be evaluated and the empty list error is thrown - at a different point, however.
print $ head []
on the other hand immediately evaluates head [], yielding an error which is subsequently caught.
You can also see the difference in GHCi:
Prelude> :t head []
head [] :: a
Prelude> :t return $ head []
return $ head [] :: Monad m => m a
Prelude> :t print $ head []
print $ head [] :: IO ()
Prelude> return $ head [] -- no error here!
Prelude> print $ head []
*** Exception: Prelude.head: empty list
To avoid that, you can perhaps just force the value:
Prelude> let x = head [] in x `seq` return x
*** Exception: Prelude.head: empty list
GHCi works in the IO monad and return for IO doesn't force its argument. So return $ head [] doesn't throw any exception, and an exception that isn't thrown can't be caught. Printing the result afterwards throws an exception, but this exception isn't in the scope of catch anymore.
The type IO a has two parts:
The structure, the part that goes out and performs side-effects. This is represented by IO.
The result, the pure value held inside. This is represented by a.
The catch function only catches exceptions when they break through the IO structure.
In the first example, you call print on the value. Since printing a value requires performing I/O with it, any exceptions raised within the value end up in the structure itself. So catch intercepts the exception and all is well.
On the other hand, return does not inspect its argument. In fact, you are guaranteed by the monad laws that calling return does not affect the structure at all. So your value simply passes right through.
So if your code isn't affected by the exception, then where is the error message coming from? The answer is, surprisingly, outside your code. GHCi implicitly tries to print every expression that is passed to it. But by then, we are already outside the scope of the catch, hence the error message you see.