[英]How can I display the definition of a function in Clojure at the REPL?
我正在寻找能够让REPL打印出函数的当前定义的能力。 有没有办法做到这一点?
例如,给定:
(defn foo [] (if true "true"))
我想说点什么
(print-definition foo)
并得到一些东西
(foo [] (if true "true"))
打印。
source
的替代方法(在启动REPL时应该通过clojure.repl/source
,从1.2.0
。如果你使用的是1.1.0
或更低版本,则source
在clojure.contrib.repl-utils
。) ,对于REPL使用,而不是查看.clj
文件中定义的函数:
(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))
一个简单的print-definition
:
(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的简洁hack来创建一个将源代码存储在其元数据中的函数: http : //github.com/Seajure/serializable-fn
defsource答案与此非常相似,但此解决方案适用于任意fns,而不仅仅是顶级定义。 它还使fns在repl上打印得漂亮,没有特殊的打印功能。
在clojure 1.2的REPL中, source
函数立即可用。 你可以这样使用它:
$ java -cp clojure.jar clojure.main Clojure 1.2.0 user=> (source slurp) (defn slurp "Reads the file named by f using the encoding enc into a string and returns it." {: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=>
其他一些函数也会自动从clojure.repl库导入REPL的user
命名空间。 请在此处查看API文档。
但是,正如在此处的其他答案中所指出的,您不能使用source
来打印您在REPL中定义的函数。
我最近在Clojure邮件列表上确切地问了这个问题,答案包括覆盖REPL的部分以隐藏输入(和输出)以备将来参考,以及覆盖defn以将源存储在元数据中(然后你可以在REPL中轻松检索)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.