[Tex/LaTex] Is it a bad practice to declare variables locally inside macros or environments

best practicesplain-tex

For me, declaring variables globally will clutter the project. Especially when there are many variables to be declared.

In addition, declaring variables locally will save our time because we don't need to make sure whether the variables have been declared.

I don't know whether it is a bad practice in TeX.

\documentclass{minimal}

\newcommand\Average[5]{%
\newcount\Total%
\Total\numexpr#1+#2+#3+#4+#5\relax%
\number\numexpr\Total/5\relax%
}

\begin{document}
The average of 1, 2, 3, 4, 5 is \Average{1}{2}{3}{4}{5}.
\end{document}

Best Answer

I've examined this in a bit more detail in my blog, but for the purposes of answering the question I'll do a bit of editing and post the key points here.

First, the standard \newcount, \newtoks, etc., functions allocate globally. So something like

\begingroup  
  \newcount\mycount
\endgroup

will permanently consume a register, even though \mycount disappears at the end of the group. The etex package provides \loccount, \loctoks, etc., which do free up the allocation at the end of a group. So

\begingroup  
  \loccount\mycount
\endgroup

is at least not going to consume registers. However, there are other issues.

In most languages, a local variable is local to some function, and nested functions have there own independent local variables. In TeX, things are different, as it is a macro language and only grouping makes things local. So something like

\def\BadIdea{%
  \loccount\mycount
  ...
}

will not destroy \mycount at the end of the material inserted by \BadIdea. On the other hand, things will work within a group, so doing

\def\BetterIdea{%
  \begingroup
    \loccount\mycount
    ....
  \endgroup
}

will destroy \mycount as expected. However, you'd get much the same effect by doing

\newcount\mycount
\def\BetterIdea{%
  \begingroup
    ....
  \endgroup
}

or even (if you know it's safe)

\def\BetterIdea{%
  \begingroup
    \@tempcnta=<value>
    ....
  \endgroup
}

i.e. using the general scratch registers.

As local variables for TeX are about groups, and not about macros, I think that best practice remains to allocate globally and use locally. With my LaTeX3 'hat' on, I'd point out that we did try some local allocations out, and when we worked things through decided it was a bit of a nightmare.

Related Question