How can I test in a safe way (i.e. without reserving tokens as explained here) if an expanded macro argument is empty?
3 Answers
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}
-
-
@AngelTsankov You don't (I originally had a different version, will remove, thanks) Commented Nov 18, 2014 at 14:10
-
How about just
\if\relax\detokenize\expandafter{#1}\relax empty\else not empty\fi
?– SJUCommented Nov 18, 2014 at 14:13 -
1This 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). Commented Nov 18, 2014 at 18:10 -
1
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.
\if\relax\detokenize{#1}\relax
”. What “safe way” are you looking for?\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.\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.