Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

format for list printing

6 views
Skip to first unread message

Erik Naggum

unread,
Sep 5, 1997, 3:00:00 AM9/5/97
to

* sshte...@cctrading.com
| I stand in awe before the power and convenience (as well as complexity)
| of the CL's format function.

the next step is then to realize its many serious limitations...

(do ((i 1 (1+ i))
(l <list> (cdr list)))
((endp l))
(format "~&~D. ~A" i (car l)))

(loop for elt in <list>
for i = 1 then (1+ i)
do (format "~&~D. ~A" i elt))

(let ((i 0))
(map nil (lambda (elt)
(format "~&~D. ~A" (incf i) elt))
<list>))

as for vectors (one-dimensional arrays), the changes necessary to the above
code fragments are trivial. the last form actually works unchanged.

#\Erik
--
404 You're better off without that file. Trust me.

Erik Naggum

unread,
Sep 5, 1997, 3:00:00 AM9/5/97
to

* sshte...@cctrading.com
| I see no reason for format not to be a "full fledged programming
| language". Since i/o is irrelevant to the language per se (Lisp, C,
| Pascal and Fortran all have similar output formatting facilities, with
| LIsp having the hairiest by far), I wonder why there is no
| text-formatting library that could be used from any language.

first, there was `format'. it was inbred over lots of generations and
acquired malign cancer in the colon, atsign, dollar, and percent. this
gave birth to "perl".

so, no, you don't want `format' to be a full-fledged programming language.

Bruno Haible

unread,
Sep 5, 1997, 3:00:00 AM9/5/97
to

Michael Greenwald <mich...@Radon.Stanford.EDU> wrote:
>
>> (let ((i 0)) (dolist (x '(a b c)) (format t "~d. ~a~%" (incf i) x)))
>
> If he's concerned about efficiency then he wouldn't be using FORMAT,
> since the string has to be parsed each call (ignoring format
> compilers, of course).

Really, you should make sure that your Common Lisp implementation supports
the ANSI CL `formatter' macro. Then you write

(format t (formatter "~d. ~a~%") (incf i) x)

so that the format string is parsed and compiled once and for all.
Decent implementations will even do that for you, by defining `format'
as a compiler-macro which looks at its second argument.

Bruno

Larry Hunter

unread,
Sep 5, 1997, 3:00:00 AM9/5/97
to

sshte...@cctrading.com asks:

Does this imply that if I am using a "decent implementations" (say,
CLISP), I should not worry about calling format with the same string 2000
times (whether the function is compiled or not)? Or should I define a
local var and set it to (formatter whatever)?

A quick test in Franz Allegro CL 4.3.1 on a unix box shows that it depends
on the optimization settings. If you compile with (optimize (speed 1)
(debug 2)) -- the default -- then using a local variable to hold the
formatter closure is about 25% faster. However, if you compile with
(optimize (speed 3) (debug 0)), then they are effectively identical.

Larry


USER(52): (declaim (optimize (speed 1) (debug 2)))
T
USER(53): (defun test-format1 ()
(with-open-file (stream "foo" :direction :output :if-exists :supersede)
(dotimes (i 10000)
(format stream "~%<~{~a ~}>" '(a b c d e f 1 2 3 4 5 "foo" "bar"
"baz" #'(b l a t))))))
TEST-FORMAT1
USER(54): (defun test-format2 ()
(with-open-file (stream "foo" :direction :output :if-exists :supersede)
(let ((formatter (formatter "~%<~{~a ~}>" )))
(dotimes (i 10000)
(format stream formatter '(a b c d e f 1 2 3 4 5 "foo" "bar"
"baz" #'(b l a t)))))))
TEST-FORMAT2
USER(55): (compile 'test-format1)
TEST-FORMAT1
NIL
NIL
USER(56): (compile 'test-format2)
TEST-FORMAT2
NIL
NIL
USER(57): (time (test-format1))
; cpu time (non-gc) 7,600 msec user, 80 msec system
; cpu time (gc) 80 msec user, 0 msec system
; cpu time (total) 7,680 msec user, 80 msec system
; real time 7,979 msec
; space allocation:
; 650,116 cons cells, 0 symbols, 1,845,864 other bytes
NIL
USER(58): (time (test-format2))
; cpu time (non-gc) 5,750 msec user, 70 msec system
; cpu time (gc) 40 msec user, 0 msec system
; cpu time (total) 5,790 msec user, 70 msec system
; real time 6,125 msec
; space allocation:
; 440,098 cons cells, 0 symbols, 801,040 other bytes
NIL
USER(59): (declaim (optimize (speed 3) (debug 0)))
T
USER(63): (compile 'test-format1)
TEST-FORMAT1
NIL
NIL
USER(66): (compile 'test-format2)
TEST-FORMAT2
NIL
NIL
USER(67): (time (test-format1))
; cpu time (non-gc) 5,710 msec user, 70 msec system
; cpu time (gc) 60 msec user, 0 msec system
; cpu time (total) 5,770 msec user, 70 msec system
; real time 5,995 msec
; space allocation:
; 430,098 cons cells, 0 symbols, 801,040 other bytes
NIL
USER(68): (time (test-format2))
; cpu time (non-gc) 5,790 msec user, 100 msec system
; cpu time (gc) 50 msec user, 0 msec system
; cpu time (total) 5,840 msec user, 100 msec system
; real time 6,183 msec
; space allocation:
; 440,098 cons cells, 0 symbols, 801,040 other bytes
NIL
USER(69):

Erik Naggum

unread,
Sep 6, 1997, 3:00:00 AM9/6/97
to

* Larry Hunter


| A quick test in Franz Allegro CL 4.3.1 on a unix box shows that it
| depends on the optimization settings. If you compile with (optimize
| (speed 1) (debug 2)) -- the default -- then using a local variable to
| hold the formatter closure is about 25% faster. However, if you compile
| with (optimize (speed 3) (debug 0)), then they are effectively identical.

optimization in Allegro CL 4.3.1 is controlled by compiler switches. these
are variables that either hold a value or a function. if the value is
non-nil or the value of the function is non-nil, the switch is true.

e.g., compilation of format strings is controlled by

compiler:compile-format-strings-switch

which has a functional value by default.

user(15): (describe compiler:compile-format-strings-switch)
#<Function speed > space @ #x165bd2> is a compiled-function.
The arguments are (safety space speed debug)

we infer that these switch functions receives the values of the various
`optimize' declarations when called by the compiler, so we can write our
own, or we could use a constant value for the appropriate switch.

incidentally, it is sufficient to (declaim (optimize (space 0))) to get
Allegro CL to compile format strings if speed is at least 1.

this is documented in the Allegro CL User Guide, and you should get some
messages when you fire up Allegro CL that indicate how to learn more:

;; Optimization settings: safety 1, space 1, speed 1, debug 2.
;; For a complete description of all compiler switches given the current
;; optimization settings evaluate (explain-compiler-settings).

Michael Greenwald

unread,
Sep 7, 1997, 3:00:00 AM9/7/97
to

hai...@ma2s2.mathematik.uni-karlsruhe.de (Bruno Haible) writes:

>Michael Greenwald <mich...@Radon.Stanford.EDU> wrote:
>>
>>> (let ((i 0)) (dolist (x '(a b c)) (format t "~d. ~a~%" (incf i) x)))
>>
>> If he's concerned about efficiency then he wouldn't be using FORMAT,
>> since the string has to be parsed each call (ignoring format
>> compilers, of course).

>Really, you should make sure that your Common Lisp implementation supports
>the ANSI CL `formatter' macro.

That's an example of what I meant by "format compilers".

0 new messages