\ifx\cyrdash\undefined
和之间有什么区别\ifdefined\cyrdash\else
?\cyrdash
是任何宏吗?
答案1
当然,它们的语法不同。
\ifx\cyrdash\undefined
是测试宏是否未定义的传统方法。当然,\undefined
,不是被定义。eTeX 中有
\ifdefined
和\ifcsname
原语。它们没有其他副作用。LaTeX
\@ifundefined
测试宏是否被定义或是否具有与 相同的含义\relax
。此外,\@ifundefined{undefinedfoo}{...}{...}
会使\undefinedfoo
成为\relax
。
通常情况下,
\ifx\foo\undefined A \else B \fi
和
\ifdefined\foo B \else A \fi
eTeX 原语可能更安全一些。也就是说,我们不需要担心是否\undefined
真的未定义。
但是这两种用法是不同的:
% wrong
% \expandafter\ifx\csname foo\endcsname\undefined A \else B \fi % This is always false
\expandafter\ifx\csname foo\endcsname\relax A \else B \fi % This is \@ifundefined
和
\ifcsname foo\endcsname B \else A \fi
事实上,\csname undefined\endcsname
使得\undefined
为\relax
,而\ifcsname undefined\endcsname
使得\undefined
不变。这就是为什么\ifcsname
在 eTeX 中 是必要的。
测试代码:
\documentclass{minimal}
\long\def\themeaning#1{\string#1: \meaning#1\par}
\begin{document}
\makeatletter\ttfamily
\def\known{abc}
\let\empty\relax
% initial
\themeaning\known
\themeaning\empty
\themeaning\unknown
\hrulefill
% useful eTeX extension
\ifdefined\known yes\else no\fi\par
\ifdefined\empty yes\else no\fi\par
\ifdefined\unknown yes\else no\fi\par
\hrulefill
% Or
\ifcsname known\endcsname yes\else no\fi\par
\ifcsname empty\endcsname yes\else no\fi\par
\ifcsname unknown\endcsname yes\else no\fi\par
\hrulefill
% the meanings are unchanged
\themeaning\known
\themeaning\empty
\themeaning\unknown
\hrulefill
% LaTeX2e kernel
\@ifundefined{known}{yes}{no}\par
\@ifundefined{empty}{yes}{no}\par
\@ifundefined{unknown}{yes}{no}\par
\hrulefill
% \unknown is changed
\themeaning\known
\themeaning\empty
\themeaning\unknown
\end{document}
答案2
根据TeX 按主题分类 \ifx
按以下方式测试宏相等性。
令牌的平等性测试比上述测试更严格,方法是
\ifx token1 token2
如果字符标记
\ifx
具有相同的字符代码和类别代码,则它们是相等的。如果控制序列标记代表相同的 TeX 基元,或者已由
\font
、\countdef
或类似方法定义,则它们相等。例如,\let\boxhor=\hbox \ifx\boxhor\hbox %is true \font\a=cmr10 \font\b=cmr10 \ifx\a\b %is true
\outer
如果控制序列是具有相同参数文本和替换文本的宏,并且相对于和具有相同的状态,则它们也是相等的\long
。例如,\def\a{z} \def\b{z} \def\c1{z} \def\d{\a} \ifx\a\b %is true \ifx\a\c %is false \ifx\a\d %is false
遵循此测试的令牌不会被扩展。
以上内容指的是ifcat
此处,也可以在 TeX by Topic 中找到。我猜你\@ifundefined
说的意思是来自 LaTeX 内核\ifundefined
。这可以通过以下方式简单地实现:
\expandafter \ifx \csname cmd name\endcsname \relax
它利用了如果 csname 未定义,\csname
机制将扩展的事实。因此,基本上最大的区别在于它更灵活,它允许您检查标记的相等性,而不仅仅是检查 csname 是否已定义。此外,它接受一个标记,而它接受一个 csname。\relax
\ifx
\ifx
\@ifundefined
答案3
以及\undefined
都是\ifundefined
宏,不能保证它们没有被某些包重新定义。
的根ifundefined
可以在 TeXBook 中的练习 7.7(第 40 页)中找到,其中 Knuth 要求读者定义这样一个宏。
当
\csname
首次使用 来定义控制序列时,该控制序列将与 等效,\relax
直到重新定义为止。利用这一事实来设计宏\ifundefined#1
,例如,\ifundefined{TeX} true text\else false text\fi
\TeX
如果之前没有定义过,或者\TeX
已经\let
等于,则扩展为真实文本\relax
;否则,它应该扩展为虚假文本。
您可以使用以下方式检查其内容meaning:
\documentclass{article}
\begin{document}
\makeatletter
%\def\undefined{\relax}
\texttt{TeX: \meaning\TeX}\\
\texttt{ifundefined: \meaning\ifundefined}\\
\texttt{@ifundefined: \meaning\@ifundefined}\\
\texttt{undefined: \meaning\undefined}\\
\makeatother
\end{document}
正如您在 LaTeX 中看到的,它们是等效的。LaTeX 还提供@ifundefined
。