2024 Clojure 调查报告!中分享您的想法。

欢迎!请参阅关于页面了解更多有关其工作原理的信息。

+12
tools.namespace

当前对 clojure.tools.namespace.repl/refresh 实现中存在的两个问题

  1. 在第一次调用时,它会重新加载类路径上的所有 Clojure 文件。它的文档字符串中提示了这一点,但没有解释为什么需要这种行为。至少,这使得第一次 refresh 调用比需要的慢得多。

  2. 它甚至会尝试重新加载之前未加载的文件。这是一个真实的情况 - 我在类路径上有一些 Clojure 文件需要依赖于不可用。仅这一点就使得无法使用 refresh。也许,可以修改它以避免加载之前未加载的文件。

目前,我正在使用这些方法

(alter-var-root #'clojure.tools.namespace.repl/refresh-tracker
                assoc :clojure.tools.namespace.dir/time (System/currentTimeMillis))

(alter-var-root #'clojure.tools.namespace.repl/remove-disabled
                (fn [orig-remove-disabled]
                  (fn [tracker]
                    (let [filter-loaded #(filter find-ns %)]
                      (-> tracker
                          orig-remove-disabled
                          (update :clojure.tools.namespace.track/unload filter-loaded)
                          (update :clojure.tools.namespace.track/load filter-loaded))))))

当然,此解决方案假设每个文件都有一个合适的 ns 表达式且不会创建其他命名空间。但似乎这只是 tools.namespace 的假设,即通过使用 clojure.tools.namespace.file/read-file-ns-decl

1 个答案

+1

在第一次调用时,它重新加载类路径上的所有 Clojure 文件。

纠正:它不会重新加载类路径上的任何命名空间。它仅限于目录(与包含在 .jar 文件中的 .clj 文件不同,这些文件也构成类路径的一部分)。

无论如何,当用户没有执行 set-refresh-dirs 时,这是它的行为。tools.namespace 无法最佳猜测 refresh-dirs 值应该是多少,因此最佳实践是在事先有意为之地设置它。

这体现在 Sierra 的 reloaded 模板中。

至少,这使得第一次刷新调用比必需的慢得多。

tools.namespace 旨在面向寻求自动化代码重新加载、面向项目的程序员。

它假定你想要 与项目一起工作(与任意脚本集相对),无法猜测哪个项目命名空间将首先需要,或者你将首先做什么(运行测试,启动服务器?)。因此,它加载每个命名空间。

值得注意的是,REPL 会话可以持续数天,甚至数周。如果出现问题,你可以 (clear) 并重新开始。

我在类路径上有些 Clojure 文件,需要一些不可用的依赖项。仅此一项就使得使用 refresh 成为不可能。

使用 set-refresh-dirs 时,此问题全部消失。

当然,这个解决方案假设每个文件都有一个合适的 ns 表单,并且不会创建其他命名空间。

这是一个好的假设,为每个位于 src、test 之下的 ns 做这件事。任意工具可能会在无法遵循这个事实上的标准时中止。

再次强调,这就是为什么存在 set-refresh-dirs 的原因——为了将 '主' 源路径(如 src/test/)与包含示例、脚本、草案等内容的其他目录区分开来。实际上,在给定的项目中执行任意命名空间的 require 是危险的?(因为这些可以是面向生产的脚本等)。

by
为了清楚起见,我欢迎所有提高生产力的方法,并且我恰好知道你寻求的是哪种工作流程(因为我当时就在 Clojurians Slack 分享此问题时)。

如果进行 t.n 修改能够实现这一点,那太好了!

但这个问题的提出是过于假设的,很容易留下误导性的信息轨迹,这就是为什么我想要更好地反映为什么有些人被迫按照 tools.namespace 设计使用。

你可以在 Sierra 的作品或谈话中找到关于 t.n 理由的更多信息。
by
> tools.namespace 面向寻求自动化代码重加载、面向项目的程序员。

我的解决方案修复了慢速代码加载问题。而且它仍然保留了自动的代码重新**加载**功能。

> 使用 set-refresh-dirs 时,这个问题全部消失了。

如果两个文件在同一个目录下,问题根本就没有解决。
by
> 如果两个文件位于同一个目录下,它们根本就不会丢失。

将不可加载的命名空间放置在`src/`或`test/`下是一种不好的做法。这会直接影响到其他用户和工具。

如果您有不可加载的命名空间,最好将它们放置在`examples/`、`drafts/`等目录下。
...