我正在使用该类article
,但发现tocloft
包定义了\chapter
,这会弄乱我的其他内容。这是怎么回事?\chapter
加载 后我可以再次使“未定义”吗tocloft
?这是一个 MWE:
\documentclass{article}
% loading tocloft will make \chapter defined
\usepackage{tocloft}
\begin{document}
\ifdefined\chapter
chapter is defined in the current \texttt{article} document.
\chapter{This is not a chapter, but will be typeset as plain text}
\else
chapter is \emph{not} defined.
\fi
\end{document}
答案1
一些包和宏会检查是否\chapter
已定义以便采取某些操作;例如,将参考书目排版为章节(book
和report
类)或部分(article
类)。
\@ifundefined
他们进行的测试基于
\@ifundefined{chapter}
{\section*{\refname}}
{\chapter*{\bibname}}
重要的是要知道,\@ifundefined
当参数中给出的命令名称未定义或等效于时,将返回 true \relax
。实际上,每当使用
\@ifundefined{foo}{<true>}{<false>}
如果之前没有定义过该命令,\foo
那么它将等效于该命令。\relax
相反,\ifdefined
当条件后的标记相当于时,条件也会返回 true \relax
,这就是您观察到这种行为的原因:确实检查了是否tocloft
存在。\chapter
\@ifundefined
这样做的原因是历史原因:LaTeX 需要在发布时或对于时知道是否\foo
定义。因此,宏将名称而不是令牌本身作为参数。它在内部使用具有之前概述的效果:如果未定义,则使用将使其等同于。\newenvironment{foo}
\c@foo
\newcounter{foo}
\@ifundefined
\csname...\endcsname
\foo
\csname foo\encsname
\relax
只要你坚持\@ifundefined
测试定义性,就不会有问题。
\ifdefined
和基元\ifcsname
是 e-TeX 扩展,因此在 LaTeX2e 发布时它们不可用。实际上没有其他可靠的方法来检查定义性;另一种策略是与未定义的标记进行比较(有\@undefined
针对此情况的策略)。但是,\csname...\endcsname
除非使用巧妙的技巧,否则问题仍然存在:
\def\@ifundefined#1{%
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname#1\endcsname\@undefined
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi}
因此,如果未定义,则\@ifundefined{foo}
不会保留\foo
等同于。但是,由于和,此测试无法完全扩展,因此开发人员决定保留原样。\relax
\begingroup
\endgroup
\@ifundefined
这个技巧之所以有效,是因为\csname foo\endcsname
在 TeX 扫描之前执行了,\endgroup
所以\relax
一旦 TeX 执行它,与的等价性就会消失;但条件\ifx
已经扩展了。:)
请注意,从 2018 年起的 LaTeX 版本中,的定义已被修改,因此如果之前未定义,\@ifundefined
它不再将测试的命令定义为。\relax
答案2
tocloft
定义\chapter
为\relax
。article
如果您希望它未定义,请发出
\usepackage{tocloft}% http://ctan.org/pkg/tocloft
\let\chapter\undefined
这里\undefined
只是一个未定义的控制序列。它也可能\anyundefinedmacro
,只要它是还不明确的。
\let
将第二个控制序列的整个定义复制到第一个控制序列中,就像它当时定义的那样。由于\undefined
不存在,\chapter
所以将“不存在”。根据您的其他用法,您可能还必须删除其他\chapter
相关定义。但是,如果没有更多信息,这应该就足够了。
\documentclass{article}
% loading tocloft will make \chapter defined
\usepackage{tocloft}% http://ctan.org/pkg/tocloft
\let\chapter\undefined
\begin{document}
\ifdefined\chapter
chapter is defined in the current \texttt{article} document.
\chapter{This is not a chapter, but will be typeset as plain text}
\else
chapter is \emph{not} defined.
\fi
\end{document}