I'm reading Malcolm Clark's A Plain TeX Primer. On page 111 there's an exercise to define a macro that prints the current time. I've reproduced Clark's answer below:
\newcount\minleft
\newcount\timehour
\def\thetime{\timehour=\time
\divide\timehour by60 %gives 24 hour part of clock
\minleft=\timehour
\multiply\minleft by-60 %
\advance\minleft by\time %minutes after hour
\ifnum\time>720\advance\timehour by-12\fi\relax
\number\timehour:\ifnum\minleft<10 %
0\fi\relax\number\minleft
\ifnum\time>720~p.m.\else~a.m.\fi}
My problem is that I don't know what \relax is doing in lines 8 and 10 (after each \fi). When I use this macro, it prints the time as it's supposed to:
8:51 p.m.
If I delete the \relax in line 8, I get the time but with the hour missing:
:51 p.m.
If I delete the \relax in line 10 (and restore the \relax in line 8), the macro works again like it did the first time:
8:51 p.m.
I naively thought that the \fi that ends the \ifnum block ends the processing of whatever's going on in the \ifnum ... \fi, and that it wouldn't matter whether \relax is there or not, in either place. Clearly that's not the case, but I can't figure out what's happening in line 8, and also why the \relax doesn't seem to be necessary in line 10.
In a different context the author does explain that \relax is a "do nothing" command that (in this other context) prevents TeX from treating the expression before the \relax and after the \relax parts of the same expression. I get that. But concerning \relax after an \fi, he says:
"The \relax is probably not required, but it's always nice to have one in: perhaps an example of 'safe TeX'."
This might be good advice, but it is not enlightening.
I found the following questions about \relax on tex.se, but I don't think they answer my question (or at least I'm not smart enough to figure it out):
What is the difference between \relax and {}?
Difference between \relax and % for ending a line
Normal \relax vs. frozen \relax
So, what is \relax actually doing in this macro?
\relaxacts as a delimiter for any register evaluation. (A space token does this, too.) I’m sure we have some good Q&As on that … Do assignments need to be appended by % to remove the trailing white spaces? only scratches the surface. – Qrrbrbirlbel Oct 10 '13 at 01:43\relaxacting as a delimiter for a register evaluation here? – Richard Sullivan Oct 10 '13 at 02:38