I'm learning common lisp in my free time and have a questions about the condition system.
When we handle an error in common lisp we specify error-type in a handler to determine which error to handle. Between raising and handling an error I can place some restarts (for example with restart-case) but I cannot specify in restart an error type.
For example, assume I have a function that takes a string and a stream, sends string to stream and read the response from stream and returns it. Assume that if my message is wrong I read from stream an error response. And I want to raise an error and bind a restart that asks for new message like this:
(defun process-message (stream raw-message)
(let ((response (get-response stream raw-message)))
(restart-case
(when (response-error-p response)
(error 'message-error :text response))
(change-raw-message (msg)
(process-message stream msg)))))
Now assume that the message is complicated and I got another function send-command
at higher level that can create a message from some arguments and calls the process-message. I want to bind another restart recreate-command-message
that will allow user to send new command from arguments if 'message-error
acquires. This restart could be places in restart-case at process-message
, but it is not fully correct because process-message
should not know about such high-level function like send-command
and the return values can differ.
But now the stream errors (such as EOF etc.) will be thrown throw recreate-command-message
and if socket will fail the recreate-command-message
restart will be available in some super-high-level socket-error
handler and this restart will be useless and idiomatically wrong.
Is this a program design problem and a program should be designed to avoid such problems, or I just cannot find how to bind restart to error type or I do not understand the condition system correctly?
Thanks.