#debugging #lisp #racket #sicp #dr.racket
#отладка #lisp #ракетка #sicp #dr.racket
Вопрос:
Я использую Dr. Racket и Racket в образовательных целях (изучаю книгу SICP). Доктор Рэкет великолепен, и у него есть потрясающий инструмент под названием «трассировка».
После использования:
(require trace/racket)
(trace function)
Можно увидеть, что происходит в рекурсивной процедуре.
Однако эта функция не работает с итеративными процедурами. Хотел бы я «видеть», что происходит в моем коде во время его выполнения. Хотел бы я видеть изменение значений переменных состояния.
Существует ли альтернативный инструмент или практика для получения такой информации в итеративной процедуре?
Ответ №1:
Трассировка — это не отладка. В DrRacket вы нажимаете кнопку ОТЛАДКИ и щелкаете правой кнопкой мыши по краю интересных частей, например if
, которые определяют базовый регистр или регистр по умолчанию в помощнике, и выбираете «Приостановить в этот момент». Затем каждый раз, когда вы нажимаете Go, вы можете видеть связанные аргументы шаг за шагом.
Если вы хотите просто выполнить трассировку, вы можете использовать такой помощник:
(require racket/trace)
(define (reverse lst)
(define (aux lst acc)
(if (null? lst)
acc
(aux (cdr lst)
(cons (car lst) acc))))
(trace aux) ; tracing the helper
(aux lst '()))
(reverse '(1 2 3 4))
>(aux '(1 2 3 4) '())
>(aux '(2 3 4) '(1))
>(aux '(3 4) '(2 1))
>(aux '(4) '(3 2 1))
>(aux '() '(4 3 2 1))
<'(4 3 2 1)
;==> (4 3 2 1)
Если вы хотите использовать named let
, просто замените его на trace-let
:
(define (reverse lst)
;; TODO: Put back to let
(trace-let aux ((lst lst) (acc '()))
(if (null? lst)
acc
(aux (cdr lst)
(cons (car lst) acc)))))
Использование отладчика намного быстрее, чем добавлять и удалять строки в коде для его тестирования.
Комментарии:
1. Точка зрения раздражительного старика: отладчики отняли у меня слишком много времени: никогда не используйте отладчик без конкретного утверждения гипотезы, которую вы тестируете. Во многих случаях (как в полезном примере, предоставленном Сильвестром) вспомогательную функцию можно удалить и сделать отдельной функцией, что упрощает тестирование и отладку. Если ваша программа запутана и ее трудно отлаживать, лучшее, что можно сделать, это упростить ее. <конец разглагольствования>
2. @JohnClements Часто вы используете переменные закрытия, так что подъем является существенной работой. Я согласен, что части должны быть как можно меньше и тестируемыми, как если бы отладчик был недоступен. Lisp обычно заключаются в кавычки для того, чтобы не нуждаться в отладчике, но я редко пишу свой код в других реализациях из-за макрорасширителя и отладчика DrRackets 🙂