¿Por qué \setlength es ineficaz dentro de un entorno tabular?

¿Por qué \setlength es ineficaz dentro de un entorno tabular?

¿Por qué es \setlengthineficaz dentro de un tabularentorno? Aquí hay un 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}

Mientras que los dos primeros puntos están bien alineados, el tercero es diferente y se comporta como si \locallengthlo estuviera 0pt. ¿Por qué es eso y qué puedo hacer? Quiero usarlo \setwidthdentro del tabularentorno, por lo que establecer la longitud fuera del entorno no es realmente una opción.

Respuesta1

Las celdas de alineación se procesan dentro de un grupo implícito, por lo que las asignaciones locales a las variables se deshacen cuando finaliza el grupo.

La definición del núcleo de \setlengthes

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

es por eso que\global\setlength parecetrabajar. Por otro lado, la definición de \settowidthes

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

y la definición de \@settodimes

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

Así \global\settowidth{\locallength}{abc}se convertiría

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

lo cual, por supuesto, es ineficaz para realizar una asignación global a \locallength.

Sí, \settowidth{\global\locallength}{abc}funcionaría, pero es sólo por casualidad.

No hay soporte en LaTeX para asignaciones de dimensión/salto global y debe confiar en comandos de nivel inferior. Entonces, una forma más segura es definir nuevos comandos:

\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

y de manera similar para \gsettoheighty \gsettodepthsi es necesario.

Esto funcionará incluso si calcestá cargado y no explota ninguna implementación particular de los comandos "locales".

Respuesta2

Ambos \global\setlength{\locallength}{10pt}parecen \setlength{\global\locallength}{10pt}funcionar, pero no tengo idea de por qué sería necesario.

https://tex.stackexchange.com/a/210598/30810Me hizo probarlo y el comentario de @ChristianHupfer explica por qué.

En mi documento más extenso, \global\settowidth{...}no funcionó; \settowidth{\global...}hizo.

información relacionada