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

欢迎!请参阅关于页面了解有关此操作的一些更多信息。

0
tools.namespace

我在代码库中找到一个问题,一些标签字面量似乎违反了最小惊讶原则

我们创建了一些纯数据处理过程的描述,包括一些 defrecord 对象,这些对象是从 data_readers.cljc 中声明的自定义标签字面量读取器创建的,并且让这些 defrecord 对象参与一个协议。一切都在正常进行,直到我遇到了这个问题

有人将这些之一的标签字面量放入了 def(起初这似乎是一个合理的做法)

(def foo #ctx/event-path [:blah])

这本身是正常的...直到调用 c.t.n.r/refresh 以后,一切都开始出问题

结果是,defrecord 对象 foo 有一个过时的类(可能是由于 data_readers.cljc 中声明的标签字面量解析器引起的命名空间依赖关系没有被 tools.namespace 识别,因此重新编译命名空间的顺序不正确),因此不再参与协议

tools.namespace 应该能够识别 data_readers.cljc 诱发的依赖吗?或者那是它所迈出的过分的一步?

2 个答案

0

我认为这里的一个重要考虑因素是,拥有 data_readers.cljc 并不会自动加载或要求读取函数命名空间。您的程序仍然需要在将标签字面量映射到该读取函数的点之前加载包含读取函数的命名空间。这对于源代码中的标签字面量来说通常是令人烦恼的,也许应该进行更改,但现在就是这样工作的方式。

鉴于包含定义的命名空间隐式依赖于读者命名空间以便可读,而正确的做法是在该命名空间的ns定义中显式化这种依赖。如果你这样做,就不会有“由data_readers.cljc引起的依赖”,只有命名空间定义中已显式的依赖,你将不会遇到这个问题。

因此,我认为这对于tools.namespace这个特性来说并不是必需的,鉴于Clojure当前的实现。

嗯 - 这是一个关键的点 @alexmiller - 这意味着我对为什么`c.t.n.r/refresh`后事物失败(但永远不会在生产环境中发生)的理解是错误的。

回到起跑线
–1

我对这个问题的初始反应是:“c.t.n.r/refresh可能会导致各种问题,我看到很多初学者在reload/refresh工作流程中遇到麻烦。”这就是为什么我倾向于跳入每个出现reload/refresh的对话中说“别那么做!”的原因。

在我看来,这是一个不加思考就解决问题的坏方法。不要只是贴上创可贴,而应该鼓励更好的REPL工作流程。

是的,我知道Clojure的一些部分会生成Java类,这可能会让REPL的使用变得更困难,但c.t.n.r/refresh并不能解决所有这些情况(而且我认为它使人们停止思考这些问题).

我确实希望核心团队就REPL友好的处理记录和其他Clojure/Java互操作领域的方式提供一些指导。我看到一些建议,使用生成的函数而不是直接引用记录类型可能有所帮助,但我觉得记录协议扩展的组织方式还有很多问题需要更好的指导?

https://github.com/aredington/clojure-repl-sufficient-p有一个有趣的仓库,它突出了当前REPL实现的一些缺点,如果有人有动力添加它,可以考虑包括这个特定的情况。我特别赞赏这个仓库在组织特定活动期望方面的方式。
如果它实际上能够 _解释_ 出现的具体问题以及能够采取什么措施来减轻这些问题,那么这件仓库将更有用。源代码文件和单个测试文件在意图上都非常不透明。

只有在内部 comp/wrapper 源文件中,它尝试展示一个 REPL 兼容的等效版本。
@sean,就我的情况而言,我找到了一种构建记录的方法,使得记录的协议实现可以在超出依赖顺序重新加载协议类的情况下存活 - 通过使用`:extend-via-metadata`。这并不那么优雅 - 使用记录类型来派发打印方法以将记录序列化为标记字面量,以及使用元数据来实现协议,但有效

(不幸的是,这只适用于clj,并且在 cljs 上遇到了无法理解的编译错误,所以我暂时放弃了使用完全序列化往返的定制标记字面量的整个想法)

@sean,我对你描述的“不够理想”和“更好的”REPL 工作流程的细节很感兴趣 - 你能链接吗?
我对这个非答案有点失望。更有建设性的看法是“确实存在该库中的缺陷,并且可以被修复”。

如果工具库.ns 中的错误得到修复,我们就不会讨论“打破所有事物”了。

反复拒绝一个库可以说是自我实现的预言 - 有一天,几乎没有人会想让更多的人参与 tools.namespace 的修复,受 FUD 指导。这继续产生了错误。

我希望有人接管 tools.namespace。我绝对对我使用的分叉版本感到满意。我现在没有时间去改进官方的 t.n。
这有点夸张了,vemv—I并不是在反对tools.namespace工具,而是在反对具体的使用refresh命令。我认为问题出在工作流程上,而不是在库上。
不管是否夸张,我对反复批评某一特定方法(可能有一个好听的名字,但本质上不过是一种‘自动化’手段)感到困惑。在我们社区中很少见到这样的做法,正如在https://clojure.org/community/etiquette 中所示。
请将讨论集中在手头的问题上。
...