Ponowne przeglądanie błędu w Emacsie Lispie

9

Muszę wywołać funkcję i wykonać czyszczenie tylko wtedy, gdy funkcja się nie powiedzie, a następnie ponownie uruchomić błąd. Oto pseudo-kod:

(condition-case err
    (call-function)
  (error
   (cleanup)
   ;; how do I raise `err`?
   ))
Elena
źródło

Odpowiedzi:

10

BTW, alternatywną opcją może być coś takiego:

(let ((error t))
  (unwind-protect
      (prog1 (call-function)
        (setq error nil))
    (when error (cleanup))))

Zaletą jest to, że unikasz wychwytywania i ponownego zgłaszania błędu, co oznacza na przykład, że debugger pokaże ci właściwy ślad wsteczny (ten, który odpowiada faktycznemu źródłu błędu, a nie ten, który odpowiada, że ​​ponownie rzucasz błąd innej osoby ).

Inną różnicą jest to, że cleanupzostanie wywołany nie tylko w przypadku błędu, ale także, jeśli kod zostanie przerwany przez a C-glub wywołanie do throw.

Stefan
źródło
1
Dzięki. Dlaczego nie condition-casezłapać keyboard-quit?
Elena
3
Ponieważ nie jest to błąd (tj. Jego sygnał, quitnie ma go errorwśród rodziców). IOW ty van również złapać ją condition-case, ale do tego trzeba umieścić quitobok error. Oczywiście nadal nie poradzi sobie ze sprawą „rzucania”.
Stefan
13

Poszukujesz signal:

(condition-case err
    (call-function)
  (error
   (cleanup)
   (signal (car err) (cdr err)))) ; reraise `err'
npostavs
źródło
Zastanawiałem się signal, ale jego prototyp (signal ERROR-SYMBOL DATA)nie (signal ERROR).
Elena
@Elena: właśnie przepraszam, rozdzieliłeś to na cari cdr. Odpowiedź zaktualizowana.
npostavs