Alternative to HANDLER-CASE which is not a macro
So, consider the following code:
(define-condition some-condition (error) nil)
(defmethod print-object ((obj some-condition) stream)
(format stream "HELLO THERE"))
(defmacro error-report-test-aux (fn-to-cause-error error-type-to-catch fn-to-handle-error expected-message)
`(let ((result-message
(handler-case (funcall ,fn-to-cause-error)
(,error-type-to-catch (e) (funcall ,fn-to-handle-error e)))))
(assert (string= result-message
,expected-message))
t))
I can use it like this:
(error-report-test-aux (lambda () (error 'some-condition))
some-condition
#'princ-to-string
"HELLO THERE")
But I wanted to make a error-report-test-aux
function instead of a macro, so that I can pass it the type of the condition inside the variable.
To just write defun
instead defmacro
and remove backquote and commas don't work because it handler-case
is a macro and doesn't evaluate error-type-to-catch
.
My question is: Is there something like handler-case
that that will evaluate its arguments (specifically the condition type argument)?
source to share
Yes and no: -)
No to your exact question
There is no standard function that does what you want, because trap errors require bindings to be set, and it is usually required to bind constant characters (like in / ) because it is easier to optimize. let
let*
You might consider creating a "generic" handler with handler-bind
and then abandoning the handling of "uninteresting" conditions (as suggested by @jkiiski in the comments), but I'm not sure if this suits your exact requirements (untested!):
(defun error-report-test-aux (fn-to-cause-error error-type-to-catch expected-message)
(catch 'trap
(handler-bind ((error
(lambda (condition)
(when (typep condition error-type-to-catch)
(throw 'trap (string= (princ-to-string condition)
expected-message))))))
(funcall fn-to-cause-error))))
Yes, implementation specific
IF your implementation implements handler-case
/ handler-bind
by binding an internal global variable you can use progv
to bind it yourself and thus implement yours error-report-test-aux
as a function.
This is probably not the best idea (your code is implementation specific).
Yes, kind
You can use the fact that some-condition
the CLOS class calls and uses common functions instead of macros.
source to share