在循环中定义和扩展宏

在循环中定义和扩展宏

我想在\foreach循环中定义和扩展宏。宏的名称取决于迭代步骤。我定义的宏被解释为字符串,而不是我实际想要的数字集。这是一个最简单的例子,可以更准确地说明问题。

\documentclass[english]{article}
\usepackage{verbatim}
\usepackage{tikz}
\newcommand\Stage{One,Two}
\newcommand\SubStageOne{2,3,4,6}
\newcommand\SubStageTwo{6,7,8}
\newcommand{\CurrentSubStage}{} % will be defined in each stage loop

\begin{document}
%
\foreach \stage in \Stage {
%
\renewcommand{\CurrentSubStage}{ \expandafter\csname SubStage\stage \endcsname }
%
The Macro replacement of {\tt CurrentSubStage} looks the same as Macro replacement of {\tt SubStage\stage}:
%
\begin{center}
\CurrentSubStage\ is the same as \expandafter\csname SubStage\stage \endcsname .
\end{center}
%
But really they are different: Consider first the output from looping over {\tt CurrentSubStage}:
\begin{itemize}
\foreach [count=\ii] \substage in \CurrentSubStage {
\item Substage number \ii\ is \substage \\
}
\end{itemize}
%
and then this output from looping over {\tt SubStageOne}:
%
\begin{itemize}
\foreach [count=\ii] \substage in \SubStageOne {
\item Substage number \ii\ is \substage
}
\end{itemize}
}
%
%
In the second \verb|\stage| iteration, i.e. ``Two'', I want to loop over \verb|\SubStageTwo| as in the \verb|\SubStageOne| that creates four rather than one item. But I do not know how to to call \verb|\Substage\stage| (This is why I created \verb|\CurrentSubStage|). My questions:
\begin{enumerate}
\item How can I define macro \verb|\CurrentSubStage| such that it does not treat the set of numbers as a single string so that the corresponding \verb|\substage| loop gives an iteration for each number?
\item Is there a possibility to do something like:\\ \verb|\foreach [count=\ii] \substage in \SubStage\stage { ...|?
\item I need to define an ``output'' macro at the end of each \verb|\stage| iteration: Something like \verb|\newcommand{\SubStageOutputOne}| in iteration One and \verb|\newcommand{\SubStageTwoOutput}| in iteration Two. (In my application, this output is a permutation of the set |\CurrentSubStage|. I want to ``save'' this permutation in a macro and call it later, at the end of the document.) In short, how can I include something like \verb|\newcommand{\SubStageOutput\stage}| at the end of each \verb|\stage| loop?
\end{enumerate}
%
[Final note: For my actual purpose, the set \verb|\Stage| contains 6 elements and each \verb|\SubStage| set contains between 3 and 10 elements each.]
%
\end{document}

答案1

你想要类似的东西

\edef\CurrentSubStage{%
  \unexpanded\expandafter\expandafter\expandafter
  {\csname SubStage\stage\endcsname}%
}

也就是说,您需要将其扩展为 中的值\csname SubStage\stage\endcsname。这\edef是一个 TeX 命令,它会在将其分配给它定义的宏之前完全扩展宏定义中的所有内容。在您的示例中,实际上

\edef\CurrentSubStage{\csname SubStage\stage\endcsname}

就足够了,但第一个版本更安全一些。它是如何工作的?扩展\unexpanded开始扩展第一个左括号后面的内容。第一个\expandafter扩展了第三个,\expandafter后者扩展了\csname。所以经过一个扩展周期后,我们得到:

\unexpanded\expandafter{\SubStageOne}

现在将余项\expandafter展开\SubStageOne,我们得到:

\unexpanded{2,3,4,6}

then\unexpanded阻止了进一步的扩展,因此\edef变成\CurrentSubStage2,3,4,6。(类似于循环的第二步。)


评论:

  • \tt在 LaTeX 中并不推荐。最好使用\ttfamiy或在这种情况下\texttt{...},请参阅使文本加粗/斜体的“正确”方法是什么?以供参考。
  • 代码中的\expandafterin完全没用:它之前尝试扩展但无法扩展。\expandafter\csname SubStage\stage \endcsnameS\csnameS

完整代码:

\documentclass[english]{article}
\usepackage{verbatim}
\usepackage{tikz}
\newcommand\Stage{One,Two}
\newcommand\SubStageOne{2,3,4,6}
\newcommand\SubStageTwo{6,7,8}
\newcommand{\CurrentSubStage}{} % will be defined in each stage loop

\begin{document}

\foreach \stage in \Stage {
  \edef\CurrentSubStage{%
    \unexpanded\expandafter\expandafter\expandafter
    {\csname SubStage\stage\endcsname}%
  }%
  The Macro replacement of \texttt{CurrentSubStage} looks the same as Macro
  replacement of \texttt{SubStage\stage}:
  \begin{center}
    \CurrentSubStage\ is the same as \csname SubStage\stage \endcsname .
  \end{center}
  But really they are different: Consider first the output from looping over
  \texttt{CurrentSubStage}:
  \begin{itemize}
    \foreach [count=\ii] \substage in \CurrentSubStage {
      \item Substage number \ii\ is \substage
    }
  \end{itemize}
  and then this output from looping over \texttt{SubStageOne}:
  \begin{itemize}
    \foreach [count=\ii] \substage in \SubStageOne {
      \item Substage number \ii\ is \substage
    }
  \end{itemize}
}

In the second \verb|\stage| iteration, i.e. ``Two'', I want to loop over
\verb|\SubStageTwo| as in the \verb|\SubStageOne| that creates four rather
than one item. But I do not know how to to call \verb|\Substage\stage| (This
is why I created \verb|\CurrentSubStage|). My questions:
\begin{enumerate}
  \item How can I define macro \verb|\CurrentSubStage| such that it does not
    treat the set of numbers as a single string so that the corresponding
    \verb|\substage| loop gives an iteration for each number? 
  \item Is there a possibility to do something like:\\
    \verb|\foreach [count=\ii] \substage in \SubStage\stage { ...|?
  \item I need to define an ``output'' macro at the end of each \verb|\stage|
    iteration: Something like \verb|\newcommand{\SubStageOutputOne}| in
    iteration One and \verb|\newcommand{\SubStageTwoOutput}| in iteration
    Two. (In my application, this output is a permutation of the set
    |\CurrentSubStage|. I want to ``save'' this permutation in a macro and call
    it later, at the end of the document.) In short, how can I include 
    something like \verb|\newcommand{\SubStageOutput\stage}| at the end of each
    \verb|\stage| loop? 
\end{enumerate}

[Final note: For my actual purpose, the set \verb|\Stage| contains 6 elements
and each \verb|\SubStage| set contains between 3 and 10 elements each.]

\end{document}

相关内容