¿Cómo agregar un \global antes de \pgfmathsetmacro?

¿Cómo agregar un \global antes de \pgfmathsetmacro?

Parece que no se puede agregar \globalantes de a, \pgfmathsetmacrolo que produce:

No puedes usar un prefijo con `\begingroup'.

Pero esa es la funcionalidad que necesito aquí.

Estoy intentando calcular el promedio de los números enteros en una lista. En el MWE la lista que tengo es

\newcommand*{\MyData}{3,7,X,Y,8,9,Z}%

y los \typeoutmensajes muestran:

**** NumberOfValidEnteries=1, \AverageValue=3.0
**** NumberOfValidEnteries=2, \AverageValue=3.5
**** NumberOfValidEnteries=3, \AverageValue=2.66666
**** NumberOfValidEnteries=4, \AverageValue=2.25

Entonces parece que \pgfmathsetmacroestá funcionando, excepto que no guarda su estado entre iteraciones sucesivas de \foreach, que es exactamente para lo que \globalestaba allí en primer lugar.

Código:

\documentclass{article}
\usepackage{tikz}
\usepackage{xstring}

% http://tex.stackexchange.com/questions/50111/how-to-check-if-the-value-of-a-parameter-is-a-number
\newcommand*{\IfIsInteger}[3]{%
    \IfStrEq{#1}{ }{%
        #3% is a blank string
    }{%
        \IfInteger{#1}{#2}{#3}%
    }%
}%

\newcommand*{\MyData}{3,7,X,Y,8,9,Z}%

\newcommand*{\AverageValue}{0}
\newcounter{NumberOfValidEnteries}
\newcommand*{\ComputeAverage}[1]{%
    %% Initialize (in case this is used more than once)
    \renewcommand*{\AverageValue}{0}
    \setcounter{NumberOfValidEnteries}{0}%
    %
    \edef\ExpandedDataEnteries{#1}% So that #1 can be a list or a macro defined list.
    \foreach \NewData in \ExpandedDataEnteries {%
        \IfIsInteger{\NewData}{%
            %\global% <---- I need this ????
            \pgfmathsetmacro{\AverageValue}{%  
                (\AverageValue * \arabic{NumberOfValidEnteries} + \NewData) /
                (\arabic{NumberOfValidEnteries} + 1)
            }%
            \stepcounter{NumberOfValidEnteries}%
            \typeout{**** NumberOfValidEnteries=\arabic{NumberOfValidEnteries}, \string\AverageValue=\AverageValue}%
        }{%
            % Not integer data so skip it
        }%
    }%
}

\begin{document}
    \ComputeAverage{\MyData}%
    Average of integers in ``\MyData" is ``\AverageValue".
\end{document}

Respuesta1

Puede colocar legalmente \globalsólo antes de un comando de asignación:

\global\def
\global\let
\global\mathchardef
\global\catcode
\global\advance

etcétera. Hay que tener en cuenta que\global quiere y buscaun comando adecuado siguiéndolo, haciendo expansión. Por ejemplo, etoolboxdefine

\newrobustcmd{\cslet}[2]{%
  \expandafter\let\csname#1\endcsname#2}

así \global\cslet{foo}{\bar}es legal, porque se convertirá

\global\expandafter\let\csname foo\endcsname\bar

después de la primera expansión, pero como \expandafteres expandible, \globalactiva su expansión y obtienes \global\let\foo\barlo que deseas.

Por otro lado, \pgfmathsetmacroestá definido pgfmathcalc.code.texpor

\def\pgfmathsetmacro#1#2{%
  \begingroup%
    \pgfmathparse{#2}%
        \let#1=\pgfmathresult
    \pgfmath@smuggleone{#1}%
  \endgroup%
}

por lo que definitivamente no se puede agregar \globaldelante de él.

La solución más sencilla es decir

\pgfmathparse
  (\AverageValue * \arabic{NumberOfValidEnteries} + \NewData) /
   (\arabic{NumberOfValidEnteries} + 1)
  }%
\global\let\AverageValue\pgfmathresult

ya que \pgfmathparsealmacena el resultado en \pgfmathresult.

información relacionada