Код без ошибок – возможно ли?
Коды, которые Вы будете разрабатывать, должны быть не только удобны и обладать приемлемым быстродействием, но и быть безошибочными. Что подразумевается под безошибочностью?
Все достаточно просто: в любом случае, после завершения работы функции (корректного или некорректного - это неважно) AutoCAD должен принять вид, который был установлен пользователем до вызова функции. Логические ошибки типа (/ 50. 0.) отследить просто, но как отследить ошибки пользователя? Например, нажатие [Esc] в самый неподходящий момент?
Есть несколько вариантов.
Вариант 1. Переопределение стандартного обработчика ошибок. В AutoCAD обязательно присутствует штатный обработчик ошибок, и имя ему - *error*. Функция принимает единственный параметр (текстовое сообщение об ошибке). А вот ее "внутренности" уже могут меняться. Так, например, обработчик ошибок в AutoCAD Architecture видоизменен самой Autodesk.
Переопределить обработчик можно - то есть написать собственную функцию *error*, которая будет выполнять те действия, которые требуются. Переопределить *error* можно и глобально (отдельной функцией), и локально - для определенной функции. Пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | (defun lispru-func-1 (/ *error* fun_func-2) (defun *error* (msg) (princ (strcat "\n lispru-func-1 error : " msg)) (princ) ) ;_ end of defun (defun fun_func-2 (/ *error*) (defun *error* (msg) (princ (strcat "\n fun_func-2 error : " msg)) (princ) ) ;_ end of defun (princ (/ 10. 0.)) ) ;_ end of defun (princ "\ncall (fun_func-2)") (fun_func-2) (princ "(fun_func-2) finished") (sqrt -1.) ) ;_ end of defun |
Если попытаться вызвать (lispru-func-1), мы получим в консоли:
1 2 3 4 | call (fun_func-2) fun_func-2 error : divide by zero _$ |
То есть такой обработчик заканчивает выполнение функции - обратите внимание, текст "(fun_func-2) finished" даже не пытается напечататься: срабатывает обработчик, прописанный в fun_func-2, и на этом выполнение кода заканчивается. А если продолжать все равно надо? В таком случае приходит на помощь вариант 2:
Использование функции vl-catch-*:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | (defun lispru-func-2 (/ err fun_func-2) (defun fun_func-2 (/ err) (if (vl-catch-all-error-p (setq err (vl-catch-all-apply (function (lambda () (princ (vl-princ-to-string (/ 10. 0.))) ) ;_ end of lambda ) ;_ end of function ) ;_ end of vl-catch-all-apply ) ;_ end of setq ) ;_ end of vl-catch-all-error-p (princ (strcat "\n fun_func-2 error : " (vl-catch-all-error-message err) ) ;_ end of strcat ) ;_ end of princ ) ;_ end of if (princ) ) ;_ end of defun (princ "\ncall (fun_func-2)") (fun_func-2) (princ "(fun_func-2) finished") (if (vl-catch-all-error-p (setq err (vl-catch-all-apply (function (lambda () (princ (vl-princ-to-string (sqrt -1.))) ) ;_ end of lambda ) ;_ end of function ) ;_ end of vl-catch-all-apply ) ;_ end of setq ) ;_ end of vl-catch-all-error-p (princ (strcat "\n lispru-func-1 error : " (vl-catch-all-error-message err) ) ;_ end of strcat ) ;_ end of princ ) ;_ end of if (princ) ) ;_ end of defun |
Теперь вызов (lispru-func-2) вернет
1 2 3 4 | call (fun_func-2) fun_func-2 error : divide by zero(fun_func-2) finished lispru-func-1 error : function undefined for argument: -1.0 _$ |
Как видим, выполнение кода не прекращается ни при каких условиях. Что и где применять - в принципе, каждый решает сам, но лично я, проведя в свое время подобные эксперименты, окончательно и бесповоротно отказался от переопределения *error* и перешел на применение vl-catch-* функций.
В примерах я не давал переопределения глобального обработчика ошибок. Желающие поэкспериментировать могут сделать это самостоятельно.
Комментарии
Есть 2 коммент. к “Код без ошибок – возможно ли?”Трэкбэки
Узнайте, что другие говорят про эту заметку...[...] Точно так же можно оперировать не только с переменными, но и с функциями, задавая их область видимости. Подобный подход, например, показывался в Код без ошибок – возможно ли?. [...]
[...] все, что ниже, является продолжением статьи Код без ошибок. Хотелось бы поговорить насчет запроса у пользователя [...]