Sim
Sim

Reputation: 4184

How does write take advantage of the format arguments contained in a simple-error

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

Answers (2)

Rainer Joswig
Rainer Joswig

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

Samuel Edwin Ward
Samuel Edwin Ward

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

Related Questions