как отловить сообщение об ошибке в Common Lisp? - PullRequest
0 голосов
/ 22 января 2019

Я не могу перехватить сообщение об ошибке, которое печатается в REPL, я хотел бы, чтобы оно было в виде строки или любого другого типа, который может быть напечатан позже, возможно ли это в Common Lisp?Это что-то общее в других языках, таких как Javascript:

var myError = undefined;
try {
    some();
}catch(e){
    myError = e.message;
}

Конечно, в Common Lisp это не будет работать, в конце концов, оно не будет возвращать объект ошибки, как в JavaScript, но мне интересно,есть какой-нибудь способ перехватить сообщение об ошибке, поэтому мне не нужно печатать его, когда происходит ошибка, но когда я хочу.

Я использую: SBCL

Я пытаюсь:

CL-USER> (handler-case (/ 3 0)
  (division-by-zero (c)
    (defvar *my-error* c)))
; in: HANDLER-CASE (/ 3 0)
;     (/ 3 0)
;
; caught STYLE-WARNING:
;   Lisp error during constant folding:
;   arithmetic error DIVISION-BY-ZERO signalled
;   Operation was (/ 3 0).
;
; compilation unit finished
;   caught 1 STYLE-WARNING condition
*MY-ERROR*
CL-USER> *my-error*
#<DIVISION-BY-ZERO {1004486093}>

Я хочу запечатлеть следующее сообщение для печати позже:

; in: HANDLER-CASE (/ 3 0)
;     (/ 3 0)
;
; caught STYLE-WARNING:
;   Lisp error during constant folding:
;   arithmetic error DIVISION-BY-ZERO signalled
;   Operation was (/ 3 0).
;
; compilation unit finished
;   caught 1 STYLE-WARNING condition

Ответы [ 2 ]

0 голосов
/ 22 января 2019

Вы перехватили условие, следовательно, вы можете воспроизвести сообщение error , но, похоже, вы хотите перехватить предупреждение SBCL о компиляции .Таким образом, он не зависит от условия.

У меня нет решения, но вы должны искать в другом направлении IMO (как ловить предупреждения SBCL и т. Д.).

Как уже говорилось, вы не должны использовать defvar.Вместо этого вы можете использовать setf, даже если вы не defvar переменную ранее.В этом случае вы получите еще одно предупреждение:

; in: HANDLER-CASE (/ 3 0)
;     (SETF *MY-ERROR* C)
; ==>
;   (SETQ *MY-ERROR* C)
; 
; caught WARNING:
;   undefined variable: *MY-ERROR*
; 
; compilation unit finished
;   Undefined variable:
;     *MY-ERROR*
;   caught 1 WARNING condition
;   caught 1 STYLE-WARNING condition

Кстати, кажется, вы используете кулинарную книгу, не так ли?:)

0 голосов
/ 22 января 2019
CL-USER> (write *my-error* :escape nil)
arithmetic error DIVISION-BY-ZERO signalled
Operation was (/ 3 0).
#<DIVISION-BY-ZERO {100369B843}>

То же самое можно сделать с помощью format, используя директиву ~a:

CL-USER> (with-standard-io-syntax (format nil "~a" *my-error*))
"arithmetic error DIVISION-BY-ZERO signalled
Operation was (/ 3 0)."

Будьте осторожны, вы используете defvar, поэтому переменная не будет назначена, если вы выполняете один и тот же код дважды. Лучше определить функцию, которая возвращает строку, и использовать локальные переменные.

Я хочу записать следующее сообщение

Это сообщение относится к тому, как ваша среда печатает сообщения об ошибках, его труднее перехватить, возможно, вы могли бы связать свой собственный поток строк и захватить весь вывод (?), Но я бы не рекомендовал делать это.

...