簡體   English   中英

如何在REPL中顯示Clojure中函數的定義?

[英]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或更低版本,則sourceclojure.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中輕松檢索)。

閱讀Clojure郵件列表中的主題

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM