Clojure 异常未捕获

rob*_*eng 2 exception finally clojure try-catch

我正在学习 Clojure,我想创建一个像 Javas try-catch 一样工作的宏。如果抛出异常,则应返回异常。否则,应返回结果。任何打开的资源也应该在 finally 部分关闭(不使用 with-open)。但是,我确实有一个问题,除了没有被抓住,我不知道如何解决。任何帮助或建议将不胜感激!

这是我的代码:

(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)))
        )
      )
   )
  )
Run Code Online (Sandbox Code Playgroud)

当我尝试打开并读取不存在的文件时:

(def v (my-try [s (FileReader. (File. "missing-file"))] (. s read)))
(println v)
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

Execution error (FileNotFoundException) at java.io.FileInputStream/open0 (FileInputStream.java:-2).
missing-file (Det går inte att hitta filen)
Run Code Online (Sandbox Code Playgroud)

我怀疑这个错误信息是一个未捕获的异常,因为(1)它没有遵循其他异常的结构,以及(2)如果我改变了异常返回的格式,比如添加了特定的消息,错误信息仍然如此没变。

非常感谢任何帮助找出问题所在!非常感谢您考虑我的要求。

Car*_*ate 5

(let [~value ~variable],~variable正在评估(FileReader. (File. "missing-file")),但那不在try. 它会变成这样:

(let [s (FileReader. (File. "missing-file"))]
    (try
        (. s read)
        . . .
    ))
Run Code Online (Sandbox Code Playgroud)

let移入try,然后expression移入let正文。


此外,就像在所有语言中一样,(catch Exception e# e#)几乎普遍都是一个坏主意。一旦发生任何非平凡的事情,扔掉错误就会变成一场噩梦,因为你已经抛出了问题的唯一证据。

  • 我仍然会去掉“除了”。拥有一个“finally”肯定有助于确保文件被关闭(这本质上就是Python的“with”所做的;有点),但是除非您确定自己能够正确处理,否则不应该进行异常处理错误。通过捕获错误并打印它,您可以防止调用堆栈上的函数代表您处理错误(因为它们可能比您下面的函数处于更好的恢复位置),并且您还丢弃了堆栈跟踪; 调试时的宝贵资源。 (2认同)