【问题标题】:Custom Exceptions in Clojure?Clojure 中的自定义异常?
【发布时间】:2011-04-19 14:49:56
【问题描述】:

我一直在尝试在 Clojure 中创建一个用户定义的异常,并且遇到了各种各样的问题。我尝试了这里列出的方法:

http://en.wikibooks.org/wiki/Clojure_Programming/Concepts#User-Defined_Exceptions

(gen-and-load-class 'user.MyException :extends Exception)

但这似乎在 Clojure 1.2 中不起作用(或者我做错了什么......)。我的环境是 Clojure 1.2、Emacs 和 lein swank。

感谢您的帮助!

【问题讨论】:

    标签: exception-handling clojure


    【解决方案1】:

    除了生成自定义类之外,还有两种更简单的方法来使用自定义异常:

    1. 使用slingshot - 这提供了自定义的throw+ 和catch+ 宏,让您可以抛出和捕获任何对象以及异常。

    2. 在 clojure 1.4 及更高版本中,您可以使用 clojure.core/ex-info 和 clojure.core/ex-data 生成并捕获 clojure.lang.ExceptionInfo 类,该类包装了消息和数据映射。

    使用起来很简单:

    (throw (ex-info "My hovercraft is full of eels"
                    {:type :python-exception, :cause :eels}))
    
    (try (...)
      (catch clojure.lang.ExceptionInfo e
        (if (= :eels (-> e ex-data :cause))
          (println "beware the shrieking eels!")
          (println "???"))))
    

    或者在 midje 测试中:

    (fact "should throw some eels"
        (...) 
        => (throws clojure.lang.ExceptionInfo
              #(= :eels (-> % ex-data :cause))))
    

    【讨论】:

    【解决方案2】:

    FWIW,除非您出于互操作原因创建自定义异常,否则您可能需要考虑改用 clojure.contrib.condition。它带有一个预编译的自定义异常,您可以使用它的 API 捎带自定义数据。我已经能够通过使用它来避免创建许多自定义异常。文档在这里: http://clojure.github.com/clojure-contrib/condition-api.html

    【讨论】:

    • clojure-contrib 现已弃用。
    【解决方案3】:

    制作一个文件src/user/MyException.clj(其中src在CLASSPATH上)包含:

    (ns user.MyException
      (:gen-class :extends java.lang.Exception))
    

    在 REPL 中检查 *compile-path* 的值。确保此目录存在并且位于CLASSPATH。如果目录不存在,则创建该目录; Clojure 不会为您这样做。

    user> *compile-path*
    "/home/user/foo/target/classes/"
    user> (System/getProperty "java.class.path")
    ".......:/home/user/foo/target/classes/:......."
    

    编译你的类:

    user> (compile 'user.MyException)
    user.MyException
    

    如果有效,在*compile-path* 你现在应该有类似这样的文件:

    /home/user/foo/target/
    /home/user/foo/target/classes
    /home/user/foo/target/classes/user
    /home/user/foo/target/classes/user/MyException.class
    /home/user/foo/target/classes/user/MyException__init.class
    /home/user/foo/target/classes/user/MyException$loading__4410__auto__.class
    

    重新启动 Clojure REPL / JVM 以加载这些类。同样,确保这些新的类文件在CLASSPATH 上。现在你应该可以使用你的类了:

    user> (user.MyException.)
    #<MyException user.MyException>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-09
      • 1970-01-01
      • 1970-01-01
      • 2012-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多