# Safe test for an empty expanded macro argument?

How can I test in a safe way (i.e. without reserving tokens as explained here) if an expanded macro argument is empty?

• I do not understand what do you mean by “expanded” (i.e., why is it relevant here). In your link the answer says “The safest way is \if\relax\detokenize{#1}\relax”. What “safe way” are you looking for? – Manuel Nov 18 '14 at 12:38
• @Manuel Basically, I am looking for a test if a macro argument expands to nothing. (\if\relax\detokenize{#1}\relax fails when passed \empty, defined as \def\empty{}.) A safe test is one that is generic enough not to rely on a token not being in the argument. – SJU Nov 18 '14 at 12:52
• @AngelTsankov The \if\relax\detokenize{#1}\relax isn't relying on anything: if the argument is \empty then it's not empty. So while 'how do I test if the full expansion of an argument' is a perfectly valid question, it's not due to anything 'unsafe' in the test for an empty argument. – Joseph Wright Nov 18 '14 at 14:18

You can use a \romannumeral trick:

\if\relax\detokenize\expandafter{\romannumeral-\Q#1}\relax


The missing space after \Q will trigger expansion of #1 (after macro substitution, of course). Since this expansion ends at the first unexpandable token, this should be what you want.

However a leading space will be ignored.

\def\notempty{\relax}
\def\perhapsempty{\empty}

\if\relax\detokenize\expandafter{\romannumeral-\Q\empty}\relax
\message{EMPTY}
\else
\message{NOT EMPTY}
\fi

\if\relax\detokenize\expandafter{\romannumeral-\Q\notempty}\relax
\message{EMPTY}
\else
\message{NOT EMPTY}
\fi

\if\relax\detokenize\expandafter{\romannumeral-\Q\perhapsempty}\relax
\message{EMPTY}
\else
\message{NOT EMPTY}
\fi

\if\relax\detokenize\expandafter{\romannumeral-\Q\space}\relax
\message{EMPTY}
\else
\message{NOT EMPTY}
\fi

This is pdfTeX, Version 3.14159265-2.6-1.40.15 (TeX Live 2014) (preloaded format=pdftex)
restricted \write18 enabled.
entering extended mode
(./tsanempty.tex EMPTY NOT EMPTY EMPTY EMPTY)


If you don't need expandability and trust that the tokens you pass are fully expandable, you can use \edef:

\begingroup\edef\x{#1}\expandafter\endgroup\expandafter
\if\expandafter\relax\detokenize\expandafter{\x}\relax


For instance,

\begingroup\edef\x{\empty}\expandafter\endgroup\expandafter
\if\expandafter\relax\detokenize\expandafter{\x}\relax
\message{EMPTY}
\else
\message{NOT EMPTY}
\fi

\begingroup\edef\x{\notempty}\expandafter\endgroup\expandafter
\if\expandafter\relax\detokenize\expandafter{\x}\relax
\message{EMPTY}
\else
\message{NOT EMPTY}
\fi

\begingroup\edef\x{\perhapsempty}\expandafter\endgroup\expandafter
\if\expandafter\relax\detokenize\expandafter{\x}\relax
\message{EMPTY}
\else
\message{NOT EMPTY}
\fi

\begingroup\edef\x{\space}\expandafter\endgroup\expandafter
\if\expandafter\relax\detokenize\expandafter{\x}\relax
\message{EMPTY}
\else
\message{NOT EMPTY}
\fi


will return

EMPTY NOT EMPTY EMPTY NOT EMPTY


Actually, an \expandafter is redundant, but clarity is better.

\documentclass{article}
\usepackage[T1]{fontenc}

\def\foo#1{\par \texttt{<\detokenize{#1}>}
\expandafter\if\relax\detokenize\expandafter{\romannumeral0#1}\relax
\if X#1X%
empty\else
not empty\fi
\else
not empty\fi}

\begin{document}
\foo{}

\foo{ }

\foo{\empty}

\foo{{}}

\foo{\sqrt}

\foo{\csname @gobble\endcsname{hello}}

\end{document}

• Why do you need the first \expandafter? – SJU Nov 18 '14 at 14:09
• @AngelTsankov You don't (I originally had a different version, will remove, thanks) – David Carlisle Nov 18 '14 at 14:10
• How about just \if\relax\detokenize\expandafter{#1}\relax empty\else not empty\fi? – SJU Nov 18 '14 at 14:13
• This answer is wrong, as it will consider 0 to be empty. See egreg's answer for a correct use of \romannumeral in this context (sorry David). – Bruno Le Floch Nov 18 '14 at 18:10
• @BrunoLeFloch the X#1X saves me, as Angel says:-) – David Carlisle Nov 18 '14 at 18:40

Have you tried the ifmtarg package? It provides the macro

\@ifmtarg{<arg>}{<Code for arg empty>}
{<Code for arg not empty>}


Use texdoc ifmtarg for the documentation.