Переменные TeX становятся локальными в списочных средах?

Переменные TeX становятся локальными в списочных средах?

По-видимому, когда значение счетчика TeX изменяется внутри enumerateсреды (и, несомненно, во многих других контекстах), оно действует как локальная переменная, так что любые изменения в нем являются локальными для среды. Например, этот код

\documentclass{article}

\newcount\total
\total = 5

\begin{document}

At first total = \number\total

\begin{enumerate}
\item \advance \total by 10
      Now total = \number\total
\item \advance \total by 10
      Now total = \number\total
\end{enumerate}

Outside of the enumerate environment, total reverts to its
original value: \number\total\\

Does the same thing happen in embedded environments?
\begin{enumerate}
\item \advance \total by 100
      Now total = \number\total
      \begin{enumerate}
      \item \advance \total by 1000
      Now total = \number\total
      \end{enumerate}
      That didn't do anything to this total = \number\total
\item \advance \total by 100
      Now total = \number\total
\end{enumerate}
Yes.  Now total = \number\total

\end{document}

производит: Изображение LaTeX, сгенерированное предыдущим исходным кодом, показывающее, что общий счетчик становится локальным для каждой среды перечисления, когда его значение изменяется с помощью \advance.

Два вопроса:

  • Как мне понять, что здесь происходит?
  • Какой самый простой способ истории изменения значения внутри enumerateсреды, чтобы измененное значение было доступно за пределами среды? Меня вполне устраивает использование LaTeX вместо TeX. Мне просто нужно простое решение, которое работает.

Почему? Я пишу тест и для каждого вопроса указываю количество баллов, которое он стоит. Когда я отображаю баллы, я также хочу обновить переменную, которая даст мне итог в конце. Иногда я присваиваю баллы подвопросам, которые я перечисляю во встроенной среде. Я хочу, чтобы эти баллы также добавлялись к итогу.

В настоящее время я делаю это так:

\newcount\totalpts
\totalpts = 0
\newcommand{\pts}[1]{(#1 points) \advance \totalpts by #1}

и я использую \ptsкоманду для отображения количества баллов за каждый вопрос. Это работает, если я использую только одну enumerateсреду для отображения вопросов, потому что я могу отобразить общую сумму как часть последнего вопроса. Это не работает, если я назначаю баллы в среде, enumerateкоторая встроена в среду внешних вопросов: баллы, которые я перечисляю для вопросов во встроенной среде, не влияют на общую сумму во внешней среде.

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

1

решение1

Все назначения по умолчанию локальны (есть несколько специальных регистров TeX, которые являются исключением). Это означает, что если группа TeX заканчивается, то регистр возвращается к своему предыдущему значению, действительному при запуске группы.

Если вы используете \globalпрефикс назначения, то назначение является глобальным, его значение сохранится после завершения группы TeX.

Поэтому используйте \global\advanceвместо этого \advanceили определите \def\gadvance{\global\advance}и используйте \gadvanceвместо этого \advance, когда работаете с \totalрегистром. И используйте прямое назначение, \global\total=valueесли он находится в группе TeX.

решение2

Какwipet объяснил, назначения регистрам счетчиков TeX являются локальными для текущей группы. Все среды LaTeX создают группы. Это касается и среды списков, но вы увидите тот же эффект, если продвинете счетчик внутри figure, center, quotationи т. д.

В то время как прямые назначения регистрам счетчиков являются локальными по умолчанию, счетчики LaTeX назначаются глобально. Таким образом, если вы используете counterи \addtocounter{}{}, назначения базовому регистру счетчика будут сделаны глобально и сохранятся за пределами текущей группы.

\documentclass{article}
\newcounter{total}
\setcounter{total}{5}

\begin{document}

At first total = \thetotal

\begin{enumerate}
  \item \addtocounter{total}{10}
  Now total = \thetotal
  \item \addtocounter{total}{10}
  Now total = \thetotal
\end{enumerate}

Outside of the enumerate environment, total reverts to its
original value: \thetotal % never end a paragraph with \\

Does the same thing happen in embedded environments?
\begin{enumerate}
  \item \addtocounter{total}{100}
  Now total = \thetotal
  \begin{enumerate}
    \item \addtocounter{total}{1000}
    Now total = \thetotal
  \end{enumerate}
  That didn't do anything to this total = \thetotal
  \item \addtocounter{total}{100}
  Now total = \thetotal
\end{enumerate}
Yes.  Now total = \thetotal

\end{document}

С помощью этого решения вы также можете переопределить, \thetotalчтобы изменить форматирование, точно так же, как вы можете изменить внешний вид номеров разделов, сносок, номеров уравнений и т. д. Вот почему лучше использовать, \thetotalчем писать\arabic{total} напрямую, даже если в настоящее время это даст тот же результат.

введите описание изображения здесь

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