\variante global de \csname…\endcsname

\variante global de \csname…\endcsname

Considere o seguinte exemplo mínimo:

\documentclass{article}
\tracingrestores=1

\def\foo{\bar\foobar}
\def\bar{\gdef\testA{blabb}}
\def\foobar{\expandafter\gdef\csname testB\endcsname{blubb}}

\begin{document}
{\foo}

\testA
\testB

\end{document}

O arquivo de log resultante contém uma entrada {retaining \testB=macro:->blubb}, mas nenhuma entrada correspondente para \testA. Pelo que entendi o TeX, isso significa que \csname...\endcsnamedefine a macro \testAcomo \relaxlocalmente, que imediatamente após reatribuo globalmente como "blubb", que, por sua vez, adiciona uma entrada de retenção no meu save_stack.

Em meu aplicativo do mundo real, preciso ser capaz de definir um número potencialmente infinito de macros nomeadas individualmente usando construções csname, o que agora levou a um estouro de pilha por causa disso. (bem, talvez não infinito, mas definitivamente mais de 80.000…)

Minha pergunta agora é: existe uma maneira de inicializar um \csname…\endcsname-construct globalmente para evitar que eles sejam empilhados na pilha de salvamento? Ou algum tipo de solução alternativa que mantenha minha pilha de salvamento limpa?

Responder1

Em vez de tornar a \csnameatribuição global, você pode torná-la ainda mais local:

\documentclass{article}
\tracingrestores=1

\def\foo{\bar\foobar}
\def\bar{\gdef\testA{blabb}}
\def\foobar{\begingroup\expandafter\endgroup\expandafter\gdef\csname testB\endcsname{blubb}}

\begin{document}
{\foo}

\testA
\testB

\end{document}

Agora o \expandafteré executado em grupo, então é definido \csnameem um grupo que termina antes de começar. Portanto, é indefinido quando ocorre a definição global, o que deve evitar a retenção da entrada.\testB\relax\gdef\testB

Responder2

Eu não sei nada sobre pilhas (La)TeX (além de stackengine, LOL), mas se o objetivo é evitar ter o \csnameinterior de um \def...

Expanda o \csnameantes de executar o outer \def.

\documentclass{article}
\tracingrestores=1

\def\foo{\bar\foobar}
\def\bar{\gdef\testA{blabb}}
\expandafter\def\expandafter\foobar\expandafter{\expandafter\gdef\csname testB\endcsname{blubb}}

\begin{document}
{\foo}

\testA
\testB

\end{document}

informação relacionada