![¿Cómo definir macros en un bucle foreach con efectos entre iteraciones y después del bucle sin usar global?](https://rvso.com/image/254705/%C2%BFC%C3%B3mo%20definir%20macros%20en%20un%20bucle%20foreach%20con%20efectos%20entre%20iteraciones%20y%20despu%C3%A9s%20del%20bucle%20sin%20usar%20global%3F.png)
Sin usar \global
, el siguiente código:
\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}
produce un documento que contiene:
para cada 1 \myarray: macro:->inicio \valmax: macro:->0 para cada 8 \myarray: macro:->inicio \valmax: macro:->1.0 para cada -3 \myarray: macro:->inicio \valmax: macro:->8.0 adentro \myarray: macro:->inicio,1,8,-3 \valmax: macro:->8.0 afuera \myarray: \relajarse \valmax: \relajarse
¡Este resultado me sienta bien!
Pero, ¿existe una mejor manera de definir macros \appendbyforeach
y \defincbyforeach
al mismo tiempo lograr los mismos efectos?
¿ etextools
El paquete es realmente práctico aquí?
Respuesta1
Nota:Este código siempre usa etextools
. Antes de aceptar mi respuesta a mi propia pregunta, espero que otros me ofrezcan soluciones más interesantes (sin etextools
, más efectivas, más rápidas, más simples...). ¡Pero siempre sin usar \global
!
Editar:Aquí una nueva versión sin valores ampliados y con sólo dos macros.
\afteriterationdef
para (re)definir una macro después de la iteración actual.\afterforeachdef
para (re)definir una macro después de foreach (y después de la iteración).
Aquí está el código de estas dos macros:
\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
Y un ejemplo:
\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}
Este ejemplo produce este texto:
foreach 1: \myarray: macro:->init,1, \myvalue: macro:->1.0 foreach 8: \myarray: macro:->init,1,8, \myvalue: macro:->8.0 foreach -3: \myarray: macro:->init,1,8,-3, \myvalue: macro:->-24.0 foreach -1: \myarray: macro:->init,1,8,-3,-1, \myvalue: macro:->24.0 dentro del grupo: \myarray: macro:->init,1,8,-3,-1, \myvalue: macro:->24.0 grupo externo: \myarray: \relax, \myvalue: \relax
Edición 2:Otro ejemplo con dos anidados \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}
Este ejemplo produce este texto:
int foreach 1: \myarray: macro:->init,(1,1), \myvalue: macro:->2.0 int foreach 1: \myarray: macro:->init,(1,1),(1,2), \myvalue: macro:->4.0 int foreach 1: \myarray: macro:->init,(1,1),(1,2),(1,3), \myvalue: macro:->7.0 text foreach 1: \myarray: macro:->init,(1,1),(1,2),(1,3), \myvalue: macro:->7.0 int foreach 2: \myarray: macro:->init,(1,1),(1,2),(1,3),(2,1), \myvalue: macro:->9.0 int foreach 2: \myarray: macro:->init,(1,1),(1,2),(1,3),(2,1),(2,2), \myvalue: macro:-> 13.0 int foreach 2: \myarray: macro:->init,(1,1),(1,2),(1,3),(2,1),(2,2),(2,3), \ mivalor: macro:->19.0 text foreach 2: \myarray: macro:->init,(1,1),(1,2),(1,3),(2,1),(2,2),(2,3), \ mivalor: macro:->19.0 int foreach 3: \myarray: macro:->init,(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),( 3,1), \mivalor: macro:->22.0 int foreach 3: \myarray: macro:->init,(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),( 3,1),(3,2), \mivalor: macro:->28.0 int foreach 3: \myarray: macro:->init,(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),( 3,1),(3,2),(3,3), \mivalor: macro:->37.0 text foreach 3: \myarray: macro:->init,(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),( 3,1),(3,2),(3,3), \mivalor: macro:->37.0 dentro del grupo: \myarray: macro:->init,(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3 ,1),(3,2),(3,3), \mivalor: macro:->37.0 grupo externo: \myarray: \relax, \myvalue: \relax