6

我希望我的 clojure 程序有一个可以运行的脚本目录 - 这些脚本中的每一个都是我使用加载文件执行的 clojure 代码。这发生在未来,因此脚本在自己的线程中运行。

问题是我从未从脚本中看到任何错误消息。如果脚本失败,则无法知道出了什么问题。我认为这是因为未来的线程中没有异常处理。我可以将异常处理放入脚本中,如下所示,它可以工作:

;; script code    
(try

(println (/ 10 0))

(catch Exception e
  (println "Exception: " (.getMessage e))))

但是,我宁愿将异常处理放在加载文件周围,这样我就不必在脚本本身中进行异常处理:

(defn handleexes [f]
  (try
    (f)
    (catch Exception e
       (println "exception: " (.getMessage e)))))

(defn start-script-play [name]
  (println "starting script: " name)
  (let [f (future (handleexes (load-file (str "./scripts/" name))))]
    (swap! scripts (fn [s] (assoc s name f)))))

所以我在handlexes中调用加载文件。这不起作用 - 大多数情况下。当我运行一个包含自己的异常处理程序的脚本时,它确实有效,如上所述!没有脚本中的异常处理程序,什么都没有。奇怪。

好吧好吧,所以我的问题是这里到底发生了什么?

  • 期货确实没有处理异常吗?
  • 为什么在加载文件中发生异常时没有捕获到异常?
  • 在这种情况下如何捕获异常?
4

1 回答 1

7

您似乎从未取消引用(使用deref@)您在示例中生成的期货。

如果在未来中抛出异常,尝试取消引用该未来将导致java.util.concurrent.ExecutionException被抛出。此异常将包装将来抛出的任何内容。

(try
  (future (/ 10 0))
  "done"
  (catch Exception e
    (str "caught " e)))

;=> "done"


(try
  @(future (/ 10 0))
  "done"
  (catch Exception e
    (str "caught " e)))

;=> "caught java.util.concurrent.ExecutionException: java.lang.ArithmeticException: Divide by zero"
于 2013-04-24T17:59:30.150 回答