Wie definiert man Makros in einer Foreach-Schleife mit Effekten zwischen den Iterationen und nach der Schleife, ohne global zu verwenden?

Wie definiert man Makros in einer Foreach-Schleife mit Effekten zwischen den Iterationen und nach der Schleife, ohne global zu verwenden?

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 \appendbyforeachund \defincbyforeachdabei die gleichen Effekte zu erzielen?

Ist etextoolsdas 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.

  1. \afteriterationdefum ein Makro nach der aktuellen Iteration (neu) zu definieren.

  2. \afterforeachdefum 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

verwandte Informationen