【问题标题】:Why isn't 'source' working?为什么“源”不起作用?
【发布时间】:2014-01-12 12:21:13
【问题描述】:

来自 REPL (Cloure 1.4.0) 我正在尝试使用 source 宏来显示我的函数的定义 - 但它回复为“找不到源”

我可以像这样在source 上使用source(并且可以看到它使用source-fn) - 但不知道为什么它不喜欢我的defn x[] "hello" 函数定义?

user=> (source source)
(defmacro source
  "Prints the source code for the given symbol, if it can find it.
  This requires that the symbol resolve to a Var defined in a
  namespace for which the .clj is in the classpath.

  Example: (source filter)"
  [n]
  `(println (or (source-fn '~n) (str "Source not found"))))
  nil


    user=> (defn x[] "hello")
    #'user/x
    user=> (source x)
    Source not found
    nil
    user=> 

【问题讨论】:

    标签: clojure macros


    【解决方案1】:

    source 只能获取在类路径上可用的源文件中定义的函数的来源。它不适用于 REPL 中定义的函数。

    更准确地说,source 的工作原理是查找由其参数命名的 Var,检查 Var 上的元数据映射是否包含源信息(一切正常工作需要 :file 和 :line 键),查看打开元数据映射中命名的文件,打开文件(作为类路径上的资源),跳过多少行,最后返回下一个表单后面的文本;详情请见(source clojure.repl/source-fn)。

    因此,它适用于存储在 Vars 中的东西——比如函数和宏——定义在源文件的顶层,它们仍然存在于类路径中。它不适用于未存储在 Vars 中的内容,以及存储在 Vars 中且支持源不存在于类路径中的内容。后一种情况可以通过 AOT 编译和 REPL 中定义的东西来实现。

    【讨论】:

    • 那么有没有办法找到在 REPL 中定义的函数(等)的“来源”?例如,如果我只在 REPL 上编码,但想保存我的工作(目前的情况)——这可能吗?
    【解决方案2】:

    source 使用函数元数据查找定义函数的文件。然后读取该文件以查找函数定义,将其转换为字符串并返回。

    简而言之,(源代码)正在做这样的事情

    user> (-> (resolve 'source) 
               meta 
               :file)
    "clojure/repl.clj"
    

    repl 中定义的函数的元数据将不包含有效的源文件。

    user=> (meta (resolve 'x))
    {:arglists ([]), :ns #<Namespace user>, :name x, :column 1, :line 1, :file "NO_SOURCE_PATH"}
    

    您可以在source-fn 函数中查看完整的工作原理。

    【讨论】:

    • 谢谢 - 我很担心选择哪个答案被接受,因为它们都非常有用!否则我会投票给两者!干杯。
    猜你喜欢
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-18
    • 2014-06-29
    • 2019-08-26
    • 2011-04-10
    相关资源
    最近更新 更多