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?
\relax
acts 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.\relax
acting as a delimiter for a register evaluation here?