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

欢迎!请参阅关于页面以了解更多关于这是如何工作的信息。

0
tools.namespace

我在代码库中发现了围绕一些标记字面量似乎违反了最小意外原则的有趣问题

我们已经创建了一些纯数据描述的过程,包括来自在 data_readers.cljc 中声明的自定义标记字面量读取器的 defrecord 对象,并让这些 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 文件并不会自动加载或引入读取函数名称空间。在读取将映射到该读取函数的有标签的文本书面语句之前,您的程序仍然需要负责引入包含读取函数的名称空间。这常常在源代码的有标签的文本书面语句中引起不便,也许这是应该改变的地方,但现在事情就是这样工作的。

鉴于这种情况,包含 def 的名称空间隐式依赖于读取名称空间以使其可读,正确的方法是在该名称空间的 ns 定义中显式这种依赖关系。如果您这样做,将不存在 “由 data_readers.cljc 引起的依赖”,只有名称空间定义中已经显式依赖项,您将不会有这个问题。

因此,我不认为这是 tools.namespace(根据 Clojure 的当前实现)所需的功能。

嗯 - 这是一个关键点 @alexmiller - 这意味着我对 `c.t.n.r/refresh` 之后事物失败(但从未在产品中)的理解是错误的。

回到原点重新设计
-1 投票

我对这个问题的第一反应是:“嗯,c.t.n.r/refresh 会破坏各种事物,我经常看到初学者在使用 reload/refresh 的工作流程时陷入困境...这就是为什么我倾向于跳入每个出现 reload/refresh 的对话,说 ‘不要这样做!’”。

对我来说,这是一个不好的解决方案,因为这是一个由最初不理想的 REPL 工作流程引起的问题。不要解决表面问题,鼓励更好的 REPL 工作流程。

是的,我知道 Clojure 中的一些部分实际上会生成 Java 类,这会使得在 REPL 中的生活变得困难--但是 c.t.n.r/refresh 根本无法解决所有这些情况(我认为它还会使人们停止思考这些问题)。

我确实希望能看到核心团队关于如何以 REPL 友好的方式处理记录以及其他 Clojure/Java 互操作领域的建议。我看到了一些建议说,使用生成的函数而不是直接引用记录类型有帮助,但我认为围绕如何组织需要更好指导的记录协议扩展仍然存在一些问题?

https://github.com/aredington/clojure-repl-sufficient-p 有一个有趣的仓库,它突出了一些当前REPL实现的不利之处,如果有人有兴趣添加这个特性,可以包括这个特定的案例。我特别喜欢这个仓库在处理某些活动的期望方面的组织方式。
如果这个仓库实际上解释了特定的问题以及如何缓解这些问题,将会非常有用。不论源文件还是那个测试文件,它们的意图都相当晦涩。

只有在内部`comp/wrapper`源文件中它才尝试展示一个与REPL友好的等效实现。
对于我的情况,我发现了一种构建记录的方法,使得记录的协议实现可以在协议类按依赖顺序重新加载时幸存 —— 通过使用`:extend-via-metadata`。这并不是非常优雅 —— 使用记录类型将`print-method`调度到序列化记录为带标签的字面量,并使用元数据来实现协议,但它有效。

(遗憾的是,这只在clj中有效,在cljs中遇到无法理解的编译错误,所以我暂时放弃了使用完全序列ization来回旅行的自定义带标签字面量的整个想法)

关于你所说的“不完美”和“更完美”的REPL工作流程,我对进一步细节感兴趣 —— 你能提供链接吗?
我对这个非答案有些失望。更建设性的看法应该是“确实是lib中存在缺陷,并且可以修复”。

如果tools.namespace中的bug被修复,我们不会在谈论它“破坏所有东西”。

反复抵制一个库有点像自我实现的预言——在某个时候,不会很多人想基于恐惧和不确定性来修改tools.namespace,这将持续bug。

我希望有人能够接管tools.namespace。我确实对我的分支非常满意。我目前没有时间改善官方的t.n。
有点过于戏剧化,vemv——我并不是在抵制tools.namespace,我是在抵制refresh。而且我认为缺陷在于工作流程,而不是库。
不管是否戏剧化,我仍然对不断反对特定方法(虽然可能有很帅气的名字,但其实不过是一种‘自动化’)感到困惑。在我们社区中通常不会看到这种行为,正如在https://clojure.org/community/etiquette 中所反映的那样。
请让我们将讨论限于眼前的问题。
...