是什么导致我的类数组宏被污染

是什么导致我的类数组宏被污染

以下 MWE 是我的项目的简化版本。\CreateMacro用于创建表示词汇表的宏。例如,使用 body\CreateMacro{Newton}{$F=ma$}创建。调用将打印其主体并插入类似数组的宏。\Newton$F=ma$\Newton\Newton\pushed

\Einstein例如,如果我们已经创建了,并调用了\Einstein,那么\Einstein也将插入到中\pushed

调用\Render将使所有元素变为\pushed\pushed

但是,我注意到有时\pushed会受到污染,如以下输出所示。我不明白为什么\Newton第九项仍然存在。第九项 \Newton不应该在那里。这似乎是由竞争条件引起的。你能找出并修复它吗?

在此处输入图片描述

\documentclass{book}

\usepackage{xcolor}
\usepackage{etoolbox}
\usepackage[many]{tcolorbox}


\def\Format#1{%
    \begin{tcolorbox}%
        \textcolor{red}{#1}%
    \end{tcolorbox}%
}

\newenvironment{Table}
{\begin{tcbraster}[%
        raster height=\textwidth,
        raster width=\linewidth,
        raster columns=2,
        raster rows=4,
        boxrule=2pt,
        raster column skip=-2pt,
        raster row skip=-2pt,
]}
{\end{tcbraster}}




\newcommand\CreateMacro[2]{%
    \expandafter\newrobustcmd\csname#1\endcsname{#2\gappto\pushed{\Format{#2}}}%
}


\gdef\Render{%
    \Table
        \pushed
    \endTable
    \gdef\pushed{}%
}




\begin{document}
\CreateMacro{Newton}{$F=ma$.}

\chapter{\Newton}
\Render


\begin{enumerate}
    \item 
    \CreateMacro{Einstein}{$E=mc^2$}
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

\end{enumerate}
\end{document}

答案1

\Newton宏被传递给\leftmark,因为它出现在章节标题中,所以在打印标题时对其进行评估并执行推送。

你必须消除这种行为。如果你打算做目录,也需要类似的消除。

\documentclass{book}

\usepackage{xcolor}
\usepackage{etoolbox}
\usepackage[many]{tcolorbox}
\usepackage{environ}
\usepackage{xparse}

\makeatletter
\renewcommand{\chaptermark}[1]{%
  \markboth{%
    % don't push as result of evaluating the heading
    \let\noexpand\push\noexpand\@gobble
    % the standard definition follows
    \MakeUppercase{%
      \ifnum\c@secnumdepth>\m@ne
        \if@mainmatter
          \@chapapp\ \thechapter. \ %
        \fi
      \fi
      #1%
    }%
  }{}%
}
\makeatother


\newcommand\Format[1]{%
    \begin{tcolorbox}%
        \textcolor{red}{#1}%
    \end{tcolorbox}%
}

\newenvironment{Table}
{\begin{tcbraster}[%
        raster height=\textwidth,
        raster width=\linewidth,
        raster columns=2,
        raster rows=4,
        boxrule=2pt,
        raster column skip=-2pt,
        raster row skip=-2pt,
]}
{\end{tcbraster}}

\newcommand\CreateMacro[2]{%
  \expandafter\newrobustcmd\csname#1\endcsname{#2\push{\Format{#2}}}%
}

\newcommand\push[1]{\gappto\pushed{#1}}

\newcommand\Render{%
    \begin{Table}
        \pushed
    \end{Table}%
    \gdef\pushed{}%
}

\begin{document}
\CreateMacro{Newton}{$F=ma$.}
\CreateMacro{Einstein}{$E=mc^2$}

\chapter{\Newton}
\Render


\begin{enumerate}
    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

\end{enumerate}
\end{document}

在此处输入图片描述

一个可能更强大的补丁是使和执行时\push相等。\@gobble\@starttoc\@outputpage

\documentclass{book}

\usepackage{xcolor}
\usepackage{etoolbox}
\usepackage[many]{tcolorbox}
\usepackage{environ}
\usepackage{xparse}

\makeatletter
\patchcmd{\@starttoc}{\begingroup}{\begingroup\let\push\@gobble}{}{}
\patchcmd{\@outputpage}{\begingroup}{\begingroup\let\push\@gobble}{}{}
\makeatother

\newcommand\Format[1]{%
    \begin{tcolorbox}%
        \textcolor{red}{#1}%
    \end{tcolorbox}%
}

\newenvironment{Table}
{\begin{tcbraster}[%
        raster height=\textwidth,
        raster width=\linewidth,
        raster columns=2,
        raster rows=4,
        boxrule=2pt,
        raster column skip=-2pt,
        raster row skip=-2pt,
]}
{\end{tcbraster}}

\newcommand\CreateMacro[2]{%
  \expandafter\newrobustcmd\csname#1\endcsname{#2\push{\Format{#2}}}%
}

\newcommand\push[1]{\gappto\pushed{#1}}

\newcommand\Render{%
    \begin{Table}
        \pushed
    \end{Table}%
    \gdef\pushed{}%
}

\begin{document}
\CreateMacro{Newton}{$F=ma$.}
\CreateMacro{Einstein}{$E=mc^2$}

\tableofcontents

\chapter{\Newton}
\Render


\begin{enumerate}
    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

\end{enumerate}
\end{document}

然而,在我看来,最好的做法是完全避免在标题中使用此类宏;在接下来的代码中,\CreateMacro{Newton}{$F=ma$}定义也要\Newton*在标题中使用,并且应该\pushNewton在更安全的时候使用。

\documentclass{book}

\usepackage{xcolor}
\usepackage{etoolbox}
\usepackage[many]{tcolorbox}
\usepackage{environ}
\usepackage{xparse}
\usepackage{atbegshi}

\newcommand\Format[1]{%
    \begin{tcolorbox}%
        \textcolor{red}{#1}%
    \end{tcolorbox}%
}

\newenvironment{Table}
{\begin{tcbraster}[%
        raster height=\textwidth,
        raster width=\linewidth,
        raster columns=2,
        raster rows=4,
        boxrule=2pt,
        raster column skip=-2pt,
        raster row skip=-2pt,
]}
{\end{tcbraster}}

\makeatletter
\newcommand\CreateMacro[2]{%
  \expandafter\newrobustcmd\csname#1\endcsname{%
    \@ifstar{\@nameuse{#1star}}{\@nameuse{#1nostar}}%
  }%
  \@namedef{#1nostar}{#2\push{\Format{#2}}}%
  \@namedef{#1star}{#2}% \global\toggletrue{#1}}%
  \@namedef{push#1}{\push{\Format{#2}}}%
}
\makeatother

\newcommand\push[1]{\gappto\pushed{#1}}

\newcommand\Render{%
    \begin{Table}
        \pushed
    \end{Table}%
    \gdef\pushed{}%
}

\begin{document}
\CreateMacro{Newton}{$F=ma$.}
\CreateMacro{Einstein}{$E=mc^2$}

\tableofcontents

\chapter{\Newton*}\pushNewton
\Render


\begin{enumerate}
    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

    \item 
    \Einstein
    \Render

\end{enumerate}
\end{document}

相关内容