Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

What is the difference between \ifx\cyrdash\undefined and \ifdefined\cyrdash\else? \cyrdash is any macro.

share|improve this question
1  
Sorry for typos. Question should be: What is the difference between \ifx\cyrdash\undefined and \ifdefined\else\cyrdash? –  Igor Kotelnikov Oct 15 '11 at 13:37
    
I changed the question (and the title) to match the real problem. –  egreg Oct 15 '11 at 19:27

3 Answers 3

up vote 24 down vote accepted

Of course, they have different syntax.

  1. \ifx\cyrdash\undefined is traditional way to test if a macro is undefined. Of course, \undefined sould not be defined.

  2. There are \ifdefined and \ifcsname primitives in eTeX. They have no other side effects.

  3. LaTeX's \@ifundefined test if a macro is defined or it has the same meaning of \relax. Furthermore, \@ifundefined{undefinedfoo}{...}{...} will makes \undefinedfoo to be \relax.

Normally, there is no difference between

\ifx\foo\undefined A \else B \fi

and

\ifdefined\foo B \else A \fi

eTeX primitives may be a little safer. Say, we don't need to worry about whether \undefined is really undefined.

However, these two usage are different:

% 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

and

\ifcsname foo\endcsname B \else A \fi

In fact, \csname undefined\endcsname makes \undefined to be \relax, while \ifcsname undefined\endcsname makes \undefined unchanged. That's why \ifcsname in eTeX is necessary.


Test code:

\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}
share|improve this answer

According to TeX by Topic \ifx tests macro equality in the following manner.

Equality of tokens is tested in a stronger sense than the above by \ifx token1 token2

  • Character tokens are equal for \ifx if they have the same character code and category code.

  • Control sequence tokens are equal if they represent the same TeX primitive, or have been similarly defined by \font, \countdef, or some such. For example,

    \let\boxhor=\hbox  
    \ifx\boxhor\hbox %is true  
    \font\a=cmr10 \font\b=cmr10 \ifx\a\b %is true 
    
  • Control sequences are also equal if they are macros with the same parameter text and replacement text, and the same status with respect to \outer and \long. For example,

    \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  
    

Tokens following this test are not expanded.

The above refers to ifcat here, also found in TeX by Topic. I presume you mean \@ifundefined from the LaTeX kernel when you say \ifundefined. That is simply implemented in the following manner:

\expandafter \ifx \csname cmd name\endcsname \relax

It uses the fact that the \csname mechanism expands to \relax if the csname is not defined. So basically the biggest difference is that \ifx is more flexible, it allows you to check equality of tokens and not simply whether a csname is defined or not. Furthermore, \ifx takes a token, whereas \@ifundefined takes a csname.

share|improve this answer

Both \undefined as well as \ifundefined are macros and there is no guarantee that they have not been redefined by a some package.

The roots of ifundefined can be found in Exercise 7.7 (p 40) in the TeXBook, where Knuth asked the reader to define such a macro.

When \csname is used to define a control sequence for the first time, that control sequence is made equivalent to \relax until it is redefined. Use this fact to design a macro \ifundefined#1 such that, for example,

\ifundefined{TeX} true text\else false text\fi

expands to the true text if \TeX hasn't previously been defined, or if \TeX has been \let equal to \relax; it should expand to the false text otherwise.

You can examine their content using 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}

As you can see in LaTeX, they are equivalent. LaTeX also offers @ifundefined.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.