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的命名空间在它可读时,隐式地依赖于读取命名空间,正确的做法是在那个命名空间的定义中明确那个依赖关系。如果您这样做,就不会有“由`data_readers.cljc`引起的依赖”,只有命名空间定义中已经明确声明的依赖关系,您就不会遇到这个问题。

因此,我认为这对于`tools.namespace`工具不是必需的(考虑到Clojure的当前实现)。

嗯——这是一个杀手级观点 @alexmiller,这意味着我对Things在`c.t.n.r/refresh`后失败(但从未在生产环境中发生)的原因的理解是有缺陷的。

回到原点
-1

我对这个问题的第一反应是:“嗯,c.t.n.r/refresh可以破坏所有 sorts of things,我经常看到初学者在 reload/refresh 的工作流程中遇到麻烦……”这就是我为什么倾向于跳入每个出现 reload/refresh 的对话中,并说“别那么做!”的原因。

在我看来,对于一个根源于不够理想的REPL工作流程的问题,这是一个糟糕的解决方案。不要使用临时解决方案,而是鼓励更好的REPL工作流程。

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

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

https://github.com/aredington/clojure-repl-sufficient-p有一个有趣的repo,强调了当前REPL实现的一些缺点,如果有人有动力添加这个特定情况,将会包括在内。我特别喜欢这个repo在术语上组织某些活动的期望方式。
如果它真正地解释了具体的问题是什么,以及你能做些什么来减轻这些问题,这个repo将更有用。src文件和单个测试文件在意图上都非常晦涩。

只有在内置/封装src文件中,它才尝试展示对REPL友好的等效形式。
@sean 对于我的情况,我找到了一种构造记录的方法,使得记录的协议实现可以在类重新加载时(根据依赖顺序)幸存 - 通过使用`:extend-via-metadata`。这并不是非常优雅 - 使用记录类型来分发打印方法,将记录序列化为带标签的字面量,并用元数据来实现协议,但它是可行的。

(不幸的是,它只能在clj上工作,并在cljs上遇到无法理解的编译错误,因此我现在放弃了带有完整序列化往返的自定义带标签字面量的整个想法)

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

如果tools.namespace中的bug被修复了,我们就不会讨论它“破坏所有事物”了。

反复打击一个库就像是一种自我实现的预言——在某些时候,不会有多少人愿意在tools.namespace上动手修复,被恐惧、不确定性和怀疑所引导。这加剧了bug的存在。

希望有人能承担起tools.namespace的任务。我对我使用的分叉版本非常满意。我现在没有时间改进官方的t.n。
这有点夸张了,vemv——我不是在劝阻tools.namespace,而是在劝阻特别地刷新。我认为问题在于工作流程,而不是库。
不管是否夸张,我对反复攻击某种特定的方法(可能有一个听起来很酷的名字,但 nothing more than 'automation')感到困惑。在我们社区中一般不会看到这种情况,如https://clojure.org/community/etiquette 中所反映的那样。
请保持讨论集中在当前的问题上。
...