clojure.repl/source-fn 函数通过使用自定义读取器在给定的符号的行和文件元数据指定的位置读取源形式。虽然这对大多数东西都适用得很好,但我发现当将 source-fn 应用于包含类似于 ::T/foo 的关键字命名空间别名的代码时出现了问题。::T/foo 在它出现的上下文中是一个合法的命名空间关键字,因为一个到 T 的命名空间别名在 ns 标头中创建。然后,当读取关键字 ::T/foo 时,它将解析为 :my-other.ns/foo,正如人们所预期的那样,因为 ns 有适当的别名。然而,当尝试通过 clojure.repl/source-fn 读取源时,ns 可能不再是指示形式的原始读取上下文,从而导致不正确的异常 java.lang.RuntimeException: Invalid token: ::T/foo。
解决方案是必须在 (binding (link: ns (.ns v))) 中包装 clojure.repl/source-fn 的读取操作,以便源读取将在原始加载读取上下文中进行,从而防止此错误。
这里有补丁等效函数,https://github.com/clojure-grimoire/lein-grim/blob/master/src/grimoire/doc.clj#L50-L74,我将在早上提交对 1.6.0 的补丁。