运行使用leiningen构建的uberjar时默认启用Clojure应用程序中的断言
当作为jar运行Clojure应用程序时,默认情况下是否应该启用断言 我们使用leiningen构建一个uberjar,然后运行使用leiningen构建的uberjar时默认启用Clojure应用程序中的断言,clojure,Clojure,当作为jar运行Clojure应用程序时,默认情况下是否应该启用断言 我们使用leiningen构建一个uberjar,然后java-jar…运行它,我刚刚发现*assert*是正确的 我找不到这个动态变量应该包含什么默认值,但我认为它应该是false(并且只在REPL开发环境中设置为true) 这与future一起导致了一个棘手的问题,前提断言错误导致future线程死亡,我们不知道发生了什么(因为我们只捕获了异常而不是可丢弃的) 我浏览了的源代码,但是我不知道*assert*var设置为tr
java-jar…
运行它,我刚刚发现*assert*
是正确的
我找不到这个动态变量应该包含什么默认值,但我认为它应该是false(并且只在REPL开发环境中设置为true)
这与future
一起导致了一个棘手的问题,前提断言错误导致future线程死亡,我们不知道发生了什么(因为我们只捕获了异常
而不是可丢弃的
)
我浏览了的源代码,但是我不知道*assert*
var设置为true的位置
我还在中找到了选项:global vars
(在中提到)。
这看起来很合理,但我认为对于“生产”构建,我会自动得到*assert*false
EDIT:我错过了
T
用来初始化*assert*
变量的RT.java
。但是,仍然很好奇为什么这是默认设置,以及关闭断言的建议方法(如果建议的话)。从源代码看,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 root
和binding
都不能更改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
----------------------------------
Clojure 1.9.0 Java 10.0.1
----------------------------------
lein test tst.demo.core
*断言*=>
言过其实
运行了包含0个断言的2个测试。
0次失败,0次错误。
lein测试32.28s用户0.56s系统349%cpu 9.387总计
从源代码看,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 root
和binding
都不能更改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
----------------------------------
Clojure 1.9.0 Java 10.0.1
----------------------------------
lein test tst.demo.core
*断言*=>
言过其实
运行了包含0个断言的2个测试。
0次失败,0次错误。
lein测试32.28s用户0.56s系统349%cpu 9.387总计
Ok,我错过了RT.java
中用来初始化*assert*
变量的T
小东西(布尔值true)。但是,仍然很好奇为什么这是默认值,以及关闭断言的建议方法(如果建议的话)。好吧,我错过了用于初始化*assert*
变量的RT.java
中的T
小东西(布尔真)。但是,仍然很好奇为什么这是默认设置,以及关闭断言的建议方法是什么(如果建议的话)。