(defmacro with-output-to-stream-or-string ((symbol &optional (stream-or-null symbol)) &body body) "Bind `symbol` to an output stream, run `body`, and return appropriately. If `stream-or-null` is a stream, `symbol` will be bound to it and nothing will be returned. If `stream-or-null` is `nil`, `symbol` will be bound to a string output stream and the resulting string will be returned. " (let ((want-string (gensym "WANT-STRING"))) `(let* ((,symbol ,stream-or-null) (,want-string (null ,symbol)) (,symbol (or ,symbol (make-string-output-stream)))) ,@body (if ,want-string (get-output-stream-string ,symbol) (values)))))