The LaTeX kernel uses these two all over the place. For example, apparently the correct way of defining something like \ifeq{\macro 1}{\macro 2}{true}{false}
is (note Martin's response: each case should begin with \expandafter
)
\def\ifeq#1#2{%
\ifx#1#2\relax
\@firstoftwo
\else
\@secondoftwo
\fi
}
rather than
\def\ifeq#1#2#3#4{%
\ifx#1#2\relax
#3%
\else
#4%
\fi
}
However, they are equivalent as far as I can see:
\long\def\@firstoftwo#1#2{#1}
\long\def\@secondoftwo#1#2{#2}
There is even a \@firstofone
! It does this:
\long\def\@firstofone#1{#1}
Clearly there is no functional difference in using these macros than simply declaring one or two more arguments. I can see two possible minor differences off the top of my head:
\@firstoftwo
is a control sequence and, as such, gobbles subsequent spaces. This means we don't have to put a%
after it if it ends a line. Of course, we have to put%
in lots of other places, and TeX doesn't actually store the%
in the macro's expansion text, so this is truly minor.Macros defined with
\@firstoftwo
take two arguments fewer than those defined normally. Thus, TeX doesn't have to store the information that my\ifeq
macro takes those two arguments; it just refers to the storage already used by\@firstoftwo
and\@secondoftwo
. I guess this cuts down a little on memory usage.
Neither of these explains the purpose of\@firstofone
, since it could only possibly be useful when placed as the very last token of a macro, and even there it doesn't actually change the subsequent input, so it seems like it could just be eliminated. Is there some reason one would want to "set off" the next token like that? There is one more possibility:These are
\long\def
'd rather than just\def
'd. Thus, they can take multiple-paragraph arguments even if the macro using them is not\long
. I guess this allows you to make the last one or two arguments of a macro\long
when the others are not, but really, why not just use\long
when you really mean it?
Are there other advantages that I've missed? Do they have minor effects on speed or tricky interactions with expansion or execution that I'm missing? What is the real reason for this bit of obfuscation?