How to iteratively build \ifcase

An alternative way of building up the ifcase

\documentclass{article}


\def\QInput{}
\def\afterfi#1\fi{\fi#1}
\def\QPreparation#1#2{\bgroup
\let\or\relax\let\input\relax
\XQPreparation{#1}{#2}%
\edef\x{\egroup\def\noexpand\QInput####1{%
  \noexpand\ifcase####1\relax\input{#1/C0.tex}\QInput\noexpand\fi}}%
\x
}
\def\XQPreparation#1#2{%
\ifnum#2>0 \afterfi
\edef\QInput{\or\input{#1/C#2.tex}\QInput}%
\XQPreparation{#1}{\the\numexpr#2-1\relax}%
\fi}


\begin{document}
\QPreparation{foo}{5}

\show\QInput
\end{document}

produces

> \QInput=macro:
#1->\ifcase #1\relax \input {foo/C0.tex}\or \input {foo/C1.tex}\or \input {foo/
C2.tex}\or \input {foo/C3.tex}\or \input {foo/C4.tex}\or \input {foo/C5.tex}\fi
 .
l.23 \show\QInput

The replacement text is not executed when the replacement text is absorbed.

You can build the macro in an indirect way:

\documentclass{article}

\newcommand{\QInput}{} % initialization

\makeatletter
\newcount\QIteration
\newcommand{\QPreparation}[2]{%
  \QIteration=\z@
  \gdef\tempa{\ifcase####1\relax\input{#1/C0.tex}}%
  \loop\ifnum\QIteration<#2
    \advance\QIteration\@ne
    \edef\tempb{%
      \expandafter\noexpand\csname or\endcsname
      \noexpand\input{#1/C\the\QIteration.tex}%
    }%
    \expandafter\g@addto@macro\expandafter\tempa\expandafter{\tempb}%
  \repeat
  \g@addto@macro\tempa{\fi}
  \def\tempb{\renewcommand\QInput[1]}%
  \expandafter\tempb\expandafter{\tempa}
}
\makeatother
\QPreparation{foo}{5}

\show\QInput

The \show command will output

> \QInput=\long macro:
#1->\ifcase #1\relax \input {foo/C0.tex}\or \input {foo/C1.tex}\or \input {foo/
C2.tex}\or \input {foo/C3.tex}\or \input {foo/C4.tex}\or \input {foo/C5.tex}\fi
 .

which seems to be what you want.

It's necessary to hide \or in the loop, because otherwise we'd get a “misplaced \or” error.

An alternative without global definitions:

\documentclass{article}

\newcommand{\QInput}{} % initialization

\makeatletter
\newcount\QIteration
\toks@={}
\newcommand{\QPreparation}[2]{%
  \QIteration=\z@
  \toks@={\ifcase##1\relax\input{#1/C0.tex}}%
  \loop\ifnum\QIteration<#2
    \advance\QIteration\@ne
    \edef\temp{%
      \expandafter\noexpand\csname or\endcsname
      \noexpand\input{#1/C\the\QIteration.tex}%
    }%
    \toks@=\expandafter{\the\expandafter\toks@\temp}%
  \repeat
  \toks@=\expandafter{\the\toks@\fi}%
  \begingroup\edef\x{\endgroup
    \noexpand\renewcommand\noexpand\QInput[1]{\the\toks@}%
  }\x
}
\makeatother
\QPreparation{foo}{5}

\show\QInput

An equivalent solution if xparse is used:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\tl_new:N \l_strickland_temp_tl
\NewDocumentCommand{\QPreparation}{mm}
 {
  \tl_clear:N \l_strickland_temp_tl
  \int_step_inline:nnnn { 0 } { 1 } { #2 }
   {
    \tl_put_right:Nn \l_strickland_temp_tl { {##1}{\input{#1/C##1.tex}} }
   }
  \use:x
   {
    \exp_not:N \DeclareDocumentCommand \exp_not:N \QInput { m }
     {
      \exp_not:N \int_case:nn { ####1 } { \exp_not:V \l_strickland_temp_tl }
     }
   }
 }
\ExplSyntaxOff

Tags:

Loops

Macros