From: David J. Cooper
Subject: Formatting Lists -- There Has to be a Better Way
Date: 
Message-ID: <380D3881.55FFEE1D@genworks.com>
Hello group,

 I am finding myself using the following idiom to achieve printout of
lists with, for example, a space and a comma after every but the last
element. 

 That voice which says "There has Got to be a Better Way" is screaming
at me that there must be a way to do this with a simple format, perhaps
with the "~<:>" directive (?) -- but I cannot seem to decipher the 
documentation on it...

 A cold Sam Adams Oktoberfest for a nice example!


(defparameter *prerequisites* (list "G101" "G102" "G103"))

(with-output-to-string(ss)
  (let ((count 0) 
        (length (length *prerequisites*)))
    (dolist (prerequisite *prerequisites*)
      (format ss "~a~a" 
                 prerequisite
                (if (< (incf count) length)
                    ", "
                  "")))))


--> "G101, G102, G103"


Thank U all,

 -dave

-- 
David J. Cooper Jr, Chief Engineer	Genworks International
·······@genworks.com			5777 West Maple, Suite 130
(248) 932-2512 (Genworks HQ/voicemail)	West Bloomfield, MI 48322-2268
(248) 407-0633 (pager)			http://www.genworks.com

From: Duane Rettig
Subject: Re: Formatting Lists -- There Has to be a Better Way
Date: 
Message-ID: <4d7uaftxr.fsf@beta.franz.com>
"David J. Cooper" <·······@genworks.com> writes:

> Hello group,
> 
>  I am finding myself using the following idiom to achieve printout of
> lists with, for example, a space and a comma after every but the last
> element. 
> 
>  That voice which says "There has Got to be a Better Way" is screaming
> at me that there must be a way to do this with a simple format, perhaps
> with the "~<:>" directive (?) -- but I cannot seem to decipher the 
> documentation on it...
> 
>  A cold Sam Adams Oktoberfest for a nice example!
> 
> 
> (defparameter *prerequisites* (list "G101" "G102" "G103"))
> 
> (with-output-to-string(ss)
>   (let ((count 0) 
>         (length (length *prerequisites*)))
>     (dolist (prerequisite *prerequisites*)
>       (format ss "~a~a" 
>                  prerequisite
>                 (if (< (incf count) length)
>                     ", "
>                   "")))))
> 
> 
> --> "G101, G102, G103"

Try:

