2014-01-12 3 views
2

Из РЕПЛ (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 с именем его аргументом, проверяя, содержит ли отображение метаданных на Var информации об источнике (за все работы необходимы :file и :line ключей), глядя вверх файл с именем в карта метаданных, открывая файл (как ресурс в пути к классам), пропуская все количество строк и, наконец, возвращая текст за следующей формой; см. (source clojure.repl/source-fn) для деталей.

Таким образом, он будет работать для вещей, хранящихся в Vars - подобных функциях и макросах, определенных на верхнем уровне в исходных файлах, которые все еще присутствуют в пути к классам. Он не будет работать для вещей, которые не хранятся в Vars, а также хранятся в Vars, источник поддержки которых отсутствует в classpath. Последний случай возможен с компиляцией AOT и вещами, определенными в REPL.

+0

Итак, есть способ найти «источник» встроенной функции REPL (и т. Д.)? Например, если я сидел только в редакторе REPL, но хотел сохранить свою работу (как она сейчас стоит) - возможно ли это? – monojohnny

4

source использует метаданные функции, чтобы найти файл, в котором была определена функция. Затем он считывает этот файл, чтобы найти определение функции, преобразует его в строку и возвращает его.

Короче говоря, (источник источник) делает что-то вроде этого

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

мета данные для функции, определенной в РЕПЛ не будет содержать корректный исходный файл.

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

Вы можете увидеть все разработки в функции source-fn.

+0

Спасибо - я был разорван, какой ответ выбрать, как принято, поскольку они оба очень информативны! В противном случае я бы проголосовал за обоих! Приветствия. – monojohnny

Смежные вопросы