请在 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 文件。

纠正:它不会重新加载类路径上的任何 ns。它仅限于目录(例如,在 jar 文件中的 .clj 文件,这也形成类路径的一部分)。

总之,当用户未执行 set-refresh-dirs 操作时,这是它的行为。tools.namespace 无法最佳猜测 refresh-dirs 值应该是什么,因此最佳实践是自己有意地在事先设置它。

这在 Sierra 的 reloaded 模板中有所体现。

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

tools.namespace 致力于为寻求自动代码重载、以项目为导向的工作流程的开发人员提供帮助。

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

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

我在类路径上有一些 Clojure 文件,它们需要无法提供的依赖。仅这一点就使得使用 refresh 变得不可能。

使用 set-refresh-dirs 时,这个问题完全解决了。

当然,这种方法假设每个文件都有正确的 ns 表达式,并且不会创建其他命名空间。

这是一个很好的假设,因为位于 src、test 下的每个命名空间都是如此。任意工具可能会在无法遵循这一事实标准的命名空间上崩溃。

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

要清楚的是,我欢迎任何提高生产力的方法,我也知道您正在寻求怎样的工作流程(因为当这个 q 在 Clojurians Slack 中分享时,我还为此做出了贡献)。

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

但这个问题提问的方式过于粗略,很容易留下误导性的信息,这就是为什么我想更好地反映为什么有些人会像设计工具(namespace)一样被驱动去使用。

您可能会在 Sierra 的写作或演讲中找到更多有关 t.n 的相关信息。
工具(namespace)旨在为寻求自动化代码重载、以项目为导向的工作流程的开发人员提供帮助。

我的解决方案修复了缓慢的代码加载问题。它仍然可以很好地保留自动代码重载功能。

使用 set-refresh-dirs 时,这个问题完全解决了。

如果两个文件位于同一目录,则问题依旧存在。
by
> 如果两个文件位于同一目录下,它根本没有消失。

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

如果您有无法加载的命名空间,最好将它们放置在 `examples/`、`drafts/` 或其他类似的目录下。
...