我希望您能够在REPL中打印出函数的当前定义。有没有什么方法可以实现这个功能?
例如,给定以下代码:
(defn foo [] (if true "true"))
我想说类似这样的话
(print-definition foo)
并获得类似以下的东西
(foo [] (if true "true"))
打印。
我希望您能够在REPL中打印出函数的当前定义。有没有什么方法可以实现这个功能?
例如,给定以下代码:
(defn foo [] (if true "true"))
我想说类似这样的话
(print-definition foo)
并获得类似以下的东西
(foo [] (if true "true"))
打印。
在REPL使用时,除了查看在.clj
文件中定义的函数之外,source
的替代方法是clojure.repl/source
(从1.2.0
开始应该可以使用)。如果您使用的是1.1.0
或更低版本,则source
在clojure.contrib.repl-utils
中。
(defmacro defsource
"Similar to clojure.core/defn, but saves the function's definition in the var's
:source meta-data."
{:arglists (:arglists (meta (var defn)))}
[fn-name & defn-stuff]
`(do (defn ~fn-name ~@defn-stuff)
(alter-meta! (var ~fn-name) assoc :source (quote ~&form))
(var ~fn-name)))
(defsource foo [a b] (+ a b))
(:source (meta #'foo))
;; => (defsource foo [a b] (+ a b))
一个简单的打印定义
:(defn print-definition [v]
(:source (meta v)))
(print-definition #'foo)
#'
是一个 读取宏,将 #'foo
扩展为 (var foo)
:
(macroexpand '#'reduce)
;; => (var reduce)
repl
名称空间,并使用它的source
函数:(ns myns
(:use [clojure.repl :only (source)]))
(defn foo [] (if true "true"))
(source foo)
=> (foo [] (if true "true"))
nil
虽然这种方法在REPL中不起作用,只有在定义函数的.clj文件位于类路径上时才有效。这并没有回答你的问题:你需要有一个defn
函数,可以存储在它定义的fn
元数据中,函数来源的信息。然后你可以编写一个函数来调用那部分元数据。这应该不会太困难。
Clojure没有反编译器,这意味着除非从磁盘加载了defn,否则无法获取任意函数的源代码。但是,您可以使用一个称为serializable-fn的巧妙技巧来创建一个函数,该函数的源代码存储在其元数据中:http://github.com/Seajure/serializable-fn
defsource答案与此非常相似,但此解决方案适用于任意fns,而不仅仅是顶级defns。它还使fns在repl上漂亮地打印,而无需特殊的打印函数。
source
函数是立即可用的。您可以这样使用它:
$ java -cp clojure.jar clojure.main Clojure 1.2.0 user=> (source slurp) (defn slurp "读取指定名称为f的文件,使用编码enc将其作为字符串读入并返回。" {:added "1.0"} ([f & opts] (let [opts (normalize-slurp-opts opts) sb (StringBuilder.)] (with-open [#^java.io.Reader r (apply jio/reader f opts)] (loop [c (.read r)] (if (neg? c) (str sb) (do (.append sb (char c)) (recur (.read r))))))))) nil user=>REPL的
user
命名空间还会自动导入clojure.repl库中的其他一些函数。在此处查看API文档:here。source
来打印您在REPL中定义的函数。最近我在Clojure邮件列表上问了这个问题,答案包括覆盖REPL的部分以将输入(和输出)存储起来以供将来参考,以及覆盖defn以将源代码存储在元数据中(然后可以在REPL中轻松检索)。