Is there a format directive to iterate over vectors in Common Lisp?

common-lisp, format

Solution

(defun pprint-array (stream array
                     &optional colon amp (delimiter #\Space))
  (declare (ignore colon amp))
  (loop
     :with first-time = t
     :for x :across array
     :unless first-time :do (format stream "~C" delimiter) :end
     :do (format stream "~S" x)
     (setf first-time nil)))

(format t "~' :@/pprint-array/" #(1 2 3 4)) ; 1 2 3 4

You can add more arguments (they would be separated by comma), or you could also handle somehow colon and ampersand.

Following Svante's advise here's a somewhat altered version of this function, it also utilizes the colon and ampersand in the following way: colon makes it alter between `prin1` and `princ` and at-sign makes it print nested arrays recursively (it could be further sophisticated to also print multidimensional arrays etc... but having limited time here's what it is:

(defun pprint-array (stream array
                     &optional colon amp
                       (delimiter #\Space) (line #\Newline))
  (if amp (loop
             :with first-time = t
             :for a :across array
             :unless first-time
             :do (when line (write-char line stream)) :end
             :if (or (typep a 'array) (typep a 'vector))
             :do (pprint-array stream a colon amp delimiter line)
             :else
             :do (if colon (prin1 a stream) (princ a stream)) :end
             :do (setf first-time nil))
      (loop
         :with first-time = t
         :for x :across array
         :unless first-time
         :do (when delimiter (write-char delimiter stream)) :end
         :do (if colon (prin1 x stream) (princ x stream))
         (setf first-time nil))))

Problem

Common Lisp supports an plethora of formatting directives. However, I couldn't find a handy directive for my problem. Basically, I'd like to print a grid of numbers. Using a list the following works nicely: ``` (format t "~{~A|~A|~A~%~^-----~%~}" '(1 2 3 4 5 6 7 8 9)) 1|2|3 ----- 4|5|6 ----- 7|8|9 NIL ``` I was unable find a similar construct to iterate over vectors. CLtL2 states clearly that `~{...~}` expects a list as argument. I tried using a vector anyway, but my Clisp rightly exclaimed about the wrong argument type. As a workaround I convert the my vector into a throw-away list using the almighty `loop`. ``` (let ((lst (loop for e across '#(1 2 3 4 5 6 7 8 9) collecting e))) (format t "~{~A|~A|~A~%~^-----~%~}" lst)) 1|2|3 ----- 4|5|6 ----- 7|8|9 NIL ``` This works, but it strikes me as a clumsy makeshift solution. I'd rather not create tons of temporary lists only for `format`. Is there a way to iterate vectors directly? Out of curiosity, is there a reason why `format` shouldn't support sequences?

Original source