1

I'm trying to understand how the \answer command from Donald Knuth's TeXbook works to do the same in LaTeX. Please explain how it works. Is it possible to implement exercises in the likeness of this idea so that the text of the exercise occurs twice: where this exercise is announced and before the answer?

In the TeXbook, appendix E, p. 418 written:

The \answer macro copies an answer into a file called answers.tex; then Appendix A reads this file by saying '\immediate\closeout\ans \ninepoint \input answers'. Each individual answer ends with a blank line; thus, \par must be used between the paragraphs of a long answer.

\newwrite\ans
\immediate\openout\ans=answers % file for answers to exercises
\outer\def\answer{\par\medbreak
  \immediate\write\ans{}
  \immediate\write\ans{\string\ansno\chapno.\the\exno:}
  \copytoblankline}
\def\copytoblankline{\begingroup\setupcopy\copyans}
\def\setupcopy{\def\do##1{\catcode`##1=\other}\dospecials
  \catcode`\|=\other \obeylines}
{\obeylines \gdef\copyans#1
  {\def\next{#1}%
  \ifx\next\empty\let\next=\endgroup %
  \else\immediate\write\ans{\next} \let\next=\copyans\fi\next}}

Notice the use of \dospecials here, to set up the verbatim copying. The \ttverbatim macro could have invoked \dospecials in the same way; but \ttverbatim is used quite frequently, so it was streamlined for speed.

  • The difference is that the answer.tex file will eventually be expanded, whereas \ttverbatim is printed as is. You might compare packages like endfloat which does the same thing (more or less). Actually, you could probably use endfloat. – John Kormylo Feb 27 '22 at 16:24
  • For example, see https://tex.stackexchange.com/questions/452596/auto-order-appendices – John Kormylo Feb 27 '22 at 16:29

1 Answers1

2

Knuth’s approach is very plain-TeX oriented. Presumably what you really want to do is be able to have in your document, e.g.,

\begin{question}
What is 6 times 9?
\end{question}

\begin{answer} 42 \end{answer}

...

\chapter{Answers to questions}

\printanswers

And have all the contents of the answer environments only output with \printanswers.

I’ve done exactly this using the approach of saving the contents of the answer environment to a file (plus a bit of wrapper) to make it possible to produce the output with \printanswers. Here's the code that I used:

\RequirePackage{verbatim} % ❶
\newwrite\ans@out % ❷
\def\answer@chapstart{\immediate\openout\ans@out=\jobname.ans} % ❸
\def\answer{%
  \@bsphack % ❹
  \let\do\@makeother\dospecials % ❺
  \immediate\write\ans@out{\string\preans} % ❻
  \immediate\write\ans@out{\string\par\string\noindent
       {\string\sc\space Exercise\string~\thequestion.}\quad}% ❻
  \immediate\write\ans@out{\string\vadjust{\string\nobreak}\relax} % ❼
  \catcode`\^^M\active % ❺
  \def\verbatim@processline{% ❺
    \immediate\write\ans@out
       {\the\verbatim@line}}%
  \verbatim@start}
\def\endanswer{%
  \immediate\write\ans@out{}% ❽
  \@esphack} % ❹
\def\preans{\if@nobreak\global\@nobreakfalse\else\bigfilbreak\fi} % ❾

\def\printanswers{\immediate\closeout\ans@out % ❿ @input{\jobname.ans} % ⓫ }

The hard work I defer to the package verbatim ❶ which lets me create verbatim-like environments which will have special handling for their contents. Here I use some code shamelessly stolen ❺ from the documentation for that package (do texdoc verbatim for more details) to tell LaTeX to write everything between \begin{answer} and \end{answer} to an external file.

The external file part is handled via TeX's write facilities. I created a new writer ❷, created a macro to open the file which was called as part of the definition of \chapter ❸ since I was outputting answers at the end of each chapter rather than at the end of the book¹ but in your case you might want to replace that line with

\immediate\openout\ans@out=\jobname.ans

so that the file is created right away. The \@bsphack\@esphack ❹ is probably not necessary here but it essentially tells LaTeX that this is code that isn't generating any output where it's called so that it's invisible space-wise. I wrote this code over 20 years ago, so I don't remember exactly what motivated that.²

I was lazy so I just output the code for formatting answers directly here ❻. If I were doing this today, I'd probably have it write instead something like \string\begin{theanswer}{\thequestion} before the output and \string\end{theanswer} afterwards. Prefixing \string to a macro is a primitive way of preventing expansion of the macro on write. Now, there are more robust ways to manage this, but again, you’re getting cut-and-pasted 20th century code here.

I think that at ❼ I was making sure that I didn't get a page break between the question number label and any displayed text that followed. At ❽ I was putting a blank line at the end of the question.³

The \preans code ❾ is something I stole from Knuth’s webmac.tex which will only break an answer across page boundaries if it’s longer than a page itself. It can make things look a bit nicer at the price of adding page count.

Finally, when it's time to print the answers, you close the \write ❿ and then read the generated file ⓫.


  1. It's always felt a little hostile to me to make readers flip so far to see the solutions to answers.
  2. Probably cargo culting.
  3. “You gotta make the back of the fence—that nobody will see— just as good looking as the front of the fence. Even though nobody will see it, you will know, and that will show that you’re dedicated to making something perfect.” –Paul Jobs
Don Hosek
  • 14,078