7

I was looking over this answer and trying to understand the code, I am a super newbie (my second day) in LaTeX and I stuck at the following part of the code that i could not make it work in a not table environment. Here is the simplest form of what i do not understand.

\documentclass{article}
\begin{document}
    \newcommand*\f[3]{#1-#2-#3}
    \newcommand*\ex[1]{\f#1 - \expandafter\f\@firstofone}
     Try \ex{111}{221}
\end{document}

For some reason, which is not clear to me, in the code linked, the last argument is not consumed but it is left to be consumed by the expandafter\f\... construct. From what I understand \expandafter should first "run" \@firstofone , getting the {221} argument, stripping the brackets and feeding it to \f. This does not happen and I cannot figure out why.

  • 4
    you need \makeatletter to use a command with @ in its name – David Carlisle Jul 1 '17 at 20:26
  • It would be more practical \newcommand*\f[2]{\f#1 - \f#2}. – Manuel Jul 2 '17 at 9:44
  • @Manuel. It would in this case, I know. But I oversimplified the example. I am just learning, so I took out everything else that did not matter and left with that – Kostas Oreopoulos Jul 2 '17 at 10:35
9

You need to use \makeatletter for this to work, but it's the least.

The call \ex{111}{221} expands first to

\f 111 - \expandafter\f\@firstofone{221}

Now \f is expanded and it looks for three arguments, finding 1, 1 and 1, because TeX uses a single token if a brace is missing.

By the definition of \f this is expanded and the replacement text is reinserted in the input stream:

1-1-1 - \expandafter\f\@firstofone{221}

The tokens 1-1-1 - are not expandable and so they are sent to the next stage. Now it remains

\expandafter\f\@firstofone{221}

This will set \f aside and expand \@firstofone which just returns its (unbraced argument), so we get

\f221

that becomes 2-2-1. Thus the net effect of your code is to print

1-1-1 - 2-2-1

which doesn't seem really useful. Wherever you found it, don't trust it.

  • First of all thanks a lot for the answer. Actually f#1 prints 1-1-1 and the final print was 1-1-1 - 2-2-1. So 111 is not the first argument to f but each number in the first argument becomes an argument to f. My problem was indeed the missing makeatletter. Can you please make the correction about 111 being the first input so I can accept the answer? (in case anyone reads it) – Kostas Oreopoulos Jul 1 '17 at 20:46
  • @KostasOreopoulos Yes, I overlooked a pair of braces. – egreg Jul 1 '17 at 21:17
6

As egreg pointed out in his answer the use of \@firstofone isn't very useful and doesn't make a difference in this particular case. However, there are cases where it is useful. For completeness I'd like to give two examples.

Expandable macros

In Why the \expandafter\@firstoftwo idiom? a typical usecase for \@firstoftwo and \@secondoftwo in fully expandable macros is given. \@firstofone, kind of LaTeX's "identity function", is useful in similar contexts where only a single parameter should be handled:

\def\gobbleIfZero#1{%
  \ifnum#1=0
    \expandafter\@gobble
  \else
    \expandafter\@firstofone
  \fi
}

foo\gobbleIfZero{0}{bar}

foo\gobbleIfZero{123}{bar}

will give

foo

foobar

\@gobble (like \@firstofone) takes a single parameter but discards it and expands to "nothing".

Fixing of catcodes

A bit more tricky but also more interesting is the case where catcode changes are involved. When TeX is parsing arguments for macros, it fixes catcodes whenever the argument text is being read. This doesn't matter in your case as there are no catcodes changes here. But suppose following, somewhat contrived example is given:

\begingroup
\catcode`4=\active
\gdef 4{four}
\endgroup

\newcommand*\f{\catcode`4=\active}
\newcommand*\exA{\f}
\newcommand*\exB{\expandafter\f\@firstofone}

{\exA{345}--{345}}

{\exB{345}--{345}}

This results in

3four5-3four5

345-3four5

The first four lines define a global macro 4 which expands to four. Usually 4 has catcode 12 (other), so we change it to 13 (active) to be able to make a macro out of it. \f here brings this macros back into scope when executed.

When \exA is executed, the catcode of 4 is changed to 13 which afterwards makes 4 being expanded to four in both of following two groups. There are no parameters here at all, so this is straightforward.

On the other hand, in the \exB macro the first {345} part is processed by \@firstofone which just returns the same text, but fixes the catcode of 4 to 12. Once it is fixed, it can't be changed anymore! Even though the catcode change from \f is processed before the first 345, it won't have any effect on it. As the catcodes of the second {345} haven't been fixed yet, the changes will still apply to this group.

This behaviour comes in quite handy if you want to inject extra code into existings macros that deal with catcode changes, e.g. \verb (inspired by this TeX pearl):

\begingroup
\catcode`\/\active
\catcode`\_\active
\@firstofone{%
  \verb|%
  \catcode`\/\active \def/{\par}%
  \catcode`\_\active \def_#1_{\textcolor{blue}{#1}}%
}_\documentclass_{article}/_\begin_{document}/  We all love _\LaTeX_!/_\end_{document}|
\endgroup

which outputs

output

I don't know where you read about \@firstofone in the first place, but it might have been in one of these contexts.

  • That was really helpful. Especially the part of using catcodes! – Kostas Oreopoulos Jul 2 '17 at 10:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.