The answer is complicated. There is an antagonism between
the “old Lisp way” of outputting a newline before the
line's contents (exemplified by the functions PRINT
and PPRINT
) and
the “Unix way” of outputting a newline after the line's
contents. Which one is “right”?
A newline convention is, by definition, a consistent way to use
the TERPRI
and FRESH-LINE
functions or - in FORMAT
notation -
~%
and ~&
directives in such a way that the
resulting output is properly subdivided into lines.
Three newline conventions are conceivable:
The most important criterion is interoperability. Two newline conventions are interoperable if, when parts of a program use one of the convention and other parts of the program use the other conventions, lines are still properly separated. It is easily seen that A and B are interoperable, B and C are interoperable as well, but A and C are not interoperable: When an output with convention A is followed by output in convention C, two lines are appended without a line separator. This should not happen.
Therefore, in what follows, we consider five kinds of programs:
Which of these five kinds of programs operation is satisfactory? Let us consider different criteria:
FRESH-LINE
prints a newline when
it is not needed, i.e. when it cannot tell for sure whether the
current column is 0? (This situation happens, for example, when
logging to a file: After the user has entered a line interactively,
the column on screen is 0, but since the input has not been echoed in
the log file, the column in the log file is usually not 0, and
FRESH-LINE
must output a newline. Then a blank
line is visible on the screen.)FRESH-LINE
omits a newline when it
would be needed?
(This is more rare, but can happen, for example, when standard output
and standard error are different streams but are joined outside the
Lisp implementation, at the OS level.
Such as in lisp | cat.)Is it possible to reliably output a blank line before or after a paragraph of text? I.e. what happens with
FRESH-LINE
, namely a conditional newline that is annullated if the
next output on the stream will be a
newline. (EXT:ELASTIC-NEWLINE
, see below.)Each approach has its advantages and disadvantages.
When used globally (i.e. no interoperability requirements), A, B, C can be compared as follows:
For CLISP built-ins, however, the interoperability requirement with both A and C is a major requirement. Therefore we have to choose B, and accept the drawbacks:
And to minimize the drawbacks, we recommend the user programs to use approach B or C, but not A.
Another drawback of B is, however, that in interactive sessions the cursor is nearly always positioned at the beginning of a line, pointing the user's focus to the wrong point and taking away a screen line.
To solve this, we introduce the concept of an elastic
newline, output by the function EXT:ELASTIC-NEWLINE
.
This is the converse of FRESH-LINE
: It waits for the next character
and outputs a newline when the next character is not a newline; then
the next character is processed normally.
As a FORMAT
directive, we write it ~.
.
EXT:ELASTIC-NEWLINE
followed by FRESH-LINE
leads to exactly one newline
always.
Elastic newline leads to a slightly different newline convention:
The five programs being considered are now:
FORCE-OUTPUT
. This is a general problem with buffered streams;
CLISP's FRESH-LINE
contains a workaround that is limited to
*STANDARD-OUTPUT*
and *ERROR-OUTPUT*
.Now criterium 1 is satisfied perfectly. We therefore choose B', not B, for use inside CLISP, and programs can use either A or C without problems during normal operation.
These notes document CLISP version 2.49.93+ | Last modified: 2018-02-19 |