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 会话可以持续数天,甚至数周。如果出现问题,你可以 (清除) 并重新开始。

我的类路径上有一些 Clojure 文件,它们需要不可用的依赖项。仅此就使得无法使用 refresh。

当使用 set-refresh-dirs 时,这个问题完全消失。

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

这是一个很好的假设,对所有位于 src、test 下的命名空间都进行操作。任意工具可能会在未能遵循这一既定标准的命名空间中失败。

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

要清楚的是,我欢迎任何提高生产力的方法,并且我恰巧知道你正在寻找什么样的工作流程(因为我当时在 Clojurians Slack 分享这个问题时在场)。

如果进行 t.n 修改能实现这一点,那当然很好!

但这个问题的提出过于肯定,可能导致误导性的信息,这就是为什么我想更好地反映为什么一些人会被迫使用按设计使用 tools.namespace。

你可能在 Sierra 的著作或演讲中找到有关 t.n 理由的更多信息。
> tools.namespace 针对寻求自动化代码重载、面向项目工作流程的程序员。

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

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

如果这两个文件在同一个目录中,问题并不会完全消失。
getBy
> 如果两个文件在同一个目录下,它们并未消失。

在 `src/` 或 `test/` 下放置不可加载的命名空间是不良实践,它直接影响到其他用户和工具。

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