Page 121

Once you understand the semantics of open and close, forget about them. Always use with-open-file.

Also, be aware that the read-line example at the bottom of the page may behave differently in different implementations. In some, the read-line will see the return following the expression you just entered and return an empty string, after which Lisp will see the "Please enter ..." and complain that Please is an unbound variable.

Page 122

In case you're curious, the name pseudo-cat comes from the Unix shell function cat, which is commonly used to print files to the screen. Why cat? It's short for "catenate." cat was designed to concatenate files. Unix designers like short names, not clear ones.

What does concatenation have to do with printing? First, in Unix, by default, all shell commands send the output to the screen. Second, by a not unreasonable extension, if you concatenate a file to nothing, you get the file. Unix designers like reusing existing commands, even if the semantics is unintuitive, so concatenating a file to nothing became the standard way to print the file to the screen.

Warning: Don't use a flag like EOF to signal the end of file value with the Lisp read function. If the input file has the symbol EOF in it, your function will be fooled into thinking the file has ended. See Exercise 2 of this chapter. This confusion can't happen with read-line or read-char because they return strings or characters, not symbols.

Page 123

Warning: The fact that read-from-string takes both optional and keyword arguments causes strange things to happen when you want the latter and not the former. See page 293.

Page 124

Though (format nil ...) is a very useful method for constructing strings, be aware that it's not printing, it's building a string. Use (format t ...) for printing, or (format stream ...) if you have a stream variable connected to a file.

There's a lot more about format in the Glossary at the back of the book. And if that's not enough, check out Section 22.3 at the Common Lisp Hyperspec.

Also, in general, use ~S for all debugging output. ~A will sometimes hide information critical to debugging an errant function, such as what package a symbol is coming from.

Page 126

You could also implement the circular buffer with a circular list. See page 208.