Почему \setlength неэффективен в табличной среде?

Почему \setlength неэффективен в табличной среде?

Почему \setlengthнеэффективен внутри tabularсреды? Вот MWE:

\documentclass{article}
\newlength{\globallength}
\newlength{\locallength}
\begin{document}
\setlength{\globallength}{10pt}%
\begin{tabular}{l}
\setlength{\locallength}{10pt}%

\hspace*{10pt}. \\

\hspace*{\globallength}. \\

\hspace*{\locallength}. \\

\hspace*{0pt}. \\

\end{tabular}
\end{document}

В то время как первые две точки хорошо выровнены, третья отличается и ведет себя так, как будто бы \locallengthэто были 0pt. Почему так и что я могу сделать? Я хочу использовать \setwidthвнутри tabularсреды, поэтому установка длины за пределами среды на самом деле не вариант.

решение1

Ячейки выравнивания обрабатываются внутри неявной группы, поэтому локальные назначения переменным отменяются по завершении группы.

Определение ядра \setlength:

% latex.ltx, line 2181:
\def\setlength#1#2{#1 #2\relax}

вот почему\global\setlength кажетсяработать. С другой стороны, определение \settowidthесть

% latex.ltx, line 2187:
\def\settowidth {\@settodim\wd}

и определение \@settodimесть

% latex.ltx, line 2183:
\def\@settodim#1#2#3{\setbox\@tempboxa\hbox{{#3}}#2#1\@tempboxa
       \setbox\@tempboxa\box\voidb@x}

Таким образом \global\settowidth{\locallength}{abc}, станет

\global\setbox\@tempboxa\hbox{{abc}}\locallength\wd\@tempboxa\setbox\@tempboxa\box\voidb@x

что, конечно, неэффективно при выполнении глобального назначения \locallength.

Да, \settowidth{\global\locallength}{abc}это сработало бы, но это просто случайность.

В LaTeX нет поддержки глобальных назначений размерности/пропуска, и вам следует полагаться на команды более низкого уровня. Поэтому более безопасный способ — определить новые команды:

\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

и аналогично для \gsettoheightи \gsettodepthесли необходимо.

Это будет работать, даже если calcзагружено и не использует какую-либо конкретную реализацию «локальных» команд.

решение2

Оба варианта \global\setlength{\locallength}{10pt}, \setlength{\global\locallength}{10pt}похоже, работают, но я понятия не имею, зачем это нужно.

https://tex.stackexchange.com/a/210598/30810заставил меня попробовать это, и комментарий @ChristianHupfer объясняет, почему.

В моем более длинном документе \global\settowidth{...}не сработало; \settowidth{\global...}сработало.

Связанный контент