TL;DR
Never forget a space after a constant, unless you know precisely why you omit it (the \romannumeral trick is a prime example of why one might want to omit a space after a constant).
What happens?
What happens is that, due to the lack of a terminator for the number being evaluated, \expandafter is expanded; this touches \else, so, by rule, TeX inserts \relax (the “frozen” type) in front of \else (note that \expandafter has already gone). See Normal \relax vs. frozen \relax.
Thus you get the same as
\ifnum1=1\@firstoftwo\relax\else\expandafter\@secondoftwo\fi{true}{false}
Now expansion resumes, because the number is still unfinished and \@firstoftwo returns \relax; the test is then evaluated to true so TeX remains with
\relax\expandafter\@secondoftwo\fi{true}{false}
The \relax token is executed (or stored in the case of \edef) and \else is gobbled up and we get
《\relax》\expandafter\@secondoftwo\fi{true}{false}
Now \expandafter removes \fi and you end up with
《\relax》\@secondoftwo{true}{false}
so finally \relax false. If you do
\edef\test{\fail{1}{true}{false}}\show\test
the terminal will indeed show
> \test=macro:
->\relax false.
If you add \tracingmacros=1 before the call to \fail, the log file will show
\fail #1->\ifnum 1=#1\expandafter \@firstoftwo \else \expandafter \@secondoftwo
\fi
#1<-1
\@firstoftwo #1#2->#1
#1<-\relax
#2<-\else
\@secondoftwo #1#2->#2
#1<-true
#2<-false
confirming my analysis.
With 《...》 I denote tokens that have already been sent to the further level.
If the call is \fail{2}{true}{false}, the first step yields
\ifnum1=2\@firstoftwo\relax\else\expandafter\@secondoftwo\fi{true}{false}
Since the number is not yet finished, \@firstoftwo is expanded, returning \relax:
\ifnum1=2\relax\expandafter\@secondoftwo\fi{true}{false}
The test now can be evaluated to false, so everything up to \fi (as \else no longer is present) is removed without expansion, leading to
\fi{true}{false}
and \fi now disappears. Indeed, \edef\test{\fail{2}{true}{false}}\show\test prints
> \test=macro:
->{true}{false}.
on the terminal.
What about if you exchange \@firstoftwo and \@secondoftwo?
\documentclass{article}
\makeatletter
\newcommand\fail[1]{%
\ifnum1=#1% <- here a space is missing
\expandafter \@secondoftwo
\else
\expandafter \@firstoftwo
\fi
}
\makeatother
\begin{document}
\edef\test{\fail{1}{false}{true}}\show\test
\tracingmacros=1 \tracingonline=1
\fail{1}{false}{true}
\tracingmacros=0
\end{document}
Now the first level expansion will again add \relax, but we get
\ifnum1=1\@secondoftwo\relax\else\expandafter\@firstoftwo\fi{false}{true}
As before, \@secondoftwo is expanded, returning \else. Oh, but the number is yet unfinished, so a further frozen \relax is added, to yield
\ifnum1=1\relax\else\expandafter\@firstoftwo\fi{false}{true}
Now the conditional is evaluated to true, and the test is removed:
\relax\else\expandafter\@firstoftwo\fi{false}{true}
As before, \relax is sent down to the stomach and \else removes all tokens up to the matching \fi, without expansion:
《\relax》\fi{false}{true}
The \fi disappears and we remain with the equivalent of
\relax{false}{true}
\@firstoftwogobbles the\elsein the same way so that TeX discards everything until\fiwhen reading the\relaxand evaluating\ifnum. Therefore the two groups{true}{false}remain untouched and are printed to the pdf. Thank you. – jakun Jun 12 '19 at 12:46