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