2011-02-08 2 views
1

Я видел несколько вариантов следующего кода регистрации макроса:В clojure есть рекурсивная версия регистрации кода?

(defmacro log 
    "for debugging, output code and code->val to stdout, returns val" 
    [code] 
    `(let [c# ~code] 
     (prn '~code) 
     (clojure.pprint/pprint c#) 
     c#)) 

однако, я не видел рекурсивную версию, которая оборачивает все макросы или функциональные формы в коде тела. Кто-нибудь имеет хорошую рабочую реализацию?

EDIT:

Чтобы уточнить, взять, например, следующий код:

(map #(+ % 10) (range 5)) 

, окружив, что в рекурсивном лог макрос:

(r-log (map #(+ % 10) (range 5))) 

макро-расширение, что должно быть:

(log (map #(log (+ % 10)) (log (range 5)))) 
+0

Вы можете указать пример, что вы ищете? Я почти наверняка не знаю ответа, но я не понимаю, что вы хотите, чтобы код примера не предоставлял. –

ответ

1

Хорошо, я придумал следующее. Я думаю, что это то, о чем вы просите:

Примечание logx - ваш log макрос с переменной длиной code аргумент.

(defmacro logx 
    "for debugging, output code and code->val to stdout, returns val" 
    [& code] 
    `(let [c# ~code] 
     (prn '~code) 
     (clojure.pprint/pprint c#) 
     c#)) 

(defn add-logx-calls [code] 
    (if (seq? code) 
    `(logx [email protected](map add-logx-calls code)) 
    code)) 

(defmacro r-log 
    [& code] 
    (apply add-logx-calls code)) 

(r-log (map #(+ % 10) (range 5))) 

Я не тестировал его ни на чем, кроме образца, который вы мне дали. Если вы его улучшите, сообщите нам об этом.

+0

Спасибо, я проверил. – bmillare

+0

Я принимаю ваш ответ, но есть ли причина, по которой вам нужно было сделать logx для кода переменной длины? Я сделал версию, которая не требует этого. – bmillare

+0

Нет веской причины. Это казалось выгодным. – Psyllo

2

несколько иной, более целенаправленный подход - это вызов функции, которая добавляет функцию журнала к каждой функции в пространствах имен, над которыми вы работаете, чтобы они регистрировали себя, когда они вызываются. это позволит вам увидеть, как ваш код запускается, не видя всех внутренних элементов карты.

clojure: adding a debug trace to every function in a namespace?

+0

Не избегать прямого ответа на вопрос, но этот ответ, скорее всего, является лучшим решением, чем то, что вопрос спрашивает. – Psyllo

+0

Хотя эта ссылка полезна, и я благодарю вас за это, я все еще вижу примеры использования кода, который делает то, о чем я прошу. Хорошим примером является то, что вы пишете относительно большой фрагмент кода, который использует основные функции вместо определенного пользователем, и вам нужно только регистрировать возврат функций в цепочке, а не все вызовы этих функций. – bmillare

+0

Да, посмотрев на него снова, я думаю, это может быть полезно. Я постараюсь что-то написать. – Psyllo

1

Я обычно использую clojure.contrib.trace тактически ввести такого рода вещи, лучше объяснить здесь, чем я мог бы:

Debugging in Clojure?

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