Some tricks:
Instead of
\expandafter\first
\expandafter\second
\expandafter\third
\expandafter\fourth
\expandafter\fifth
\expandafter\sixth
\expandafter\seventh
\expandafter\eighth
\expandafter\ninth
\expandafter\tenth
\eleventh
you can in many situations do:
\newcommand\exchange[2]{#2#1}
\expandafter\exchange\expandafter{\eleventh}{%
\first\second\third\fourth\fifth\sixth\seventh\eighth\ninth\tenth
}
Instead of
\expandafter\expandafter\expandafter\first
\expandafter\expandafter\expandafter\second
\expandafter\expandafter\expandafter\third
\expandafter\expandafter\expandafter\fourth
\expandafter\expandafter\expandafter\fifth
\expandafter\expandafter\expandafter\sixth
\expandafter\expandafter\expandafter\seventh
\expandafter\expandafter\expandafter\eighth
\expandafter\expandafter\expandafter\ninth
\expandafter\expandafter\expandafter\tenth
\eleventh
you can do:
\newcommand\exchange[2]{#2#1}
\expandafter\first
\expandafter\second
\expandafter\third
\expandafter\fourth
\expandafter\fifth
\expandafter\sixth
\expandafter\seventh
\expandafter\eighth
\expandafter\ninth
\expandafter\tenth
\romannumeral0%
\exchange{ }{\expandafter\expandafter\expandafter}\eleventh
or
\newcommand\exchange[2]{#2#1}
\expandafter\exchange\expandafter{%
\romannumeral0%
\exchange{ }{\expandafter\expandafter\expandafter}\eleventh
}{%
\first\second\third\fourth\fifth\sixth\seventh\eighth\ninth\tenth
}
Assume you wish the second token to be expanded before processing/expanding the first token.
You might do: \expandafter\first\second
.
Now assume you wish K-level-expansion of the second token to have taken place before processing/expanding the first token.
With K=1 you can place 1 \expandafter
before \first
:
\expandafter\first
\second
With K=2 you can place 3 \expandafter
before \first
:
\expandafter\expandafter
\expandafter\first
\second
With K=3 you can place 7 \expandafter
before \first
:
\expandafter\expandafter
\expandafter \expandafter
\expandafter\expandafter
\expandafter \first
\second
With K=L you can place ∑i=1..L(2L-i)=∑i=1..L(2i-1)=2L-1 \expandafter
before \first
.
This way the amount of \expandafter
that needs to be placed before \first
increases exponentially.
Using nested \romannumeral
-expansion, which takes its toll on the semantic nest, you can also have a linear increase of the amount of tokens needed:
\@ifdefinable\stopromannumeral{\chardef\stopromannumeral=`\^^00}%
K=1 - 1-level-expansion of \second
shall have taken place before processing/expanding \first
:
\expandafter\first
\second
K=2 - 2-level-expansion of \second
shall have taken place before processing/expanding \first
:
\expandafter\first
\romannumeral\expandafter\expandafter\expandafter\stopromannumeral
\second
K=3 - 3-level-expansion of \second
shall have taken place before processing/expanding \first
:
\expandafter\first
\romannumeral\expandafter\expandafter\expandafter\stopromannumeral
\romannumeral\expandafter\expandafter\expandafter\stopromannumeral
\second
K=4 - 4-level-expansion of \second
shall have taken place before processing/expanding \first
:
\expandafter\first
\romannumeral\expandafter\expandafter\expandafter\stopromannumeral
\romannumeral\expandafter\expandafter\expandafter\stopromannumeral
\romannumeral\expandafter\expandafter\expandafter\stopromannumeral
\second
K=5 - 5-level-expansion of \second
shall have taken place before processing/expanding \first
:
\expandafter\first
\romannumeral\expandafter\expandafter\expandafter\stopromannumeral
\romannumeral\expandafter\expandafter\expandafter\stopromannumeral
\romannumeral\expandafter\expandafter\expandafter\stopromannumeral
\romannumeral\expandafter\expandafter\expandafter\stopromannumeral
\second
K=6 - 6-level-expansion of \second
shall have taken place before processing/expanding \first
:
\expandafter\first
\romannumeral\expandafter\expandafter\expandafter\stopromannumeral
\romannumeral\expandafter\expandafter\expandafter\stopromannumeral
\romannumeral\expandafter\expandafter\expandafter\stopromannumeral
\romannumeral\expandafter\expandafter\expandafter\stopromannumeral
\romannumeral\expandafter\expandafter\expandafter\stopromannumeral
\second
Get the picture?
For K-level-expansion of \second
you need (K-1) instances of
\romannumeral\expandafter\expandafter\expandafter\stopromannumeral
between \expandafter\first
and \second
.
\expandafter\endcsname
-trick:
Assume you have foo
and bar
and baz
and wish to get the sequence \foo\bar\baz
, consisting of the tokens \foo
and \bar
and \baz
.
This does the trick:
\csname foo\expandafter\endcsname
\csname bar\expandafter\endcsname
\csname baz\endcsname
Assume you need to construct a control-sequence-token from its name but don't like to combine \csname..\endcsname
with "\expandafter
-orgies":
Maybe the macro \CsTokenFromCsName
is your friend:
\makeatletter
\@ifdefinable\CsTokenFromCsName{%
\long\def\CsTokenFromCsName#1#{\romannumeral\InnerCsTokenFromCsName{#1}}%
}%
\newcommand\InnerCsTokenFromCsName[2]{%
\expandafter\exchange\expandafter{\csname#2\endcsname}{0 #1}%
}%
\newcommand\exchange[2]{#2#1}%
\makeatother
\CsTokenFromCsName{foobar}
→ \foobar
\CsTokenFromCsName\newcommand{foobar}...
→ \newcommand\foobar...
\CsTokenFromCsName\global\long\def{foobar}...
→ \global\long\def\foobar...
\CsTokenFromCsName\meaning{foobar}
→ \meaning\foobar
\CsTokenFromCsName\string{foobar}
→ \string\foobar
\CsTokenFromCsName\CsTokenFromCsName\global\let{foo}={bar}
→
\CsTokenFromCsName\global\let\foo={bar}
→
\global\let\foo=\bar
A nice tool for tail-recursive macros is \PassFirstToSecond
, defined as \newcommand\PassFirstToSecond[2]{#2{#1}}
:
Assume a tail-recursive macro which calls itself again and again, with modified arguments, until some termination-condition which depends on the tail-recursive macro's arguments is fulfilled.
You can nest calls to \PassFirstToSecond
within \PassFirstToSecond
's second argument in order to first modify the last argument as needed, then to modify the last but one argument as needed, then to modify the last but two argument as needed, etc.
Can look like this:
\newcommand\TailRecursiveMacro[9]{%
\if⟨termination-condition that depends on #1..#9 is fulfilled⟩
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{%
⟨Things to do with #1..#9 in case termination-condition that depends on #1..#9 is fulfilled⟩%
}{%
% Prepare the next iteration as the termination-condition is not fulfilled:
\expandafter\PassFirstToSecond\expandafter{%
⟨Things to do for obtaining the new argument #9, probably a \romannumeral0-expansion-thing⟩%
}{%
\expandafter\PassFirstToSecond\expandafter{%
⟨Things to do for obtaining the new argument #8, probably a \romannumeral0-expansion- thing⟩%
}{%
\expandafter\PassFirstToSecond\expandafter{%
⟨Things to do for obtaining the new argument #7, probably a \romannumeral0-expansion- thing⟩%
}{%
\expandafter\PassFirstToSecond\expandafter{%
⟨Things to do for obtaining the new argument #6, probably a \romannumeral0-expansion-thing⟩%
}{%
\expandafter\PassFirstToSecond\expandafter{%
⟨Things to do for obtaining the new argument #5, probably a \romannumeral0-expansion-thing⟩%
}{%
\expandafter\PassFirstToSecond\expandafter{%
⟨Things to do for obtaining the new argument #4, probably a \romannumeral0-expansion-thing⟩%
}{%
\expandafter\PassFirstToSecond\expandafter{%
⟨Things to do for obtaining the new argument #3, probably a \romannumeral0-expansion-thing⟩%
}{%
\expandafter\PassFirstToSecond\expandafter{%
⟨Things to do for obtaining the new argument #2, probably a \romannumeral0-expansion-thing⟩%
}{%
\expandafter\PassFirstToSecond\expandafter{%
⟨Things to do for obtaining the new argument #1, probably a \romannumeral0-expansion-thing⟩%
}{%
\TailRecursiveMacro
}%
}%
}%
}%
}%
}%
}%
}%
}%
}%
}%
The \romannumeral0
-expansion-thingie is mentioned in Bruno Le Floch's answer.
You can combine this with an additional level of \romannumeral
-expansion to ensure in expansion-contexts that regardless the amount of iterations the result will always be delivered after two expansion-steps/after two "hits" with \expandafter
—can look like this:
\newcommand\TailRecursiveMacro[9]{%
% Let's start \TailRecursiveMacro's \romannumeral-expansion:
\romannumeral
\if⟨termination-condition that depends on #1..#9 is fulfilled⟩
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{%
% Let's stop \TailRecursiveMacro's \romannumeral-expansion:
0⟨space token⟩%
⟨Things to do/deliver with #1..#9 in case termination-condition that depends on #1..#9 is fulfilled⟩%
}{%
% Prepare the next iteration as the termination-condition is not fulfilled:
\expandafter\PassFirstToSecond\expandafter{%
⟨Things to do for obtaining the new argument #9, probably a \romannumeral0-expansion-thing⟩%
}{%
\expandafter\PassFirstToSecond\expandafter{%
⟨Things to do for obtaining the new argument #8, probably a \romannumeral0-expansion- thing⟩%
}{%
\expandafter\PassFirstToSecond\expandafter{%
⟨Things to do for obtaining the new argument #7, probably a \romannumeral0-expansion- thing⟩%
}{%
\expandafter\PassFirstToSecond\expandafter{%
⟨Things to do for obtaining the new argument #6, probably a \romannumeral0-expansion-thing⟩%
}{%
\expandafter\PassFirstToSecond\expandafter{%
⟨Things to do for obtaining the new argument #5, probably a \romannumeral0-expansion-thing⟩%
}{%
\expandafter\PassFirstToSecond\expandafter{%
⟨Things to do for obtaining the new argument #4, probably a \romannumeral0-expansion-thing⟩%
}{%
\expandafter\PassFirstToSecond\expandafter{%
⟨Things to do for obtaining the new argument #3, probably a \romannumeral0-expansion-thing⟩%
}{%
\expandafter\PassFirstToSecond\expandafter{%
⟨Things to do for obtaining the new argument #2, probably a \romannumeral0-expansion-thing⟩%
}{%
\expandafter\PassFirstToSecond\expandafter{%
⟨Things to do for obtaining the new argument #1, probably a \romannumeral0-expansion-thing⟩%
}{%
% \TailRecursiveMacro's \romannumeral-expansion is already started.
% So via \expandafter\@gobble make sure that the next iteration does
% not also start \romannumeral-expansion:
\expandafter\@gobble\TailRecursiveMacro
}%
}%
}%
}%
}%
}%
}%
}%
}%
}%
}%
You can check whether an argument is empty as follows:
With e-TeX-extensions:
%%=============================================================================
%% Check whether argument is empty:
%%=============================================================================
%% \CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
\newcommand\CheckWhetherNull[1]{%
\romannumeral0\if\relax\detokenize{#1}\relax
\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{\@firstoftwo\expandafter{} \@firstoftwo}%
{\@firstoftwo\expandafter{} \@secondoftwo}%
}%
Without e-TeX-extensions:
%%=============================================================================
%% Check whether argument is empty:
%%=============================================================================
%% \CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\CheckWhetherNull[1]{%
\romannumeral0\expandafter\@secondoftwo\string{\expandafter
\@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
\@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
\@secondoftwo\string}\@firstoftwo\expandafter{} \@secondoftwo}%
{\@firstoftwo\expandafter{} \@firstoftwo}%
}%
You can check whether a macro argument's first token is an explicit catcode-1(begin group)-character-token as follows:
%%-----------------------------------------------------------------------------
%% Check whether argument's first token is an explicit catcode-1-character:
%%.............................................................................
%% \CheckWhetherBrace{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked has leading
%% catcode-1-token>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked has no leading
%% catcode-1-token>}%
\newcommand\CheckWhetherBrace[1]{%
\romannumeral0\expandafter\@secondoftwo\expandafter{\expandafter{%
\string#1.}\expandafter\@firstoftwo\expandafter{\expandafter
\@secondoftwo\string}\expandafter\expandafter\@firstoftwo{ }{}%
\@firstoftwo}{\expandafter\expandafter\@firstoftwo{ }{}\@secondoftwo}%
}%
If it is about token-sequences that don't contain curly braces/that do neither contain explicit catcode-1(begin group)-character-tokens, nor contain explicit catcode-2(end group)-character-tokens, then you can check by means of delimited arguments, i.e. by means of expansion only, whether an argument is/is not an element of a set of token-sequences/which element of the set of token-sequences the argument is.
Assume, you wish to check whether an argument either is empty or is A1
or is B2
or is C3
or is D4
, and if so, which one it is:
The gist is:
Use a macro with argument-delimiter !!A1!B2!C3!D4!
and see where the delimiter-matching takes place.
Of course you first need to ensure that the argument which is to be checked does not contain !
as otherwise the argument which is to be checked might contain the entire delimiter or might in erroneous ways complete the delimiter, which would lead to erroneous delimiter-matching:
\documentclass{article}
\makeatletter
% Use a definition of \CheckWhetherNull as presented above:
\newcommand\CheckWhetherNull[1]{%
\romannumeral0\if\relax\detokenize{#1}\relax
\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{\@firstoftwo{\expandafter}{} \@firstoftwo}%
{\@firstoftwo{\expandafter}{} \@secondoftwo}%
}%
\@ifdefinable\GobbletoExclam{\long\def\GobbletoExclam#1!{}}%
\@ifdefinable\Forkfork{\long\def\Forkfork#1!!A1!B2!C3!D4!#2#3!!!!{#2}}%
\newcommand\Fork[7]{%
% #1 - argument to check
% #2 - tokens in case Argument is empty
% #3 - tokens in case Argument is A1
% #4 - tokens in case Argument is B2
% #5 - tokens in case Argument is C3
% #6 - tokens in case Argument is D4
% #7 - tokens in case Argument is something else
\expandafter\CheckWhetherNull\expandafter{\GobbletoExclam#1!}{%
% #1 does not contain "!", so continue testing:
\Forkfork!#1!A1!B2!C3!D4!{#2}% <- Argument #1 is empty
!!#1!B2!C3!D4!{#3}% <- Argument #1 is A1
!!A1!#1!C3!D4!{#4}% <- Argument #1 is B2
!!A1!B2!#1!D4!{#5}% <- Argument #1 is C3
!!A1!B2!C3!#1!{#6}% <- Argument #1 is D4
!!A1!B2!C3!D4!{#7}% <- Argument #1 is something else without "!"
!!!!%
}{%
#7% <- Argument #1 is something else with "!"
}%
}%
\makeatother
\begin{document}
\Fork{}%
{You have emptiness.}%
{You have A1.}%
{You have B2.}%
{You have C3.}%
{You have D4.}%
{You have something else.}%
\Fork{A1}%
{You have emptiness.}%
{You have A1.}%
{You have B2.}%
{You have C3.}%
{You have D4.}%
{You have something else.}%
\Fork{B2}%
{You have emptiness.}%
{You have A1.}%
{You have B2.}%
{You have C3.}%
{You have D4.}%
{You have something else.}%
\Fork{C3}%
{You have emptiness.}%
{You have A1.}%
{You have B2.}%
{You have C3.}%
{You have D4.}%
{You have something else.}%
\Fork{D4}%
{You have emptiness.}%
{You have A1.}%
{You have B2.}%
{You have C3.}%
{You have D4.}%
{You have something else.}%
\Fork{!A1!B2!C3!D4!}%
{You have emptiness.}%
{You have A1.}%
{You have B2.}%
{You have C3.}%
{You have D4.}%
{You have something else.}%
\Fork{E5}%
{You have emptiness.}%
{You have A1.}%
{You have B2.}%
{You have C3.}%
{You have D4.}%
{You have something else.}%
\end{document}

(Be aware that with the trick above no temporary assignment was performed and no \if..
-primitive was used.)
Assume you have a list of L arguments and wish to keep/select only the K-th argument thereof while removing the other arguments from the token-stream.
I can offer the macro \KeepKthOfLArguments
:
\documentclass{article}
\makeatletter
%% Code for \KeepKthOfLArguments:
%%=============================================================================
\newcommand\PassFirstToSecond[2]{#2{#1}}%
%%=============================================================================
%% Check whether argument is empty:
%%=============================================================================
%% \CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\CheckWhetherNull[1]{%
\romannumeral0\expandafter\@secondoftwo\string{\expandafter
\@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
\@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
\@secondoftwo\string}\@firstoftwo\expandafter{} \@secondoftwo}%
{\@firstoftwo\expandafter{} \@firstoftwo}%
}%
%%=============================================================================
%% Keep only the K-th of L consecutive undelimited arguments.
%% ( IF K < 1 OR K > L just remove L consecutive undelimited arguments. )
%%=============================================================================
%% \KeepKthOfLArguments{<integer number K>}%
%% {<integer number L>}%
%% <sequence of L consecutive undelimited arguments>
%%
%% If L < 1 yields nothing.
%% Else:
%% If K >= 1 and K < L yields:
%% <K-th undelimited argument from <sequence of L consecutive undelimited
%% arguments>>
%% If K < 1 or K > L
%% (-> there is no K-th argument in the
%% <sequence of L consecutive undelimited arguments> )
%% yields nothing but removal of <sequence of L consecutive
%% undelimited arguments>
\newcommand\KeepKthOfLArguments[2]{%
\romannumeral0%
% #1: <integer number K>
% #2: <integer number L>
\expandafter\UD@KeepKthOfLArgumentsKSmallerOneFork
\expandafter{\romannumeral\number\number#1 000\expandafter}%
\expandafter{\romannumeral\number\number#2 000}%
}%
%%-----------------------------------------------------------------------------
\newcommand\UD@KeepKthOfLArgumentsKSmallerOneFork[2]{%
% #1: <K letters m>
% #2: <L letters m >
\CheckWhetherNull{#1}{% K is smaller than one:
\UD@KeepKthOfLArgumentsRemoveNArguments{#2}{ }{}%
}{% K is not smaller than one:
\expandafter\PassFirstToSecond
\expandafter{%
\@firstoftwo{}#1%
}{%
\UD@KeepKthOfLArgumentsEvaluateLMinusKDifferenceLoop{#1}{#2}%
}{#2}%
}%
}%
%%-----------------------------------------------------------------------------
\newcommand\UD@KeepKthOfLArgumentsEvaluateLMinusKDifferenceLoop[4]{%
% #1: <K letters m>
% #2: <L letters m>
% (For detecting whether K>L or K<=L, during the loop letters m will
% be removed both from #1 and #2 until at least one of these arguments
% is empty.
% When the loop terminates with 0<K<=L, #1 will be empty and #2
% will hold an amount of letters m corresponding to the the
% difference L-K.
% When the loop terminates with K>L, #1 will not be empty and #2
% will be empty.
% )
% #3: <K-1 letters m>
% #4: <L letters m>
% (#3 and #4 will be left untouched during the loop so they can be
% used for performing appropriate action when loop terminates as
% it is known whether K>L.)
\CheckWhetherNull{#1}{% We have K<=L:
\UD@KeepKthOfLArgumentsRemoveNArguments{%
#3%
}{%
\UD@KeepKthOfLArgumentsRemoveNArguments{#2}{ }%
}{}%
}{%
\CheckWhetherNull{#2}{% We have K>L:
\UD@KeepKthOfLArgumentsRemoveNArguments{#4}{ }{}%
}{% We don't know yet whether K<=L or K>L, thus remove letters m and
% do another iteration:
\expandafter\PassFirstToSecond
\expandafter{%
\@firstoftwo{}#2%
}{%
\expandafter\UD@KeepKthOfLArgumentsEvaluateLMinusKDifferenceLoop
\expandafter{%
\@firstoftwo{}#1%
}%
}{#3}{#4}%
}%
}%
}%
%%-----------------------------------------------------------------------------
%% \UD@KeepKthOfLArgumentsRemoveNArguments{<N letters m>}%
%% {<argument 1>}%
%% {<argument 2>}%
%% <sequence of consecutive
%% undelimited arguments>
%%.............................................................................
%% Removes the first N undelimited arguments from the <sequence of
%% consecutive undelimited arguments>, then inserts
%% <argument 1><argument 2>
%%
%% On the one hand when providing <argument 2> empty, you can use
%% <argument 1> for nesting calls to \UD@KeepKthOfLArgumentsRemoveNArguments.
%% On the other hand you can provide a <space token> for stopping
%% \romannumeral-expansion as <argument 1> and have the
%% macro grab the <K-th undelimited argument> from the <sequence of L
%% consecutive undelimited arguments> as <argument 2>.
%%
\newcommand\UD@KeepKthOfLArgumentsRemoveNArguments[3]{%
%% #1: <N letters m>
%% #2: <Argument 1>
%% #3: <Argument 2>
\CheckWhetherNull{#1}{#2#3}{%
\@firstoftwo{%
\expandafter\UD@KeepKthOfLArgumentsRemoveNArguments
\expandafter{%
\@firstoftwo{}#1%
}{#2}{#3}%
}%
}%
}%
%%-----------------------------------------------------------------------------
%% End of code for \KeepKthOfLArguments.
\makeatother
\begin{document}
\begin{verbatim}
\KeepKthOfLArguments{17}{30}%
{Phrase 1}{Phrase 2}{Phrase 3}{Phrase 4}{Phrase 5}{Phrase 6}%
{Phrase 7}{Phrase 8}{Phrase 9}{Phrase 10}{Phrase 11}{Phrase 12}%
{Phrase 13}{Phrase 14}{Phrase 15}{Phrase 16}{Phrase 17}{Phrase 18}%
{Phrase 19}{Phrase 20}{Phrase 21}{Phrase 22}{Phrase 23}{Phrase 24}%
{Phrase 25}{Phrase 26}{Phrase 27}{Phrase 28}{Phrase 29}{Phrase 30}%
. Something behind all the phrases.
\end{verbatim}
\KeepKthOfLArguments{17}{30}%
{Phrase 1}{Phrase 2}{Phrase 3}{Phrase 4}{Phrase 5}{Phrase 6}%
{Phrase 7}{Phrase 8}{Phrase 9}{Phrase 10}{Phrase 11}{Phrase 12}%
{Phrase 13}{Phrase 14}{Phrase 15}{Phrase 16}{Phrase 17}{Phrase 18}%
{Phrase 19}{Phrase 20}{Phrase 21}{Phrase 22}{Phrase 23}{Phrase 24}%
{Phrase 25}{Phrase 26}{Phrase 27}{Phrase 28}{Phrase 29}{Phrase 30}%
. Something behind all the phrases.
\bigskip
\noindent\hrulefill
\bigskip
\noindent\verb|\KeepKthOfLArguments| does deliver the result after two
expansion-steps:
\begin{verbatim}
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\test
\expandafter\expandafter\expandafter{%
\KeepKthOfLArguments{3}{11}{A}{B}{C}{D}{E}{F}{G}{H}{I}{J}{K}%
}%
\end{verbatim}
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\test
\expandafter\expandafter\expandafter{%
\KeepKthOfLArguments{3}{11}{A}{B}{C}{D}{E}{F}{G}{H}{I}{J}{K}%
}%
\noindent\texttt{\string\test: \meaning\test}%
\end{document}

(This will be continued in my second answer.)
\let\num\m@ne
A few commands later the programmer then did\global\advance\num2
This dangerously changes the meaning of\m@ne
, as\showthe\m@ne
shows. The assignment is dangerous enough without\global
.\showthe\m@ne
reveals that meanings don't change. Both the token\m@ne
and the token\num
serve the purpose of accessing the same count-register whose value - by convention - should always be -1.\global\advance\num2
increases the value of that count-register by 2 and thus breaks that convention and thus might break any code where it is relied on that convention.