Search code examples
exceptionclojuretry-catchfinally

Clojure exception not caught


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.


Solution

  • 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.