Reputation: 4184
I am curious how
(write
(make-instance 'simple-error
:format-control "A:~a ~% B:~a~%"
:format-arguments `("A" "B"))
:stream nil)
works, as I tried to implement it myself to gain experience in basic lisp funcionality but soon had to realize, that I am not able to. As the intuitive way of implementation:
(defmethod my-write ((simple-error err))
(FORMAT nil (if (simple-condition-format-control err)
(simple-condition-format-control err)
"")
(simple-condition-format-arguments err)))
obviously cannot work, as (simple-condition-format-arguments err)
returns the list of arguments and therefore, in the example above, "B:~a" does not have a corresponding parameter to print.
So how would I actually implement this method?
Upvotes: 1
Views: 117
Reputation: 139321
As mentioned by Samuel, you need to use APPLY
.
Also note that NIL
for the stream in WRITE
does something else than in FORMAT
. With FORMAT
the stream argument NIL
causes the output to be returned as a string. With man other output functions, like WRITE
, it means standard output.
Upvotes: 0
Reputation: 6675
You can use apply
for this. It takes the function passed as its first argument and applies it to arguments constructed from its other arguments. For example, (apply #'f 1 2)
calls (f 1 2)
, (apply #'f 1 '(2 3))
calls (f 1 2 3)
and so on. It's perfectly suited for this situation.
SBCL has a function almost identical to yours:
(defun simple-condition-printer (condition stream)
(let ((control (simple-condition-format-control condition)))
(if control
(apply #'format stream
control
(simple-condition-format-arguments condition))
(error "No format-control for ~S" condition))))
Upvotes: 2