Alignment cells are processed inside an implicit group, so local assignments to variables are undone when the group ends.
The kernel definition of \setlength
is
% latex.ltx, line 2181:
\def\setlength#1#2{#1 #2\relax}
which is why \global\setlength
seems to work. On the other hand, the definition of \settowidth
is
% latex.ltx, line 2187:
\def\settowidth {\@settodim\wd}
and the definition of \@settodim
is
% latex.ltx, line 2183:
\def\@settodim#1#2#3{\setbox\@tempboxa\hbox{{#3}}#2#1\@tempboxa
\setbox\@tempboxa\box\voidb@x}
Thus \global\settowidth{\locallength}{abc}
would become
\global\setbox\@tempboxa\hbox{{abc}}\locallength\wd\@tempboxa\setbox\@tempboxa\box\voidb@x
which of course is ineffective in making a global assignment to \locallength
.
Yes, \settowidth{\global\locallength}{abc}
would work, but it's just by chance.
There is no support in LaTeX for global dimension/skip assignments and you should rely on lower level commands. So a safer way is to define new commands:
\makeatletter
\newlength\local@length@for@global
\newcommand\gsetlength[2]{%
\setlength{\local@length@for@global}{#2}%
\global#1\local@length@for@global
}
\newcommand{\gsettowidth}[2]{%
\settowidth{\local@length@for@global}{#2}%
\global#1\local@length@for@global
}
\makeatother
and similarly for \gsettoheight
and \gsettodepth
if needed.
This will work even if calc
is loaded and does not exploit any particular implementation of the “local” commands.
locally
set, i.e. in a group. A table cell is a group! That's why you need a\global\setlength{....}
\global\setlength
will not work with packagecalc
.\setlength{\global\locallength}
will work withcalc
, but it won't for\addtolength
. A way independent from the implementation of\setlength
:\setlength{\locallength}{...}\global\locallength=\locallength
.