USER(1): (defparameter *prerequisites* (loop for i from 101 to 150 collect (format nil "G~d" i)))
*PREREQUISITES*
USER(2): (format t ··@<--> ~{ ~a~^,·····@>~%" *prerequisites*)
-->  G101, G102, G103, G104, G105, G106, G107, G108, G109, G110, G111, G112,
G113, G114, G115, G116, G117, G118, G119, G120, G121, G122, G123, G124, G125,
G126, G127, G128, G129, G130, G131, G132, G133, G134, G135, G136, G137, G138,
G139, G140, G141, G142, G143, G144, G145, G146, G147, G148, G149, G150.
NIL
USER(3): 

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Will Fitzgerald
Subject: Re: Formatting Lists -- There Has to be a Better Way
Date: 
Message-ID: <NXiP3.1267$8D.7915@newsfeed.slurp.net>
I have a file, format-examples.lisp, with examples of format strings like
this. If DO vs. LOOP vs. DOLIST vs. recursion is hard to remember, format
strings are yet another little language, even more obscure.

Duane Rettig wrote in message <·············@beta.franz.com>...
>Try:
>
>USER(1): (defparameter *prerequisites* (loop for i from 101 to 150 collect
(format nil "G~d" i)))
>*PREREQUISITES*
>USER(2): (format t ··@<--> ~{ ~a~^,·····@>~%" *prerequisites*)
>-->  G101, G102, G103, G104, G105, G106, G107, G108, G109, G110, G111,
G112,
>G113, G114, G115, G116, G117, G118, G119, G120, G121, G122, G123, G124,
G125,
>G126, G127, G128, G129, G130, G131, G132, G133, G134, G135, G136, G137,
G138,
>G139, G140, G141, G142, G143, G144, G145, G146, G147, G148, G149, G150.
>NIL
>USER(3):
>
>--
>Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
>1995 University Ave Suite 275  Berkeley, CA 94704
>Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: John Watton
Subject: Re: Formatting Lists -- There Has to be a Better Way
Date: 
Message-ID: <7ul9el$nk3$1@nnrp1.deja.com>
In article <··················@newsfeed.slurp.net>,
  "Will Fitzgerald" <··········@no-spam-please-neodesic.com> wrote:
> I have a file, format-examples.lisp, with examples of format strings
like
> this.

Well don't just tease us. Let's have the file posted or a url supplied,
please.

--
John Watton
Alcoa Inc.


Sent via Deja.com http://www.deja.com/
Before you buy.
From: Will Fitzgerald
Subject: Re: Formatting Lists -- There Has to be a Better Way
Date: 
Message-ID: <iSDP3.909$971.5902@newsfeed.slurp.net>
John Watton wrote in message <············@nnrp1.deja.com>...
>In article <··················@newsfeed.slurp.net>,
>  "Will Fitzgerald" <··········@no-spam-please-neodesic.com> wrote:
>> I have a file, format-examples.lisp, with examples of format strings
>like
>> this.
>
>Well don't just tease us. Let's have the file posted or a url supplied,
>please.
>

It's just that the code is so secret I didn't want to just give it away...
but you've been nice, so I'll do it:

;; some examples of format statements.
;;

;; (setq l '(apple beet carrot delberry elderberry fig grape hoganberry jam
kelp loganberry))

;; from lisp-faq
(defun print-list (list &optional (elements-per-line 10))
  (fresh-line)
  (loop for i upfrom 1
        for element in list do
        (format t "~A ~:[~;~%~]" element (zerop (mod i elements-per-line))))
  (format t "~&~D~%" (length list)))

;;;? (print-list l 5)
;;;APPLE BEET CARROT DELBERRY ELDERBERRY
;;;FIG GRAPE HOGANBERRY JAM KELP
;;;LOGANBERRY
;;;11
;;;NIL
;;;? (print-list l 3)
;;;APPLE BEET CARROT
;;;DELBERRY ELDERBERRY FIG
;;;GRAPE HOGANBERRY JAM
;;;KELP LOGANBERRY
;;;11
;;;NIL
;;;

;; my variation.
(defun print-list (list &optional (elements-per-line 10))
    (let ((len (length list)))
      (labels ((sxiz (i)
                 (cond
                  ((= i len) 1)
                  ((zerop (mod i elements-per-line)) 2)
                  (t 0))))
        (fresh-line)
        (loop for i upfrom 1
              for element in list do
              (format t "~A~[, ~;.~%~;,~%~]" element
                      (sxiz i)))
        (format t "~&~D~%" len))))

;;;? (print-list l 5)
;;;APPLE, BEET, CARROT, DELBERRY, ELDERBERRY,
;;;FIG, GRAPE, HOGANBERRY, JAM, KELP,
;;;LOGANBERRY.
;;;11
;;;NIL
;;;? (print-list l 3)
;;;APPLE, BEET, CARROT,
;;;DELBERRY, ELDERBERRY, FIG,
;;;GRAPE, HOGANBERRY, JAM,
;;;KELP, LOGANBERRY.
;;;11
;;;NIL

;; from cltl-2 pg. 605

(defun print-list (list stream)
  (fresh-line)
  (format stream "~%;; ~{~<~%;; ~1:; ~S~>~^,~}.~%" list))

;; or without ;;

(defun print-list (list stream)
  (fresh-line)
  (format stream "~% ~{~<~% ~1:; ~S~>~^,~}.~%" list))

;; ? (print-list l t)
;;
;; ;;  APPLE, BEET, CARROT, DELBERRY, ELDERBERRY, FIG, GRAPE, HOGANBERRY,
;; ;;  JAM, KELP, LOGANBERRY.
;; NIL

;; how to do tabs.
(defun ntabs (n &optional (tab-size 8) (stream t))
  (format stream "~VT" (* n tab-size)))


;;; simple loop ... adds hyphen for all but last item.

(defmethod make-computer-deutsch ((self list) &optional (package *package*))
  (intern (format nil "~{~S~^-~}" self) package))

; ~{  ... iterate over list
; ~S  ... print item
; ~^  ... up & out (at end)?
;  -  ... put hyphen
; ~}  ... end iteration

;; regular old 'print each item in the list with spaces' :

(format nil "~{~S~^ ~}" '(this is a test))
(format nil "~{~a~^ ~}" '(this is a test))

;; (make-computer-deutsch '(goal plan conflict precondition blocked))
;; --> GOAL-PLAN-CONFLICT-PRECONDITION-BLOCKED

(format t "~%~10d,~5d, ~3d, ~1d ~5,'0d" 500 500 500 500 500)
;;        500,  500, 500, 500 00500

(format t "~%~5,3f ~10,3f ~10,20f" pi pi pi)
;; 3.142      3.142 3.14159265358979300000
From: Samir Barjoud
Subject: Re: Formatting Lists -- There Has to be a Better Way
Date: 
Message-ID: <wkaepe8w8k.fsf@mindspring.com>
"David J. Cooper" <·······@genworks.com> writes:

> Hello group,
> 
>  I am finding myself using the following idiom to achieve printout of
> lists with, for example, a space and a comma after every but the last
> element. 
> [...]

(defun ~cl (stream arg colon at-sign)
  (loop for e on arg
      do (princ (car e) stream)
      when (rest e)
      do (princ ", " stream)))

(format nil "Comma delimited list: ~/~cl/" '(1 2 3 4 5))

-- 
Samir Barjoud
·····@mindspring.com
From: Jason Trenouth
Subject: Re: Formatting Lists -- There Has to be a Better Way
Date: 
Message-ID: <7hgPODrzoT=vzDNB0KuJScxjV3o0@4ax.com>
On 20 Oct 1999 00:57:47 -0400, Samir Barjoud <·····@mindspring.com> wrote:

> "David J. Cooper" <·······@genworks.com> writes:
> 
> > Hello group,
> > 
> >  I am finding myself using the following idiom to achieve printout of
> > lists with, for example, a space and a comma after every but the last
> > element. 
> > [...]
> 
> (defun ~cl (stream arg colon at-sign)
>   (loop for e on arg
>       do (princ (car e) stream)
>       when (rest e)
>       do (princ ", " stream)))
> 
> (format nil "Comma delimited list: ~/~cl/" '(1 2 3 4 5))

I like "on" too, but you can do something slightly more elegant than the above
using LOOP's destructuring facility:

	(loop for (next . more) on *PREREQUISITES*
		do (princ next)
		when more do (princ ", "))

__Jason
From: Rainer Joswig
Subject: Re: Formatting Lists -- There Has to be a Better Way
Date: 
Message-ID: <joswig-2310991246530001@194.163.195.67>
In article <····························@4ax.com>, Jason Trenouth <·····@harlequin.com> wrote:

> On 20 Oct 1999 00:57:47 -0400, Samir Barjoud <·····@mindspring.com> wrote:
> 
> > "David J. Cooper" <·······@genworks.com> writes:
> > 
> > > Hello group,
> > > 
> > >  I am finding myself using the following idiom to achieve printout of
> > > lists with, for example, a space and a comma after every but the last
> > > element. 
> > > [...]
> > 
> > (defun ~cl (stream arg colon at-sign)
> >   (loop for e on arg
> >       do (princ (car e) stream)
> >       when (rest e)
> >       do (princ ", " stream)))
> > 
> > (format nil "Comma delimited list: ~/~cl/" '(1 2 3 4 5))
> 
> I like "on" too, but you can do something slightly more elegant than the above
> using LOOP's destructuring facility:
> 
>         (loop for (next . more) on *PREREQUISITES*
>                 do (princ next)
>                 when more do (princ ", "))
> 
> __Jason

or (ugly):

(loop for element in '(1 2 3)
      for nil = nil then (princ ", ")
      do (princ element))
From: Pierre R. Mai
Subject: Re: Formatting Lists -- There Has to be a Better Way
Date: 
Message-ID: <87hfjm76k7.fsf@orion.dent.isdn.cs.tu-berlin.de>
"David J. Cooper" <·······@genworks.com> writes:

>  I am finding myself using the following idiom to achieve printout of
> lists with, for example, a space and a comma after every but the last
> element. 
> 
>  That voice which says "There has Got to be a Better Way" is screaming
> at me that there must be a way to do this with a simple format, perhaps
> with the "~<:>" directive (?) -- but I cannot seem to decipher the 
> documentation on it...
> 
>  A cold Sam Adams Oktoberfest for a nice example!

> (defparameter *prerequisites* (list "G101" "G102" "G103"))

(format nil "~{~A~^, ~}" *prerequisites*)

--> "G101, G102, G103"

IIRC the HyperSpec has some examples for doing this in the entry for
the ~^ formatting directive (formatted output section).

Regs, Pierre.

-- 
Pierre Mai <····@acm.org>         PGP and GPG keys at your nearest Keyserver
  "One smaller motivation which, in part, stems from altruism is Microsoft-
   bashing." [Microsoft memo, see http://www.opensource.org/halloween1.html]
From: Howard R. Stearns
Subject: Re: Formatting Lists -- There Has to be a Better Way
Date: 
Message-ID: <380E09EC.40C37C11@elwood.com>
I have written the following extended examples into the margin of page
602 of my copy of CLtL2:

(format t "(~{~#[~;~]~s~^, ~})" list) 
 => () or (1) or (1, 2) or (1, 2, 3), etc

(format t "~{~s~#[~; and ~:;, ~]~}" list)
   => x 
or => x and y
or => x, y and z
etc

If you do this more than once, it's nice to package it up to uses in
~/.../ as Samir suggests.

I also use FORMAT-TEXTUAL-LIST, which comes with CLIM.  See the doc at
http://www.mikemac.com/mike/clim/page177.html

Here is my definition of format-textual-list.  It might be a good idea
to have a version of print-list-contents that could be used within
~/.../ (e.g., with ·@ and other arguments controlling separator and
conjunction, and with printer always being prin1).

(defun print-list-contents (printer list stream &key (separator " ")
				    conjunction)
  (do ((list list next)
       (next (cdr list) (cdr next)))
      ((atom next)
       (when (and conjunction (not next))
	 (write-string conjunction stream))
       (funcall printer (car list) stream)
       (when next
	 (write-string " . " stream)
	 (funcall printer next stream)))
    (funcall printer (car list) stream)
    (write-string separator stream)))

(defun print-vector-contents (printer vector stream &key (start 0)
				       end (separator " ") conjunction)
  (loop with end = (or end (length vector))
	for i from start below (1- end)
	do (funcall printer (elt vector i) stream)
	do (write-string separator stream)
	finally
	(progn
	  (when conjunction
	    (write-string conjunction stream))
	  (funcall printer (elt vector i) stream))))

;;; It would be nice if this took a SUPRESS-SEPARATOR argument that
;;; indicated that the separator should not be used when the
;;; conjunction is used.  Its hard to imagine why this isn't always
;;; done whenever conjunction is not nil, because users can get the
;;; current spec behavior by just including the separator character in
;;; their conjunction.  (Supress-separator is a little tricky to
;;; implement elegently.)

(defun FORMAT-TEXTUAL-LIST (sequence printer &key (stream
*standard-output*)
				     (separator ", ")
				     conjunction)
  (etypecase sequence
    (null)
    (cons (if (cdr sequence)
	      (print-list-contents printer sequence stream
				   :separator separator
				   :conjunction conjunction)
	      (funcall printer (car sequence) stream)))
    (vector (let ((length (length sequence)))
	      (case length
		(0)
		(1 (funcall printer (elt sequence 0) stream))
		(t (print-vector-contents printer sequence stream
					  :end length
					  :separator separator
					  :conjunction conjunction)))))))
From: Sam Steingold
Subject: Re: Formatting Lists -- There Has to be a Better Way
Date: 
Message-ID: <un1tc779e.fsf@ksp.com>
>>>> In message <·················@genworks.com>
>>>> On the subject of "Formatting Lists -- There Has to be a Better Way"
>>>> Sent on Tue, 19 Oct 1999 23:35:29 -0400
>>>> Honorable "David J. Cooper" <·······@genworks.com> writes:
 >> 
 >>  I am finding myself using the following idiom to achieve printout
 >> of lists with, for example, a space and a comma after every but the
 >> last element.

(format t "~{ ~a~^,~}" '(1 2 3 4 5))
 1, 2, 3, 4, 5

CLTL2 has a lot of great examples.
you might also want to see how I print `*features*' and `*modules*' in
`sysinfo' in base.lsp in http://www.podval.org/~sds/data/cllib.zip

-- 
Sam Steingold (http://www.podval.org/~sds/)
Micros**t is not the answer.  Micros**t is a question, and the answer is Linux,
(http://www.linux.org) the choice of the GNU (http://www.gnu.org) generation.
Oh Lord, give me the source code of the Universe and a good debugger!