为什么 \WithSuffix\providecommand 会覆盖 thmtools 可重设环境实例已定义的命令?

为什么 \WithSuffix\providecommand 会覆盖 thmtools 可重设环境实例已定义的命令?

考虑输出

MWE 的输出

此 MWE:

\documentclass{book}

\usepackage{amsthm}
\usepackage{thmtools}
\usepackage{suffix}

\declaretheorem[numberwithin=chapter, style=plain,name=Theorem,refname={theorem,theorems},Refname={Theorem,Theorems}]{theorem}

\begin{document}

\chapter{Test Chapter}

\begin{restatable}[Made-Up Theorem]{theorem}{MadeUpTheorem}
    This is a made-up theorem.
\end{restatable}

Now, let's repeat the restatable theorem:
\MadeUpTheorem*

Next, let's try to define a new command if it has not yet been defined.
\WithSuffix\providecommand\MadeUpTheorem*{ABC}

Let's see what happens:
\MadeUpTheorem*

\textbf{Why does this output ABC? Why not the original theorem?}

I thought providecommand only defined a command if it had not already been defined.

\end{document}

  • (可选)问:为什么会输出 ABC?为什么它不再次输出原来编造的定理?
  • 问:\MadeUpTheorem*更重要的是,如果它以前没有被定义,我该如何“重新定义” ?

即使已经定义,它似乎\providecommand也会覆盖原始定义。\MadeUpTheorem*

在我的用例中,原始文件restatable与调用的文件位于不同的文件中\MadeUpTheorem*。它是使用编译的\include,但在中间编译期间不是包括在内,因此未定义。但在最终编译期间,它被包括在内,因此不应打印“ABC”。

答案1

(可选)问:为什么输出 ABC?为什么不再次输出原来编造的定理?

因为实际上执行的 if-defined-then-skip 条件作用\providecommand于内部命令\WSF:\MadeUpTheorem the character *(由 组成\csname\SuffixName\MadeUpTheorem*\endcsname),而不是\MadeUpTheorem其本身。

由于内部命令始终未定义,因此\MadeUpTheorem后跟星号的行为始终会发生变化。这意味着\WithSuffix\providecommand...和的净效应\WithSuffix\newcommand...相同。

thmtools查看不使用但使用手动定义的示例\mycmd*

\documentclass{article}
\usepackage{suffix}
\usepackage{fvextra} % for \EscVerb

\makeatletter
\def\mycmd{\@ifstar{\mycmd@{starred, original}}{\mycmd@{not starred}}}
\def\mycmd@#1{#1\par}
\makeatother

\parindent=0pt
\begin{document}
\subsection*{initially}
\mycmd
\mycmd*

\subsection*{after \EscVerb{\\WithSuffix\\providecommand\\mycmd*{...}}}
\WithSuffix\providecommand\mycmd*{starred, after \EscVerb{\\WithSuffix}}
\mycmd
\mycmd*
\end{document}

在此处输入图片描述

\MadeUpTheorem*:更重要的是,如果以前没有定义过,我该如何“重新定义” ?

一般来说,没有简单的解决方案。关键在于它\MadeUpTheorem*不是一个单一的命令,而是\MadeUpTheorem后面跟着一个星号,并且\MadeUpTheorem定义了它是否后面跟着可选的星号,其行为会有所不同。

一般条件检查“如果命令/宏接受可选星号”并不简单,但如果您知道该命令是由某些实用程序命令定义的,因此/或其替换文本遵循某种模式,则可以检查这些模式并提供部分解决方案。

例如,\MadeUpTheorem定义的\begin{restatable}[Made-Up Theorem]{theorem}{MadeUpTheorem}模式为

% see https://github.com/muzimuzhi/thmtools/blob/0.74/source/thm-restate.dtx#L201-L207
\gdef\MadeUpTheorem{%
  \@ifstar{%
    \thmt@thisistheonefalse\csname thmt@stored@MadeUpTheorem\endcsname
  }{%
    \thmt@thisistheonetrue\csname thmt@stored@MadeUpTheorem\endcsname
  }%
}
\documentclass{article}
\usepackage{suffix}
\usepackage{amsthm, thmtools}
\usepackage{fvextra} % for \EscVerb

\declaretheorem[numberwithin=section, style=plain,name=Theorem,refname={theorem,theorems},Refname={Theorem,Theorems}]{theorem}

\makeatletter
\def\mycmd{\@ifstar{\mycmd@{starred, original}}{\mycmd@{not starred}}}
\def\mycmd@#1{#1\par}

\newcommand\starred@restatable[1]{%
  \unexpanded{%
    \@ifstar{%
      \thmt@thisistheonefalse\csname thmt@stored@#1\endcsname
    }{%
      \thmt@thisistheonetrue\csname thmt@stored@#1\endcsname
    }%
  }%
}
\newcommand\IfRestatableTF[1]{%
  \begingroup
  \edef\starred@temp{\ExpandArgs{e}\starred@restatable{\scantokens\expandafter{\expanded{\expandafter\@gobble\string#1}\noexpand}}}%
  \expandafter\endgroup
  \ifx#1\starred@temp
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}
\makeatother

\parindent=0pt
\begin{document}
\section{title}
\begin{restatable}[Made-Up Theorem]{theorem}{MadeUpTheorem}
    This is a made-up theorem.
\end{restatable}

\subsection*{initially}
\mycmd
\mycmd*

\MadeUpTheorem
\MadeUpTheorem*

\subsection*{after \EscVerb{\\WithSuffix\\providecommand\\mycmd*{...}}}
\WithSuffix\providecommand\mycmd*{starred, after \EscVerb{\\WithSuffix}}
\mycmd
\mycmd*

\IfRestatableTF\MadeUpTheorem
  {}
  {\WithSuffix\newcommand\MadeUpTheorem*{ABC}}
\MadeUpTheorem
\MadeUpTheorem*
\end{document}

在此处输入图片描述

注意@Ulrike Fischer 的建议(\ProvideDocumentCommand\MadeUpTheorem{s}{abc})检查\MadeUpTheorem其本身是否已定义,而不是是否\MadeUpTheorem已定义接受可选的星星。

相关内容