Common Lisp имеет стандартную систему ошибок, которую можно использовать для реализации этого.
В реализациях Common Lisp, которые предоставляют перезапуск use-value
или store-value
для ошибок типа undefined-function
.
Пример
CL-USER 69 > (flet ((call-use-value-restart (c)
(use-value (lambda (arg)
(format t "~%dummy function with arg ~a~%" arg))
c)))
(handler-bind ((undefined-function #'call-use-value-restart))
(this-function-does-not-exist "foo")))
dummy function with arg foo
NIL
В приведенном выше примере функция this-function-does-not-exist
не существует.Как видите, ошибка обрабатывается и вместо нее вызывается другая функция, которая затем выводит некоторые данные.
Если мы вызываем неопределенную функцию самостоятельно, мы получаем ошибку:
CL-USER 70 > (this-function-does-not-exist "foo")
Error: Undefined operator THIS-FUNCTION-DOES-NOT-EXIST in form (THIS-FUNCTION-DOES-NOT-EXIST "foo").
1 (continue) Try invoking THIS-FUNCTION-DOES-NOT-EXIST again.
2 Return some values from the form (THIS-FUNCTION-DOES-NOT-EXIST "foo").
3 Try invoking something other than THIS-FUNCTION-DOES-NOT-EXIST with the same arguments.
4 Set the symbol-function of THIS-FUNCTION-DOES-NOT-EXIST to another function.
5 Set the macro-function of THIS-FUNCTION-DOES-NOT-EXIST to another function.
6 (abort) Return to top loop level 0.
Type :b for backtrace or :c <option number> to proceed.
Type :bug-form "<subject>" for a bug report template or :? for other options.
CL-USER 71 : 1 >
Наш пример в основном вызывает программный перезапуск номер 3:
Он связывает обработчик, который вызывает функцию call-use-value-restart
, когда происходит ошибка типа undefined-function
.
Функция call-use-value-restart
затем вызывает перезапуск use-value
с помощью функции, которую он предоставляет.Здесь вы можете предоставить функцию, которая вызывает внешнюю программу с именем, заданным (cell-error-name c)
.Перезапуск use-value
затем просто вызывает предоставленную функцию и продолжает выполнение программы, как обычно.
Подсказка для решения
Как правило, можно написать маленькую вершинупетля уровня, где предоставляется такой обработчик.
Другой способ вызвать перезапуск
В этом примере мы используем hook для добавления обработчикав случае ошибкиЗдесь мы используем глобальную переменную *debugger-hook*
.Это должна быть функция, и в нашем случае она вызывает новую функцию, когда условие c
имеет тип undefined-function
.
* (defun provide-a-function-hook (c hook)
(declare (ignore hook))
(typecase c
(undefined-function (use-value (lambda (arg)
(format t "~%dummy function with arg ~a~%" arg))
c))))
PROVIDE-A-FUNCTION-HOOK
* (setf *debugger-hook* #'provide-a-function-hook)
#<FUNCTION PROVIDE-A-FUNCTION-HOOK>
* (this-function-does-not-exist "foo")
; in: THIS-FUNCTION-DOES-NOT-EXIST "foo"
; (THIS-FUNCTION-DOES-NOT-EXIST "foo")
;
; caught STYLE-WARNING:
; undefined function: THIS-FUNCTION-DOES-NOT-EXIST
;
; compilation unit finished
; Undefined function:
; THIS-FUNCTION-DOES-NOT-EXIST
; caught 1 STYLE-WARNING condition
dummy function with arg foo
NIL