On Friday, July 20, 2012 3:44:58 PM UTC+2, pjb wrote:
> proton writes:
>
> > Hi all,
> >
> > I want to display a list with an iteration format directive which also
> > displays the iteration count. Is this possible?
> >
> > This is what I have:
> >
> > (setq table '((John 13 blue) (Mary 16 green) (Charles 10 yellow)))
> >
> > I want to display it like this:
> >
> > 1. Name: John, age: 13, color: blue.
> > 2. Name: Mary, age: 16, color: green.
> > 3. Name: Charles, age: 10, color: yellow.
> >
> > So I could use (format t "~{~X. Name: ~a, age: ~a, color: ~a.~%~}"
> > table)
> >
> > The ~X directive is what I am looking for: to display the iteration
> > number. Of course, I could use a loop, but I was wondering about the
> > possibility of doing it with format.
>
> (format t "~{~A. Name: ~a, age: ~a, color: ~a.~%~}"
> (mapcar (let ((i -1)) (lambda (x) (cons (incf i) x)))
> table))
>
> Inconvenient: you need to cons a new list.
>
>
> Another solution:
>
> (defvar *i* -1)
>
> (defun cl-user::i (stream argument colon at &rest parameters)
> "~W,I/i/ prints (incf *i* i) over W positions."
> (declare (ignore argument colon at))
> (destructuring-bind (&optional (width 0) (increment 1) &rest ignored) parameters
> (declare (ignore ignored))
> (format stream "~VD" width (incf *i* increment))))
>
> (let ((table '((John 13 blue) (Mary 16 green) (Charles 10 yellow)))
> (*i* 0))
> (format t "~:{~3/i/~:*. Name: ~a, age: ~a, color: ~a.~%~}" table))
>
> 1. Name: john, age: 13, color: blue.
> 2. Name: mary, age: 16, color: green.
> 3. Name: charles, age: 10, color: yellow.
>
> (let ((table '((John 13 blue) (Mary 16 green) (Charles 10 yellow)))
> (*i* 0))
> (format t "~:{~3,10/i/~:*. Name: ~:(~a~), age: ~a, color: ~a.~%~}"
> table))
> 10. Name: John, age: 13, color: blue.
> 20. Name: Mary, age: 16, color: green.
> 30. Name: Charles, age: 10, color: yellow.
>
> Notice in this solution we need to use ~:* to push back the argument
> that is necessarily eaten by ~/i/. Also, the formating function must
> either be in the CL-USER package, or you must qualify it:
> ~/my-package:i/.
>
>
> --
> __Pascal Bourguignon__
http://www.informatimago.com/
> A bad day in () is better than a good day in {}.
Thank you Pascal! That's a really neat solution with the ~/ directive.
To solve the package problem for the variable *i*, do you think it would be a good idea to define it as let over lambda?:
(let ((*i* -1))
(defun i (stream argument colon at &rest parameters)
... ))
Cheers.