![global を使用せずに、反復間およびループ後に効果を持つ foreach ループでマクロを定義するにはどうすればよいでしょうか?](https://rvso.com/image/254705/global%20%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%9B%E3%81%9A%E3%81%AB%E3%80%81%E5%8F%8D%E5%BE%A9%E9%96%93%E3%81%8A%E3%82%88%E3%81%B3%E3%83%AB%E3%83%BC%E3%83%97%E5%BE%8C%E3%81%AB%E5%8A%B9%E6%9E%9C%E3%82%92%E6%8C%81%E3%81%A4%20foreach%20%E3%83%AB%E3%83%BC%E3%83%97%E3%81%A7%E3%83%9E%E3%82%AF%E3%83%AD%E3%82%92%E5%AE%9A%E7%BE%A9%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF%E3%81%A9%E3%81%86%E3%81%99%E3%82%8C%E3%81%B0%E3%82%88%E3%81%84%E3%81%A7%E3%81%97%E3%82%87%E3%81%86%E3%81%8B%3F.png)
を使用せずに\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 つだけの新しいバージョンを示します。
\afteriterationdef
現在の反復後にマクロを(再)定義します。\afterforeachdef
foreach の後 (および反復の後) にマクロを (再) 定義します。
これら 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