48

I thought the way to undo a \def was to define it to \relax, but that does not appear to work. Also, am not sure why this produces no output if I try to use \def instead of \let in my attempt to do an undef.

\documentclass{article}

\begin{document}

\def\CaseA{}%

\ifdefined\CaseA%
    \def\ProcessCaseA{}%
    % Do stuff that uses \ProcessCaseA
    %\def\ProcessCaseA\relax% no output if use this, and comment next line
    \let\ProcessCaseA\relax% no output if comment this, and use above line
\fi

% Now do stuff that requires \ProcessCaseA NOT be defined
\ifdefined\ProcessCaseA
    ERROR: \textbackslash ProcessCaseA is still defined
\else
    SUCCESS: \textbackslash ProcessCaseA is not defined
\fi

\end{document}

3 Answers 3

27

The macro \ifdefined is not part of basic TeX, so I suppose you are getting it from eTeX. In that case, you should consider using the etoolbox package, which provides a few wrapper functions \ifdef{\macro}{true}{false} and \ifundef{\macro}{true}{false}. The etoolbox manual tells me that the latter has the convenient effect of registering a macro \let to \relax as being "undefined", which sounds like what you want.

Alternatively, depending on the situation, if you truly wish to erase a macro from TeX's memory, you can define it in a group and then leave the group. Note that this is quite different from \letting it to \relax, since if TeX tries to read \macro before it has ever been \def'd or \let, it will raise an error, while if you have written \let\macro=\relax, it will just do nothing.

5
  • Adding \begingroup and \endgroup worked great. Thanks. Commented Jun 14, 2011 at 0:22
  • 11
    etoolbox also has \undef.
    – Philipp
    Commented Jun 14, 2011 at 5:27
  • @Philipp: so it does! I never went to that section of the manual.
    – Ryan Reich
    Commented Jun 14, 2011 at 13:53
  • 4
    @RyanReich Could you update your answer including an example of the use of \begingroup and \endgroup? I understand the spirit, but I'm having problems implementing it! Thank you.
    – Dox
    Commented Apr 24, 2015 at 12:08
  • 1
    Note, the "define in group then leave group" solution as far as I can see only works when the original definition can be moved inside a group. If it's already defined globally/in the current level, no amount of group manipulating can undefine it. //
    – user202729
    Commented Oct 25, 2022 at 16:39
34

You need to let it to undefined, not relax, try this

\providecommand*\@nameundef[1]{%
  \expandafter\let\csname #1\endcsname\@undefined}

See comments by Ulrich below for some caveats.

2
  • 12
    ... conditional on the fact that no control sequence named \@undefined is defined. (But I think that's assumed at some places in the kernel as well, so \def\@undefined{} would likely break a lot of stuff anyway, so the user will notice.) Commented Jun 14, 2011 at 7:09
  • 12
    @UlrichSchwarz The command \@undefined is used more than 800 times in my texmf tree, so it is a good assumption.
    – yo'
    Commented Mar 6, 2012 at 10:23
26

The assignment \let\xyz\relax makes \xyz "undefined" as far as the \@ifundefined test is concerned. So

\makeatletter
\let\xyz\relax
\@ifundefined{xyz}{LaTeX undefined}{LaTeX defined}\par
\ifdefined\xyz e-TeX defined\else e-TeX undefined\fi\par
\ifcsname xyz\endcsname e-TeX defined\else e-TeX undefined\fi\par

would print

LaTeX undefined
e-TeX defined
e-TeX defined

The only safe way to "undefine" a command is to define it inside a group: at the end of it the definition will vanish. There is \undef in etoolbox that relies on the fact that a specific control sequence (\etb@undefined) will never be defined by anybody.

Choosing between the \@ifundefined and \ifdefined tests is a matter of convenience and mostly depends on what you need. Notice that the argument to \@ifundefined is the macro's name, without the backslash.

3
  • @tohecz It undefines the command, unless \@undefined has received a meaning. It's the same as etoolbox's \undef.
    – egreg
    Commented Nov 24, 2013 at 0:03
  • Is there a latex3 equivalent? If I have for example \l_prefix_foo_skip as in your answer here.
    – user49901
    Commented Dec 10, 2017 at 17:21
  • @Grimler Why would you want to undefine a register name?
    – egreg
    Commented Dec 10, 2017 at 19:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .