更改後的巨集定義恢復為原始定義

更改後的巨集定義恢復為原始定義

我有兩個命令\testone\testtwo\testtwo僅當之前存在相關\testone且採用相同參數時才會出現。因此,我想\testone將其參數儲存在再次獲取它們的\@repeat@me位置\testtwo,這樣我就不必輸入兩次。

但是,只有當兩者處於同一環境中時,這才有效。但在某些情況下,它決定\@repeat@me忽略的更改值。

\documentclass{article}
\makeatletter

\def\@repeat@me{}

\newcommand\testtwo{\bf{\@repeat@me}% print what is currently defined.
% reset the definition so it does not interfere with next call
\def\@repeat@me{}}

% print it and then remember it.
\newcommand\testone[1]{\def\@repeat@me{#1}\emph{\@repeat@me}}%

\makeatother
\begin{document}

% prints: \emph{Hello World} \bf{Hello World}
\testone{Hello World} \testtwo{}

% prints: \bf{\emph{Hello World}}
% intended: \bf{\emph{Hello World}} \bf{Hello World}
\bf{\testone{Hello World}} \testtwo{}

\end{document}

答案1

如果您想要全域分配(為了逃避群組和環境,您需要)\global\def(或\gdef):

\documentclass{scrartcl}

\makeatletter
\newcommand*\@repeat@me{}
\newcommand*\testtwo{\textbf{\@repeat@me}\gdef\@repeat@me{}}
\newcommand\testone[1]{\gdef\@repeat@me{#1}\emph{\@repeat@me}}
\makeatother

\begin{document}

\testone{Hello World} \testtwo
\textbf{\testone{Hello World}} \testtwo

\end{document}

答案2

請注意,TeX 強制規定了(重新)定義可以存在並在外部恢復的範圍。這就是這裡發生的事情。我們來看看擴充:

\testone{Hello World} \testtwo{}

擴展為(帶註釋)

\def\@repeat@me{Hello World}\emph{\@repeat@me} % \testone{Hello World}
\textbf{\@repeat@me}\def\@repeat@me{}% \testtwo{}

擴展到

\emph{Hello World} \textbf{Hello World}% Using the new definition of \@repeat@me

在此輸入影像描述

現在來看看第二組巨集的擴充:

\textbf{\testone{Hello World}} \testtwo{}

擴展為(帶註釋)

\textbf{% <--- start of a group/scope
  def\@repeat@me{Hello World}\emph{\@repeat@me}% \testone{Hello World}
} % <--- end of a group/scope
\textbf{\@repeat@me}\def\@repeat@me{}% \testtwo{}

擴展到

\textbf{\emph{Hello World}} % At scope-end, \@repeat@me reverts to its original definition
\textbf{}% Since \@repeat@me is empty {}

在此輸入影像描述

使用像這樣的全域定義\gdef使得生存的重新定義\@repeat@me超出了所提供的範圍\textbf{..}


在此輸入影像描述

\documentclass{article}
\makeatletter

\def\@repeat@me{}

% print it and then remember it.
\newcommand\testone[1]{\gdef\@repeat@me{#1}\emph{\@repeat@me}}%

\newcommand\testtwo{\textbf{\@repeat@me}% print what is currently defined.
  % reset the definition so it does not interfere with next call
  \def\@repeat@me{}}

\makeatother
\begin{document}

% prints: \emph{Hello World} \textbf{Hello World}
\testone{Hello World} \testtwo{}

% prints: \textbf{\emph{Hello World}} \textbf{Hello World}
\textbf{\testone{Hello World}} \testtwo{}

\end{document}

相關內容