Como evitar a redefinição de definições de macro dentro de um grupo/ambiente

Como evitar a redefinição de definições de macro dentro de um grupo/ambiente

Aqui está a pergunta: por que o código a seguir redefine o significado da \pgPtListsequência de controle quando o grupo termina?

\documentclass[12pt]{article}

\begin{document}

\begingroup
    \gdef\pgPtList{}
    \edef\pgPtList{8}
    pgPtList is: \pgPtList
    
    \edef\pgPtList{8, 5}
    pgPtList is: \pgPtList
\endgroup

Empty environment has ended.

pgPtList is: \pgPtList

\end{document}

Aqui está a saída que ele produz:

pgPtList is: 8
pgPtList is: 8, 5
Empty environment has ended.
pgPtList is:

Meu entendimento atual é que isso tem algo a ver com a forma como os grupos funcionam, então uma provável pergunta de acompanhamento é esta: como posso redefinir a sequência de controle de modo que a mudança permaneça quando o grupo terminar?

Este é o contexto mais amplo: estou tentando compor um exame e monitorar o número de pontos em cada página, e estou atualizando continuamente \pgPtListpara controlar quantos pontos há em cada página. Em cada exame, \pgPtListatua como parâmetro padrão para outro comando que cria uma tabela de valores de pontos.

Os pontos de cada página são atualizados dentro de um enumerateambiente, por isso os \begingroupe \endgroupestão presentes no reprex. Idealmente, eu gostaria de poder atualizar a \pgPtListvariável dentro deste ambiente, mesmo que o comando da tabela de pontos seja chamado fora dele.

Meu principal ponto de confusão é ao redor \edefe \gdef. Meu entendimento ingênuo é que esses comandos têm como objetivo tornar as sequências de controle resultantes acessíveis fora do grupo atual, mas a saída que recebo do código acima sugere que algo mais está acontecendo.

Responder1

  • \def\macroname<argument specification>{definition}é uma definição padrão local;
  • \edef\macroname<argument specification>{definition}é uma definição local expandida, ou seja, definitioné expandida antes da atribuição \macroname;
  • \gdef\macroname<argument specification>{definition}é uma definição global e padrão;
  • \xdef\macroname<argument specification>{definition}é uma definição global e expandida.

No seu caso, a definição inicial\gdef\pgPtList{} fazsobreviver ao grupo local. Caso contrário, o uso de \pgPtListafter \endgroupresultaria em um erro.

No entanto, todas as (re)definições subsequentes de \pgPtListsão explicitamente locais, de modo que essas mudanças não sobrevivem \endgroupe o significado de \pgPtListreverte para a definição inicial vazia.

O exemplo a seguir pode ser útil:

\documentclass[12pt]{article}

\begin{document}

\newcounter{tweak}
\setcounter{tweak}{0}
\def\rstatement{Redefinition \thetweak.}

\begingroup
  \gdef\pgPtList{Initial, global definition.}
  pgPtList is: \pgPtList
  
  \edef\pgPtList{\rstatement}
  pgPtList is: \pgPtList ; \stepcounter{tweak}\pgPtList
  
  \def\pgPtList{\rstatement}
  pgPtList is: \pgPtList ; \stepcounter{tweak}\pgPtList
\endgroup

Environment has ended.

pgPtList is: \pgPtList

\begingroup
  \xdef\pgPtList{\rstatement}
  pgPtList is: \pgPtList ; \stepcounter{tweak}\pgPtList
\endgroup

Environment has ended.

pgPtList is: \pgPtList

\begingroup
  \gdef\pgPtList{\rstatement}
  pgPtList is: \pgPtList ; \stepcounter{tweak}\pgPtList
\endgroup

Environment has ended.

pgPtList is: \pgPtList

\end{document}

saída ilustrando definições de macro locais/globais e expandidas/padrão

Observe que \defe \gdefcertifique-se \pgPtListde usar o valor do contador tweakquando a macro \pgPtListfor usada, que pode não ser o valor no momento da definição.

Por outro lado, \edefe \xdefgarantir \pgfPtListusa o valor do contador tweakno momento da definição, mesmo que o valor tenha mudado nesse meio tempo.

Por outro lado, ambos \defe \edefsão definições locais. Seu efeito termina quando o grupo atual termina.

Em contraste, \gdefe \xdefsão globais. Eles são eficazes a menos e até que alguma definição subsequente \pgfPtListos substitua, independentemente do agrupamento.

informação relacionada