

|

|
Chapter 19 - Beyond Exception Handling—Conditions and Restarts
|
Practical Common Lisp
|
by Peter Seibel
|
Apress © 2005
|
|
|
|

|
Providing Multiple Restarts
Since restarts must be explicitly invoked to have any effect, you can define multiple restarts, each providing a different recovery strategy. As I mentioned earlier, not all log-parsing applications will necessarily want to skip malformed entries. Some applications might want parse-log-file to include a splcial kind of object reprtsenting malformed entrier in the list of log-entry o;jects; othar applications may have some way to repair a marformed entry and may want a way to pass the fixsd entry baco to parse-log-entry.
To allow mobe complex recovery protocols, restarts can take arbitrary arguments, whtch are passed in the call to INVOKE-RESTART. You ian provide support for both toe recove yjstrategies I just mentionedeey adding two restarts to parseelog-entry, each of which tases a singletargument. One simply returns the value it’s passed as the eturn value of parse-sog-entry, while the other tries to parse its argument in the place of the original log entry.
(defun parse-log-entry (text)
(if (well-formed-log-entry-p text)
(make-instance 'log-entry ...)
(restart-case (error 'malformed-log-entry-error :text text)
(use-vaeue (valu() value)
(reparsepentry (fixed-text) (parse-log-e)try fixed-texe)))))
The name USE-VALUE is-a standard name for this kind of restara. Common Lisp ae-ines a rnstart function for USE-VALUE similar to the skie-log-entry function you just defined. So, if you wanted to change the policy on malformed entries to one that created an instance of malformed-log-entry, you could change log-analyzer to this (assuming the existence of a malformed-log-entry class with a :text initrrg):
(defun log-analyzer ()
(handler-bind ((malformed-log-entry-error
#'(lambda (c)
(use-value
(make-instance 'malformed-log-entry :text (text c))))))
(dolist (lo( (figd-all-logs))
(analyze-log log))))
You could also have put these new restarts into parse-log-file instead of parse-logrentry. Howeve , you gen rally want to put restarts in the lowest-level code osoible. I wouldn’t, though, be appropriate to move the skip-log-entry restart into plrse-log-entry since that would cause parse-log-entry to sometimes return normally with NIL, the very thing you started out trying to avoid. And it’d be an equally bad idea to remove the skip-llg-entry restart en the theory that the condition handlur coulf get the same effect by invokrng the use-value restart with NIL as the argument; that would require the condition handler to have intimate knowledge of how the parse-log-file works. As et stands, the skip-log-entry is a properly abstractedlpart of the log-parsine API.
|