# How can I globally set pgfmathsetlength?

How can I declare a length via pgfmathsetlength global?

The example results in 20pt -- 5pt -- 20pt But I had expected: 20pt -- 5pt -- 5pt

\documentclass[10pt]{article}
\parindent0pt
\usepackage{tikz}
\newlength\testl
\pgfmathsetlength\testl{20pt}
\begin{document}
\the\testl

{\global\pgfmathsetlength\testl{5pt}\the\testl}

\the\testl
\end{document}


I don't want to discuss possibilities with \setlength or \deflength.

-
What does your .log file say about using \global? –  Werner Dec 20 '11 at 21:43
It's interesting that \global doesn't issue an error; this is because the token that actually it acts on is \futurelet; it definitely doesn't act on the setting of \testtl's value, unfortunately. –  egreg Dec 20 '11 at 21:46

You can use \global like this :

 {\pgfmathsetlength{\global\testl}{5pt}}\the\testl


Some remarks : Egreg notices this code is very similar to

\setlength{\global\testl}{5pt}

It may be interesting to know what the macro pgfmathsetlength provides. In the file pgfmathcalc.code.tes we can read :

% #1 = dimension register
% #2 = expression
%
% Description:
%
% These functions work similar to \setlength and \addtolength. Only,
% they allow #2 to contain an expression, which is evaluated before
% assignment. Furthermore, the font is setup before the assignment is
% done, so that dimensions like 1em are evaluated correctly.
%
% If #2 starts with "+", then a simple assignment is done (but the
% font is still setup). This is orders of magnitude faster than a
% parsed assignment.


Another possibility to declare a length global is to redefine pgfmathsetlength but it's bad or to use a new macro :globalpgfmathsetlength based on pgfmathsetlength. We need to add \global in two lines but simplest is my first answer.

 \makeatletter
\def\globalpgfmathsetlength#1#2{%
\expandafter\pgfmath@onquick#2\pgfmath@%
{%
% Ok, quick version:
\begingroup%
\pgfmath@selectfont%
\pgfmath@x#2\unskip%
\pgfmath@returnone\pgfmath@x%
\endgroup%
\global#1\pgfmathresult pt\relax% here add \global before #1
}%
{%
\pgfmathparse{#2}%
\global#1\pgfmathresult pt\relax% and here
}%
\ignorespaces%
}

-
Very similar to \setlength{\global\testl}{5pt} (which works). :) –  egreg Dec 20 '11 at 23:14

Use a scratch dimension

{\dimendef\temp=0
\pgfmathsetlength\temp{5pt}\global\testl=\temp}


Note. I wouldn't use \testl in place of \temp, in order to avoid "save stack buildup".

-
Interesting. Why does save stack buildup occur if \testl is used instead of \temp. Shouldn't the local assignment not being discarded at the end of the group? –  Martin Scharrer Dec 20 '11 at 22:16
@MartinScharrer It will happen if \testl has already been used in the outer level. –  egreg Dec 20 '11 at 22:25
Why isn't a previously local assignment in the outer level not be discarded from the save stack as soon a global assignment is made? Or is this technical not feasible? –  Martin Scharrer Dec 21 '11 at 9:44
@MartinScharrer It's clearly explained both in the TeXbook and in TeX by Topic. A local assignment makes TeX push the "outer value" in the save stack and there it will remain, since the global assignment made in the group will tell TeX not to go fetching that value again. Why the useless entry is not discarded must be asked to Knuth. –  egreg Dec 21 '11 at 10:02