40

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}
24

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.

  • Adding \begingroup and \endgroup worked great. Thanks. – Peter Grill Jun 14 '11 at 0:22
  • 10
    etoolbox also has \undef. – Philipp Jun 14 '11 at 5:27
  • @Philipp: so it does! I never went to that section of the manual. – Ryan Reich Jun 14 '11 at 13:53
  • 1
    @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 Apr 24 '15 at 12:08
32

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.

  • 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.) – Ulrich Schwarz Jun 14 '11 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' Mar 6 '12 at 10:23
22

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.

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

\let\ProcessCaseA\relax% no output if comment this, and use above line

You should be using \global\let here rather than \let.

  • 1
    This does not seem to a make a difference. I still get the same results. I had tried \gdef before but that does not produce any output (same problem as documented in the comments of the MWE). – Peter Grill Jun 14 '11 at 0:18
  • 6
    There's no reason to use \global here. Conditionals do not create a group. – TH. Jun 14 '11 at 1:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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