# Is there a way of limiting the scope of \newlength?

Is there a way of limiting the scope of \newlength? I'm using the same name in many TikZ picture but each with different value, and I don't want it to live on between the pictures as it's not intended to.

-
You might want to take a look at tex.stackexchange.com/questions/7134/… –  Joseph Wright Sep 29 '11 at 19:21

The following works for me and localizes the setting of lengths using grouping:

\documentclass{article}
\newlength{\mylen}
\begin{document}
\setlength{\mylen}{30pt}% Global definition
Here is some text. \rule{40pt}{\mylen}

\bigskip
{% <--- \begingroup
\setlength{\mylen}{20pt}% Local redefinition
Here is some text. \rule{40pt}{\mylen}
}% <--- \endgroup

\bigskip
Here is some text. \rule{40pt}{\mylen}
\end{document}​


-

Remember that \newlength allocates a new (skip) register, which can then be used everywhere; \setlength acts locally, so its effect is limited to the group or environment in which it is given.

There's little use (in the most common situations) for local allocation. For limited scope one can use the "scratch" registers which are never allocated:

\dimen0 \dimen2 \dimen4 \dimen6 \dimen8 \dimen255
\dimen1 \dimen3 \dimen5 \dimen7 \dimen9

\skip0 \skip2 \skip4 \skip6 \skip8 \skip255
\skip1 \skip3 \skip5 \skip7 \skip9

\toks0 \toks2 \toks4 \toks6 \toks8 \toks255
\toks1 \toks3 \toks5 \toks7 \toks9

\box0 \box2 \box4 \box6 \box8
\box1 \box3 \box5 \box7 \box9


The registers <type>0 are also called <type>@ (\dimen@ is the same as \dimen0 and so on). The division into pair of lines is because registers in the top line should always be used locally and those in the second line "globally", that is, their setting should be preceded by \global (this is done to prevent "save stack buildup").

LaTeX allocates also \@tempdima, \@tempdimb, \@tempdimc (dimen registers); \@tempskipa, \@tempskipb (skip register); \@tempboxa (box register); \@tempcnta, \@tempcntb (count registers) and \count@ is the same as \count255.

So there's plenty of room for playing with registers for limited scope without allocating new ones. However, scratch registers may be exploited by the macro we are using in the same scope, so some care is necessary.

-
@GonzaloMedina That's why that line was too long! I couldn't see it. –  egreg Sep 29 '11 at 19:51

Each tikzpicture can contain local settings which will not effect other tikzpicture environments. The way to limit the scope within a single tikzpicture is to use \begin{scope} ... \end{scope}.

To illustrate, consider:

\documentclass{article}
\usepackage{tikz}
\begin{document}

\newlength{\mylen}
\setlength{\mylen}{1cm}% global definition

% y-coordinate can be ignored, only used for formatting the output.
% We use mylen to determine how the long the drawn line is

\begin{tikzpicture}
\setlength{\mylen}{2cm}% This is ONLY in effect within this tikzpicture
\draw [red,thick] (0,0) -- (\mylen,0) node [right] {2cm};
\end{tikzpicture}

\begin{tikzpicture}
\draw [blue,thick] (0,-1) -- (\mylen,-1) node [right] {1cm};% not affected by above \setlength
\begin{scope}
\setlength{\mylen}{3cm}% This is ONLY in effect within this scope
\draw [green,thick] (0,-1.2) -- (\mylen,-1.2) node [right] {3cm};
\end{scope}
\draw [orange,thick] (0,-1.4) -- (\mylen,-1.4) node [right] {1cm};% not affected by above \setlength
\end{tikzpicture}
\end{document}


Before we we enter the tikzpicture environment, we have globally set the value of \mylen to 1cm. In the first tikzpicture, the setting to 2cm is local within that picture, as can be seen by the blue line in the subsequent picture -- it still used the initial setting of 1cm instead of 2cm.

In the second tikzpicture, we use \begin{scope} and set \mylen to 3cm and draw the green line. This setting reverts back to the prior setting at \end{scope} and hence the orange line is still 1cm long.

The following is copied directly from a related question on moving and rotating portions of a diagram as it is relevant here as well:

Inside a tikzpicture environment the scope environment applies all options local to the environment contents. Furthermore, if you include \usetikzlibrary{scopes} in the preamble, you can start a scope at "certain places" with a { provided that the single brace is followed by the options within [].

From the documentation (Section 12.3 in the v2.10 TiKZ & PGF manual):

The “certain places” where an opening brace has this special meaning are the following: First, right after the semicolon that ends a path. Second, right after the end of a scope. Third, right at the beginning of a scope, which includes the beginning of a picture. Also note that some square bracket must follow, otherwise the brace is treated as a normal TeX scope.

-

I don't really know what I'm doing here because I neither deal with \newlength a lot nor with lower-level commands like \let, but the following seems to work:

\documentclass{article}

\begin{document}

\newlength{\elephant}
\setlength{\elephant}{100mm}

\rule{\elephant}{\elephant}

\let\elephant\relax

%\rule{\elephant}{\elephant}

\end{document}


If you uncomment the second \rule, you'll get four error messages because \elephant is undefined – I think this is what you want?

-
The errors occur because \elephant is not a length after using \let. It is still defined in the last (commented) command, by virtue of \let. –  Werner Sep 29 '11 at 19:30
So \let turns the length \elephant into a marco \elephant, which hence is invalid input for \rule? Would that still solve gablin's problem? –  doncherry Sep 29 '11 at 19:35
Yes. \let\foo\bar duplicates the meaning of \bar by putting it into \foo. I don't know why one would want to have code that does not compile. Unless @gablin's question deals with isolating instances where using a length might be out-of-place. Perhaps the OP will be able to clarify by expanding the original question. –  Werner Sep 29 '11 at 19:38