Reputation: 1137
The Common Lisp Hyperspec page for print
mentions this:
print is just like prin1 except that the printed representation of object is preceded by a newline and followed by a space.
This is the first time I've seen a function like this, and it threw me off the first time I used it, because I never expected that a function with such a common name might include an uncommon feature.
I'm looking for the original reason. I know it might simply be because that's how another then-common lisp might have done it, and common-lisp simply adopted it, but if that's the case I'm looking for the design reason in that other lisp.
I imagine it might have something to do with ensuring that the output is always readable with read
straight out of print
. Though I would've preferred a newline for this, I can guess that the trailing space might be so that in a stream, read
can know that it's the end of an object and return it immediately without having to wait for the rest of the stream (the following print
s). However, I still can't figure out the purpose behind the preceeding newline.
I've been looking through the HyperSpec, but I can't find a reason mentioned.
EDIT:
I looked into Common-Lisp's predecessors, specifically InterLisp, MacLisp, and MacLisp's predecessor Lisp 1.5.
Interlisp's (page 145 in this pdf) and Lisp 1.5's (page 140 in this pdf) print
function print the object followed by a newline.
It seems it was MacLisp that introduced this difference. I didn't find a reason in the original reference manual, and I only found the following on this revised reference manual:
Like PRIN1, PRINT outputs object to file in a form that can be understood by READ. However, object is output preceded by newline and followed by a space so that repeated calls to PRINT can be done without having the end of one object run into the begining of the next.
Of course, the trailing newline in the original definition would've sufficed for that purpose, so this reason doesn't seem valid.
EDIT 2:
As shown by Rainer Joswig's answer, it seems that this change appeared in Lisp 1.6 before MacLisp.
Upvotes: 3
Views: 1468
Reputation: 139411
See for example: PDP-6 LISP (LISP 1.6) Revised. (January 1967)
My guess would be that this variant of PRINT
(which writes a newline, then the s-expression in readable format and then a space) entered the MIT branch of Lisp because of its use in the Read Eval Print Loop. See page 1 and 17 of above. From PDP-6 Lisp 1.6 it moved into what was then called Maclisp and beyond.
Jon L White would know it.
Look at the example for the REPL, the read eval PRINT loop, on page 1.
Here I use a LispWorks Lisp listener, where the last closing parenthesis already makes READ
accept the s-expression and no further enter is necessary:
CL-USER 25 > (PROG NIL
A
(TERPRI)
(PRINT (EVAL (READ)))
(GO A))
(+ 12 12)
24
(+ 45 (*
34
12
12))
4941
Each result is on its own line. This is btw. also like the interaction on a MIT Lisp Machine - the last closing parenthesis enters the s-expression, the expression is evaluated and the value(s) printed.
Now imagine that it is defined to not print a newline first:
CL-USER 27 > (PROG NIL
A
(TERPRI)
(PRIN1 (EVAL (READ)))
(terpri)
(GO A))
(+ 1 2)3
(* 23 (+ 1
1
3))115
The result would be printed directly after the last closing parenthesis.
Peter Norvig gives the same reasoning in his book Paradigms of Artificial Intelligence Programming, page 231/232 (as noted by user dkim):
In Lisp, however, the function print puts in a newline before the object to be printed, and a space after. ... In UNIX there was only one reasonable policy, because all input to the UNIX interpreter (the shell) is terminated by newlines, so there is no need for a newline-before. In some Lisp interpreters, however, input can be terminated by a matching right parenthesis. In that case, a newline-before is needed, lest the output appear on the same line as the input.
Upvotes: 7
Reputation: 60084
Basically this is a REPL-only function, something along the lines of "poor man's trace
or debug
".
It's use case is something like
(map nil #'print list)
or, more generally,
(complex-traversal-map #'print weird-structure)
It inserts whitespace around the printed object to avoid interference
with the output of other print
calls.
What kind of whitespace is emitted has evolved over the decades.
It should have been called print-on-a-separate-line
but it had to be
short and easily guessable.
It's essentially "legacy" functionality, like rplaca
and rplacd
.
Upvotes: 2