2014-01-12 132 views
2

從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=> 

回答

6

source只能得到類路徑中可用的源文件中定義的函數源。它不適用於在REPL中定義的函數。

更確切地說,source作品通過查找其參數命名的VAR,檢查對無功的元數據映射是否包括源信息(一切都是工作需要:file:line鍵),查找命名的文件元數據映射,打開文件(作爲類路徑上的資源),跳過很多行,最後將文本返回到下一個表單後面;詳情請參見(source clojure.repl/source-fn)

因此,它可以用於存儲在Vars中的東西 - 比如函數和宏 - 在源文件的頂層定義,它仍然存在於類路徑中。它不適用於沒有存儲在Vars中的事物,也不適用於存儲在其類別路徑中不存在其後備源的Vars中的事物。後一種情況在AOT編譯和REPL定義的情況下是可能的。

+0

那麼有沒有找到in-REPL定義函數(等)的'源'的方法?例如,如果我只是在REPL上編寫代碼,但想保存我的工作(就目前的情況而言) - 那可能嗎? – monojohnny

4

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函數中看到完整的工作方式。

+0

謝謝 - 我被撕裂選擇哪個答案被接受,因爲他們都非常豐富!否則,我會投票支持!乾杯。 – monojohnny