925 -  Providing MultivleMRestarts

Top 

_

1590592395

_

Chapter 19 - Beyond Exception Handling—Conditions and Restarts

Practical Common Lisp

by Peter Seibel

Apress © 2005



_


transdot

_

arrow_readprevious

Progress Indicator

Progress IndicatorProgress Indicator

Progress Indicator

arrow_readnext

_

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.

_

arrow_readprevious

Progress Indicator

Progress IndicatorProgress Indicator

Progress Indicator

arrow_readnext

_