Geänderte Makrodefinition wird auf Original zurückgesetzt

Geänderte Makrodefinition wird auf Original zurückgesetzt

Ich habe zwei Befehle \testoneund \testtwo. \testtwoerscheint nur, wenn vorher ein relevanter Befehl vorhanden war \testoneund dieselben Argumente verwendet. Daher möchte ich \testoneseine Argumente dort speichern, \@repeat@mewo \testtwosie wieder abgerufen werden, damit ich sie nicht zweimal eingeben muss.

Dies funktioniert jedoch nur, wenn sich beide in derselben Umgebung befinden. In einigen Fällen wird jedoch entschieden, dass der geänderte Wert \@repeat@meignoriert werden soll.

\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}

Antwort1

Wenn Sie eine globale Zuweisung wünschen (um Gruppen und Umgebungen zu entkommen, benötigen Sie) \global\def(oder \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}

Antwort2

Beachten Sie, dass TeX einen Bereich erzwingt, innerhalb dessen (Neu-)Definitionen bestehen bleiben und außerhalb davon rückgängig gemacht werden können. Genau das passiert hier. Sehen wir uns die Erweiterungen an:

\testone{Hello World} \testtwo{}

erweitert zu (mit Kommentaren)

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

das sich ausdehnt auf

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

Bildbeschreibung hier eingeben

Schauen Sie sich nun die Erweiterungen des zweiten Makrosatzes an:

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

erweitert zu (mit Kommentaren)

\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{}

das sich ausdehnt auf

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

Bildbeschreibung hier eingeben

Die Verwendung einer globalen Definition wie \gdefführt dazu, dass die Neudefinition von \@repeat@meüber den durch bereitgestellten Rahmen hinaus überlebt \textbf{..}.


Bildbeschreibung hier eingeben

\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}

verwandte Informationen