2024年 Clojure 状态调查!中分享您的想法。

欢迎!有关如何使用本网站的更多信息,请参阅关于页面。

+4
Clojure
编辑

目前 `clojure.core/*assert*` 的默认值是 true

这对库的创建者和使用者都有一些意义。

作为库的创建者,您不能随意在各个地方添加断言来帮助您进行开发/测试,因为这会导致大多数用户在生产环境中付出性能代价,因为他们将与 *asserts* 启用运行。

作为库的使用者,由于您不知道哪些库正在使用断言,您必须始终记住在必要时禁用它们。

实际上,在 Clojure 中全局禁用这些断言并不容易,因为 `assert` 是一个宏,它会检查 `*assert*`,变量的值需要在加载任何命名空间之前设置。

相反,Java 默认禁用所有断言,因此库的创建者不必为此担忧,而消费者可以在开发时间通过提供 `java -ea`(启用断言)来显式启用它们。

鉴于我猜想更改 `*assert*` 的默认值可能因向后兼容性问题而变得复杂,也许可以添加一个像 Rust 中的 `debug-assert` 一样,默认不启用的断言。

在我看来,重要的是要有一个简单的不变量检查指令,我们知道默认情况下它不会影响性能,这样我们就可以在不影响生产性能的情况下默认情况下使代码库更安全地进行测试和开发。

其他两个选项是更好默认值的 assert,一个是 `false`,另一个是 `java.lang.Class desiredAssertionStatus()` 的值,该值似乎根据是否提供了 `-ea` 标志返回真/假,默认情况下也将是 `false`。但是,由于大多数 Clojure 用户已经依赖默认情况下 assert 为 true,这可能不是一个好选择。

我看到了像debug-assert这样的添加的好处,使得库的开发人员可以在测试时选择启用(而库的用户也可以选择启用测试),而应用程序的开发人员可以使用assert或选择不启用,如果他们不想在生产环境中激活的话。

编辑了
对于 `debug-assert` 我觉得非常好。我相信绝对有必要有一个通用的、可靠的向库中添加断言的方式,这样就可以在这种绝对的确定性下添加断言,即在任何情况下都不会默认出现在任何人的生产构建中,除非用户明确选择加入。

一些检查在开发和测试期间是非常需要的,但在默认的生产环境中却过于昂贵,而另一些在生产中可能是必要的,以避免潜在的数据库损坏和复杂的传播故障。

库的作者应该有权选择在哪里划这条线,这不应该是全有或全无的选择,并且作者在开发/测试过程中不应该因为担心可能将过于严格的、昂贵到不可承受的检查强加给下游消费者而受到限制。

当然,区分仅用于开发/测试和生产的断言对应用程序开发人员也是非常有用的。

顺便提一下,在Clojurians Slack上的讨论线程
https://app.slack.com/client/T03RZGPFR/C03S1KBA2

编辑

我建议将标题改为类似“将`debug-assert`作为一个单独的、默认关闭的、昂贵的dev/test-only操作”的内容,以明确这里提出的建议。
我将把https://docs.clojure.org/clojure.spec.alpha/assert添加到对话中,因为这个在默认情况下是关闭的(在运行时,但可以在运行时用于测试,也可以在编译时完全禁用)。

推荐将其作为库方法的问题在于,你会因为Spec失败而处于被动位置,因为没有像常规assert一样自定义消息选项。
by
如果我的理解正确,你将只在dev/test时间内使用debug-assert进行断言。然后对于在生产上要进行的断言,你会使用常规assert。

这似乎有点像日志记录。能否可能向当前的assert函数添加类似日志级别的"level"呢?
by
我提出debug-assert是为了不损害assert的后向兼容性。我认为当前形式的assert不应该用于任何与生产相关的事情,因为它们可以被禁用。我认为我们应该在代码中对重要内容进行检查时使用我们正常的(when-not 某些东西(throw ...))。
debug-assert的整个目的是在Java中模拟assert,你可以在dev中"滥用"它来检查你的不变性,但你确信不会不小心让它进入生产环境并让代码的用户支付性能的代价。

所以我认为这里没有级别,只是一个开发工具。

登录注册后回答此问题。

...