如何在 foreach 循环中定义宏并在迭代之间和循环后产生效果而不使用全局?

如何在 foreach 循环中定义宏并在迭代之间和循环后产生效果而不使用全局?

如果不使用\global,则代码如下:

\documentclass{minimal}
\usepackage[T1]{fontenc}
\usepackage{tikz}
\usepackage{etextools}

\newcommand\appendbyforeach[2]{%
  \AfterGroup*{\noexpand\AfterGroup{\noexpand\edef\noexpand#1{\noexpand#1#2}}}
}

\newcommand\defincbyforeach[2]{%
  \AfterGroup*{\noexpand\def\noexpand#1{#2}}
  \AfterGroup*{\noexpand\AfterGroup{\noexpand\def\noexpand#1{#2}}}
}

\newcommand\meaningwithname[1]{\textbackslash#1: \expandafter\meaning\csname #1\endcsname}

\newcommand\mymacro{
  \begingroup
  \def\myarray{init}
  \def\valmax{0}
  \foreach \i in {1,8,-3}{
    \appendbyforeach{\myarray}{,\i}
    \pgfmathsetmacro{\max}{\valmax < \i ? \i : \valmax}
    \defincbyforeach\valmax{\max}
    %%% print state of \myarray and \valmax
    foreach \i\\\meaningwithname{myarray}\\\meaningwithname{valmax}\par
  }
  inside\\\meaningwithname{myarray}\\\meaningwithname{valmax}\par
  \endgroup
  outside\\\meaningwithname{myarray}\\\meaningwithname{valmax}\par
}

\begin{document}\mymacro\end{document}

生成一个包含以下内容的文档:

    foreach 1
\myarray: 宏:->初始化
\valmax: 宏:->0
    foreach 8
\myarray: 宏:->初始化
\valmax: 宏:->1.0
    foreach -3
\myarray: 宏:->初始化
\valmax: 宏:->8.0
    里面
\myarray: 宏:->init,1,8,-3
\valmax: 宏:->8.0
    外部
\myarray:\放松
\valmax:\放松

这个结果我很满意!

但是有没有更好的方法来定义宏\appendbyforeach\defincbyforeach同时达到相同的效果呢?

etextools包裹在这里真的实用吗?

答案1

笔记:此代码始终使用etextools。在接受我对我自己的问题的回答之前,我希望其他人能为我提供更有趣的解决方案(不使用etextools,更有效,更快,更简单……)。但始终不使用\global

编辑:这是没有扩展值且只有两个宏的新版本。

  1. \afteriterationdef在当前迭代之后(重新)定义宏。

  2. \afterforeachdef在 foreach 之后(以及迭代之后)重新定义一个宏。

以下是这两个宏的代码:

\documentclass{minimal}
\usepackage[T1]{fontenc}
\usepackage{tikz}
\usepackage{etextools}

\makeatletter

% define a macro after current iteration
\newcommand\afteriterationdef[1]{\aftergroup@def#1}

% define a macro after foreach (and after iteration)
\newcommand\afterforeachdef[1]{\afteriterationdef{#1}\AfterGroup{\aftergroup@def#1}}

\makeatother

举个例子:

\newcommand\meaningwithname[1]{%
  \textbackslash#1: \expandafter\meaning\csname #1\endcsname}

\newcommand\mymacro{
  {
    \def\myarray{init}
    \def\myvalue{1}
    \foreach \i in {1,8,-3,-1}{
      % append some value to \myarray
      \edef\myarray{\myarray,\i}
      \afterforeachdef\myarray
      % incremental definition of \mtvalue
      \pgfmathsetmacro{\myvalue}{\myvalue*\i}
      \afterforeachdef\myvalue
      %%% print meaning of \myarray and \myvalue at each iteration
      foreach \i: \meaningwithname{myarray}, \meaningwithname{myvalue}\par
    }
    %%% print meaning of \myarray and \myvalue after \foreach
    inside group: \meaningwithname{myarray}, \meaningwithname{myvalue}\par
  }
  %%% print meaning of \myarray and \myvalue outside
  outside group: \meaningwithname{myarray}, \meaningwithname{myvalue}\par
}

\begin{document}\mymacro\end{document}

此示例生成以下文本:

foreach 1:\myarray:宏:->init,1,\myvalue:宏:->1.0
foreach 8:\myarray:宏:->init,1,8,\myvalue:宏:->8.0
foreach -3:\myarray:宏:->init,1,8,-3,\myvalue:宏:->-24.0
foreach -1:\myarray:宏:->init,1,8,-3,-1,\myvalue:宏:->24.0
组内:\myarray:宏:->init,1,8,-3,-1,\myvalue:宏:->24.0
外部组:\myarray:\relax,\myvalue:\relax

编辑2:另一个包含两个嵌套的示例\foreach

\newcommand\mymacrowithnestedforeach{
  {
    \def\myarray{init}
    \def\myvalue{1}
    \foreach \i in {1,...,3}{
      \foreach \j in {1,...,3}{
        % append some value to \myarray
        \edef\myarray{\myarray,(\i,\j)}
        \afterforeachdef\myarray
        % incremental definition of \myvalue
        \pgfmathsetmacro{\myvalue}{\myvalue+\j*\i}
        \afterforeachdef\myvalue
        %%% print meaning of \myarray and \myvalue at each iteration
        int foreach \i: \meaningwithname{myarray}, \meaningwithname{myvalue}\par
      }
      % 
      \afterforeachdef\myarray
      \afterforeachdef\myvalue
      %%% print meaning of \myarray and \myvalue at each iteration
      ext foreach \i: \meaningwithname{myarray}, \meaningwithname{myvalue}\par
    }
    %%% print meaning of \myarray and \myvalue after \foreach
    inside  group: \meaningwithname{myarray}, \meaningwithname{myvalue}\par
  }
  %%% print meaning of \myarray and \myvalue outside
  outside group: \meaningwithname{myarray}, \meaningwithname{myvalue}\par
}

\begin{document}\mymacrowithnestedforeach\end{document}

此示例生成以下文本:

int foreach 1:\myarray:宏:->init,(1,1),\myvalue:宏:->2.0
int foreach 1:\myarray:宏:->init,(1,1),(1,2),\myvalue:宏:->4.0
int foreach 1:\myarray:宏:->init,(1,1),(1,2),(1,3),\myvalue:宏:->7.0
ext foreach 1:\myarray:宏:->init,(1,1),(1,2),(1,3),\myvalue:宏:->7.0
int foreach 2:\myarray:宏:->init,(1,1),(1,2),(1,3),(2,1),\myvalue:宏:->9.0
int foreach 2:\myarray:宏:->init,(1,1),(1,2),(1,3),(2,1),(2,2),\myvalue:宏:->13.0
int foreach 2:\myarray:宏:->init,(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),\myvalue:宏:->19.0
ext foreach 2:\myarray:宏:->init,(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),\myvalue:宏:->19.0
int foreach 3:\myarray:宏:->init,(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),\myvalue:宏:->22.0
int foreach 3:\myarray:宏:->init,(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),\myvalue:宏:->28.0
int foreach 3:\myarray:宏:->init,(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3),\myvalue:宏:->37.0
ext foreach 3:\myarray:宏:->init,(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3),\myvalue:宏:->37.0
组内:\myarray:宏:->init,(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3),\myvalue:宏:->37.0
外部组:\myarray:\relax,\myvalue:\relax

相关内容