![Wie definiert man Makros in einer Foreach-Schleife mit Effekten zwischen den Iterationen und nach der Schleife, ohne global zu verwenden?](https://rvso.com/image/254705/Wie%20definiert%20man%20Makros%20in%20einer%20Foreach-Schleife%20mit%20Effekten%20zwischen%20den%20Iterationen%20und%20nach%20der%20Schleife%2C%20ohne%20global%20zu%20verwenden%3F.png)
Ohne zu verwenden \global
, der folgende Code:
\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}
erstellt ein Dokument mit folgendem Inhalt:
für jedes 1 \myarray: Makro:->init \valmax: Makro:->0 für jeden 8 \myarray: Makro:->init \valmax: Makro:->1.0 für jeden -3 \myarray: Makro:->init \valmax: Makro:->8.0 innen \myarray: Makro:->init,1,8,-3 \valmax: Makro:->8.0 draußen \meinarray: \relax \valmax: \relax
Mit diesem Ergebnis bin ich sehr zufrieden!
Aber gibt es eine bessere Möglichkeit, Makros zu definieren \appendbyforeach
und \defincbyforeach
dabei die gleichen Effekte zu erzielen?
Ist etextools
das Paket hier wirklich praktisch?
Antwort1
Notiz:Dieser Code verwendet immer etextools
. Bevor ich die Antwort auf meine eigene Frage akzeptiere, hoffe ich, dass andere mir interessantere Lösungen anbieten (ohne etextools
, effektiver, schneller, einfacher ...). Aber immer ohne Verwendung von \global
!
Bearbeiten:Hier eine neue Version ohne erweiterte Werte und mit nur zwei Makros.
\afteriterationdef
um ein Makro nach der aktuellen Iteration (neu) zu definieren.\afterforeachdef
um ein Makro nach foreach (und nach der Iteration) (neu) zu definieren.
Hier ist der Code dieser beiden Makros:
\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
Und ein Beispiel:
\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}
Dieses Beispiel erzeugt diesen Text:
für jeden 1: \myarray: Makro:->init,1, \myvalue: Makro:->1.0 für jeden 8: \myarray: Makro:->init,1,8, \myvalue: Makro:->8.0 foreach -3: \myarray: Makro:->init,1,8,-3, \myvalue: Makro:->-24.0 foreach -1: \myarray: Makro:->init,1,8,-3,-1, \myvalue: Makro:->24.0 innerhalb der Gruppe: \myarray: Makro:->init,1,8,-3,-1, \myvalue: Makro:->24.0 außerhalb der Gruppe: \myarray: \relax, \myvalue: \relax
Bearbeitung 2:Ein weiteres Beispiel mit zwei verschachtelten \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}
Dieses Beispiel erzeugt diesen Text:
int foreach 1: \myarray: Makro:->init,(1,1), \myvalue: Makro:->2.0 int foreach 1: \myarray: Makro:->init,(1,1),(1,2), \myvalue: Makro:->4.0 int foreach 1: \myarray: Makro:->init,(1,1),(1,2),(1,3), \myvalue: Makro:->7.0 ext foreach 1: \myarray: Makro:->init,(1,1),(1,2),(1,3), \myvalue: Makro:->7.0 int foreach 2: \myarray: Makro:->init,(1,1),(1,2),(1,3),(2,1), \myvalue: Makro:->9.0 int foreach 2: \myarray: Makro:->init,(1,1),(1,2),(1,3),(2,1),(2,2), \myvalue: Makro:->13.0 int foreach 2: \myarray: Makro:->init,(1,1),(1,2),(1,3),(2,1),(2,2),(2,3), \myvalue: Makro:->19.0 ext foreach 2: \myarray: Makro:->init,(1,1),(1,2),(1,3),(2,1),(2,2),(2,3), \myvalue: Makro:->19.0 int foreach 3: \myarray: Makro:->init,(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1), \myvalue: Makro:->22.0 int foreach 3: \myarray: Makro:->init,(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2), \myvalue: Makro:->28.0 int foreach 3: \myarray: Makro:->init,(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3), \myvalue: Makro:->37.0 ext foreach 3: \myarray: Makro:->init,(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3), \myvalue: Makro:->37.0 innerhalb der Gruppe: \myarray: Makro:->init,(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3), \myvalue: Makro:->37.0 außerhalb der Gruppe: \myarray: \relax, \myvalue: \relax