From: Barry Margolin
Subject: Newlines in formatted output
Date: 
Message-ID: <1161rpINNp51@early-bird.think.com>
I've been leafing through Peter Norvig's book "Paradigms of Artificial
Intelligence Programming", and ran across a paragraph that I thought
deserved comment.  It's nothing major, but it affects many programs;
consider it my little "advice for the day".

On p.230, he discusses the fact that there's no standard convention for
when to print newlines in Lisp, before or after output; he compares it to
C, where everyone knows that you end a printf control with "\n" to go to
the next line (if you don't, you often end up with your Unix prompt on the
same line as the last output).

In my experience, Lisp actually makes it *easier* to get things write
regarding newlines in formatted output.  My policy is that whenever I want
formatted output to be on a line of its own, I start it with "~&" and end
it with "~%".  "~&" is not as well known as "~%", but it is a very nice
little feature that fills an important gap.  It outputs a newline *only* if
you're not already at the beginning of a line (it is the FORMAT equivalent
of the function FRESH-LINE).  The thing that makes this important is that
it facilitates using functions that produce output as building blocks.  In
most other languages, the program must keep track of whether it needs to
force a newline at various times; it's common for them to be overly
conservative and randomly produce extra blank lines.

Consider, for instance, a routine that prints the elements of a list, N
elements per line, and then prints something else (perhaps the number of
elements) on a new line.  A simple implementation might be:

(defun print-list (list &optional (elements-per-line 10))
  (terpri)
  (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)))

When the length of LIST is a multiple of ELEMENTS-PER-LINE, this will
result in a blank line between the list elements and the length.  To fix
this (without ~&) requires you to keep track of whether you just printed a
newline, e.g.

(defun print-list (list &optional (elements-per-line 10) &aux newline-printed)
  (terpri) 
  (setq newline-printed t)
  (loop for i upfrom 1
	for element in list do
    (setq newline-printed  (zerop (mod i elements-per-line)))
    (format t "~A ~:[~;~%~]" element newline-printed))
  (format t "~:[~%~;~]~D~%" newline-printed (length list)))

or determine whether you would have just printed a newline, e.g.

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

But with ~& it is as simple as the original version:

(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)))

Basically, the I/O system is now maintaining the NEWLINE-PRINTED state for
you.

Notice also the change from TERPRI to FRESH-LINE at the beginning of the
function.  While it wasn't too difficult to maintain of compute the newline
state within the function, there is no way to know the initial state.  I've
seen C functions that take the initial state as a parameter, but this is
cumbersome.  Look how much easier it is when you can just let the I/O
system keep track itself.

However, note that this is not a panacea.  CLtL doesn't require the
implementation to keep track of this at all times.  In particular, when
buffered input and output are mixed together on the same terminal, Lisp may
not be able to determine whether you're physically at the beginning of a
new line.  When Lisp can't determine, it's supposed to assume that a
newline is needed, just in case.  (There are similar problems with the
absolute tabbing FORMAT operator.)  However, in those cases, the program
wouldn't be able to do any better, so output that follows the above
convention will be at least as good as anything else.

Some people use ~& at both the beginning and end of the line.  As I said, I
generally use ~% at the end, since I know a priori that we're not at the
beginning of a line, and I like to make that knowledge apparent in the
program.  There's one exception: when it follows a ~A control where the
argument is likely to be a formatted string.  In this case, I don't know
whether the argument that was formatted by ~A ended in a newline or not, so
I use ~& to prevent a double newline (if I were interested in rendering the
output previsely, so that the user can tell whether the value ends in a
newline, I'd probably be using ~S rather than ~A).
-- 
Barry Margolin
System Manager, Thinking Machines Corp.

······@think.com          {uunet,harvard}!think!barmar
From: Richard A. O'Keefe
Subject: Re: Newlines in formatted output
Date: 
Message-ID: <11573@goanna.cs.rmit.oz.au>
In article <············@early-bird.think.com>, ······@think.com (Barry Margolin) writes:
> In my experience, Lisp actually makes it *easier* to get things write
> regarding newlines in formatted output.  My policy is that whenever I want
> formatted output to be on a line of its own, I start it with "~&" and end
> it with "~%".  "~&" is not as well known as "~%", but it is a very nice
> little feature that fills an important gap.  It outputs a newline *only* if
> you're not already at the beginning of a line (it is the FORMAT equivalent
> of the function FRESH-LINE).

Quintus Prolog includes a format/[2,3] command which is inspired by Common
Lisp.  In QP, we use "~n" where Common Lisp uses "~%" and "~N" where
Common Lisp uses "~&".  We knew a good idea when we saw one.  (In fact some
versions of C Prolog have a sl/[0,1] which corresponds to FRESH-LINE.)

Norvig's point remains:  there are a lot of people who think the right thing
to do in Lisp is to call TERPRI to _start_ a line (the etymology of the
name, TERminate PRInt, should dissuade them, but it doesn't).  When I
commented on this in comp.lang.c, saying that "\n" in C is appropriate for
ending lines, not starting, them, I received a lot of "hate" mail.

From my experience in working on Quintus Prolog low-level I/O, I can testify
that it is amazingly easy to implement FRESH-LINE at low cost, if you plan to
do so from the outset.  There are _so_ many good ideas in Common Lisp...

> However, note that this is not a panacea.  CLtL doesn't require the
> implementation to keep track of this at all times.  In particular, when
> buffered input and output are mixed together on the same terminal, Lisp may
> not be able to determine whether you're physically at the beginning of a
> new line.

Getting this right in QP required the I/O model to be capable of representing
"these streams affect the same device".  Especially in the case of output to
terminals, embedded cursor motion commands defeated even that.  Common Lisp
does about as well as one could reasonably expect, but of course a Lisp
environment (Interlisp-D or Xerox Common Lisp, for example) can do better.

-- 
You can lie with statistics ... but not to a statistician.