\ifx\somecommand\undefined 和 \ifdefined\somecommand\else 之间有什么区别?

\ifx\somecommand\undefined 和 \ifdefined\somecommand\else 之间有什么区别?

\ifx\cyrdash\undefined和之间有什么区别\ifdefined\cyrdash\else\cyrdash 是任何宏吗?

答案1

当然,它们的语法不同。

  1. \ifx\cyrdash\undefined是测试宏是否未定义的传统方法。当然,\undefined不是被定义。

  2. eTeX 中有\ifdefined\ifcsname原语。它们没有其他副作用。

  3. 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

相关内容