【问题标题】:Assertions in Clojure applications enabled by default when running uberjar built with leiningen运行使用 leiningen 构建的 uberjar 时默认启用 Clojure 应用程序中的断言
【发布时间】:2018-08-10 17:28:43
【问题描述】:

在将 Clojure 应用程序作为 jar 运行时是否应该默认启用断言?

我们使用 leiningen 构建一个 uberjar,然后使用 java -jar ... 运行它,我刚刚发现 *assert* 是真的。

我找不到这个动态变量应该保持什么默认值,但我认为它会是假的(并且只在 REPL 开发环境中设置为真)。

这会导致与future 结合使用的一个令人讨厌的问题,其中前置条件断言错误导致未来线程终止,我们不知道发生了什么(因为我们只捕获了Exception 而不是Throwable)。

我浏览了clojure.lang.RT 的源代码,但我无法弄清楚*assert* var 设置为true 的位置。

我还在leinigen sample project 中找到了:global-vars 选项(How to disable Clojure assertions, including preconditions? 中提到了这一点)。 这看起来很合理,但我认为对于“生产”构建,我会自动获得 *assert* false

编辑:我错过了用于在RT.java 中初始化*assert* 变量的T 小东西(布尔真)。但是,仍然很好奇为什么这是默认设置以及关闭断言的推荐方法是什么(如果甚至推荐的话)。

【问题讨论】:

  • 好吧,我错过了用于在 RT.java 中初始化 *assert* 变量的 T 小东西(布尔值 true)。但是,仍然很好奇为什么这是默认设置以及关闭断言的推荐方式是什么(如果甚至推荐的话)。

标签: clojure


【解决方案1】:

从源代码来看,clojure.core/assert 是一个在编译时计算 *assert* 的宏:

(defmacro assert
  "Evaluates expr and throws an exception if it does not evaluate to
  logical true."
  {:added "1.0"}
  ([x]
     (when *assert*
       `(when-not ~x
          (throw (new AssertionError (str "Assert failed: " (pr-str '~x)))))))
  ([x message]
     (when *assert*
       `(when-not ~x
          (throw (new AssertionError (str "Assert failed: " ~message "\n" (pr-str '~x))))))))

这意味着alter-var-rootbinding 都不能改变assert 的行为,因为它们在运行时运行,在assert 已经评估了*assert* 之后。因此,project.clj 中的:global-vars 选项:

  :global-vars {*warn-on-reflection* false
                *assert* false }

是唯一可行的解​​决方案,因为它是在宏扩展之前进行评估的。使用此测试代码:

(dotest
  (spyxx *assert*)
  (assert false "Don't do that!")
  (println "past the assertion"))

我们得到结果:

----------------------------------
   Clojure 1.9.0    Java 10.0.1
----------------------------------

lein test tst.demo.core
*assert* => <#java.lang.Boolean false>
past the assertion

Ran 2 tests containing 0 assertions.
0 failures, 0 errors.
lein test  32.28s user 0.56s system 349% cpu 9.387 total

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-09
    • 1970-01-01
    • 2017-06-19
    • 2013-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多