How to add a \global before \pgfmathsetmacro?

It seems that one can't add \global before a \pgfmathsetmacro as that yields:

You can't use a prefix with \begingroup'.

But that is the functionality I need here.

I am trying to compute the average of the integers in a list. In the MWE the list I have is

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


and the \typeout messages show:

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


So it seems as if the \pgfmathsetmacro is working except it is not saving its state between successive iterations of the \foreach, which is exactly what the \global was there for in the first place.

Code:

\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}

• \pgfmathsetmacro\temp{...}\global\let\AverageValue\temp – egreg Mar 8 '14 at 22:47
• @egreg: Glad that that was easy. A bit embarrassed that I did not think of that. :-) – Peter Grill Mar 8 '14 at 22:48

You can legally place \global only before an assignment command:

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


and so on. One should note that \global wants and looks for a suitable command following it, doing expansion. For instance, etoolbox defines

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


so \global\cslet{foo}{\bar} is legal, because it will become

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


after the first expansion, but since \expandafter is expandable, \global triggers its expansion and you get \global\let\foo\bar as wanted.

On the other hand, \pgfmathsetmacro is defined in pgfmathcalc.code.tex by

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


so one can definitely not add \global in front of it.

The easiest workaround is to say

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


since \pgfmathparse stores the result in \pgfmathresult`.