global を使用せずに、反復間およびループ後に効果を持つ foreach ループでマクロを定義するにはどうすればよいでしょうか?

global を使用せずに、反復間およびループ後に効果を持つ 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}

次の内容を含む文書を生成します:

    1 について
\myarray: マクロ:->init
\valmax: マクロ:->0
    8 の
\myarray: マクロ:->init
\valmax: マクロ:->1.0
    繰り返し -3
\myarray: マクロ:->init
\valmax: マクロ:->8.0
    内部
\myarray: マクロ:->init,1,8,-3
\valmax: マクロ:->8.0
\myarray: \relax
\valmax: \relax

この結果は私にぴったりです!

しかし、同じ効果を達成しながらマクロ\appendbyforeachを定義するより良い方法はあるのでしょうか?\defincbyforeach

ここでのパッケージは本当に実用的でしょうかetextools?

答え1

注記:このコードでは常に が使用されますetextools。自分の質問に対する回答を受け入れる前に、他の人がもっと興味深い解決策( を使用せずetextools、より効果的、高速、シンプルなど)を提案してくれることを期待します。ただし、 は常に を使用しないでください\global

編集:ここでは、拡張された値がなく、マクロが 2 つだけの新しいバージョンを示します。

  1. \afteriterationdef現在の反復後にマクロを(再)定義します。

  2. \afterforeachdefforeach の後 (および反復の後) にマクロを (再) 定義します。

これら 2 つのマクロのコードは次のとおりです。

\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: macro:->init,1,8,-3,-1, \myvalue: macro:->24.0
グループ外: \myarray: \relax、\myvalue: \relax

編集2: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: macro:->init,(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3), \myvalue: macro:->37.0
グループ外: \myarray: \relax、\myvalue: \relax

関連情報