
Por que é \setlength
ineficaz dentro de um tabular
ambiente? Aqui está um 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}
Enquanto os dois primeiros pontos estão bem alinhados, o terceiro é diferente e se comporta como se \locallength
estivesse 0pt
. Por que isso acontece e o que posso fazer? Quero usar \setwidth
dentro do tabular
ambiente, então definir o comprimento fora do ambiente não é realmente uma opção.
Responder1
As células de alinhamento são processadas dentro de um grupo implícito, portanto as atribuições locais às variáveis são desfeitas quando o grupo termina.
A definição do kernel \setlength
é
% latex.ltx, line 2181:
\def\setlength#1#2{#1 #2\relax}
e é por isso\global\setlength
parecetrabalhar. Por outro lado, a definição de \settowidth
é
% latex.ltx, line 2187:
\def\settowidth {\@settodim\wd}
e a definição de \@settodim
é
% latex.ltx, line 2183:
\def\@settodim#1#2#3{\setbox\@tempboxa\hbox{{#3}}#2#1\@tempboxa
\setbox\@tempboxa\box\voidb@x}
Assim \global\settowidth{\locallength}{abc}
se tornaria
\global\setbox\@tempboxa\hbox{{abc}}\locallength\wd\@tempboxa\setbox\@tempboxa\box\voidb@x
o que, obviamente, é ineficaz para fazer uma atribuição global para \locallength
.
Sim, \settowidth{\global\locallength}{abc}
funcionaria, mas é apenas por acaso.
Não há suporte no LaTeX para atribuições de dimensão/pular global e você deve confiar em comandos de nível inferior. Então uma maneira mais segura é definir novos 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
e da mesma forma para \gsettoheight
e \gsettodepth
se necessário.
Isso funcionará mesmo se calc
estiver carregado e não explorar nenhuma implementação específica dos comandos “locais”.
Responder2
Ambos \global\setlength{\locallength}{10pt}
e \setlength{\global\locallength}{10pt}
parecem funcionar, mas não tenho ideia de por que isso seria necessário.
https://tex.stackexchange.com/a/210598/30810me fez tentar, e o comentário de @ChristianHupfer explica o porquê.
No meu documento mais longo, \global\settowidth{...}
não funcionou; \settowidth{\global...}
fez.