# Why doesn't this \ifx test if the macro is empty?

Consider the following MWE:

\documentclass{standalone}
\newcommand{\myname}{ss}
\begin{document}
\mycmd
\end{document}


I don't know why the above command returns the Professor \myname whether \newcommand{\myname}{} is or is not empty?!


For the simplest case, of a command being defined/undefined, and (in case it's defined) being empty/not empty you could write two nested conditionals; one \ifx\myname\@undefined, an another \ifx\myname\@empty1:

\makeatletter
\newcommand{\mycmd}{%
\ifx\myname\@undefined
\else
\ifx\myname\@empty
\else
Professor \myname
\fi
\fi}
\makeatother
\newcommand*{\myname}{ss}%



Here's a slightly better user interface (the user doesn't have to know about \newcommand) that already tells the code if the name was given (regardless of what the name actually is).

The command \setname (quite similar to LaTeX's \author) defines the token list \myname to contain the name, and sets the conditional \if@name@set to \iftrue. If \setname is not used, then \if@name@set is \iffalse and \myname contains a default value.

\documentclass{article}

\makeatletter
\newcommand{\setname}[1]{%
\let\if@name@set\iftrue
\gdef\myname{#1}}
\let\if@name@set\iffalse
\newcommand{\mycmd}{%
\if@name@set
Professor \myname
\else
\textbf{??\myname??}%
\fi}
\makeatother

\begin{document}
\mycmd

\setname{X}% set the name
\mycmd % print again
\end{document}


Phelype's answer explains much of the issue.

There is another approach, though:

\documentclass{standalone}

\newcommand{\mycmd}{%
\ifdefined\myname
Professor \myname
\else
\fi
}

\newcommand{\myname}{ss}

\begin{document}

\mycmd

\end{document}


It's usually better to use “private” commands for this kind of programming, so as to cover possible actions by the user, who might define \myname for their own purposes.

The main code should go in a .sty or .cls file, of course.

\documentclass{standalone}

\makeatletter % <- this should not appear in a .sty or .cls file
%% code for .sty or .cls
\else
\fi
}

%% end of code for .sty or .cls
\makeatother % <- this should not appear in a .sty or .cls file

\begin{document}

%% in the document “metadata part”

\end{document}


I can offer a \romannumeral0-expansion-based routine \UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined for checking whether a macro argument consists of a single token which is undefined or is defined blank. ("Defined blank" means that expanding the token either yields no token at all or yields only space tokens.)

The routine doesn't require ε-TeX-extensions or the like and can be applied in expansion-contexts also, e.g., within \csname..\endcsname. The result will be delivered after two expansion-steps/after two "hits" by \expandafter.

The routine doesn't use any \if..\else..\fi.
The routine will be confused neither by (unbalanced) \if../\else/\fi nor by unbalanced \csname/\endcsname in its arguments.

The routine will not expand arguments, it will only "look" at the set of tokens formed by the first argument for "deciding" whether the tokens that form the second or the tokens that form the third argument are to be delivered.

Possible pitfall: In case of the argument being a single macro-token which does not process arguments checking whether that macro-token is defined blank is done by "looking" at the \meaning of the macro-token via \UD@CheckWhetherBlank after stripping the prefix (the macro:->-thingie) via the LaTeX 2ε-kernel-macro \strip@prefix. "Looking" at the meaning of the macro-token instead of "looking" at the toplevel-expansion of the macro-token is done for ensuring that the test won't fail in case the macro-token expands to things that are \outer. (You can do something like this:

\def\unfold{\umbrella}


, and \unfold will expand to \umbrella which is a thing that is \outer. In this case directly passing the result of toplevel-expanding \unfold as argument to a macro for checking blankness of that expansion is not possible as this implies having an \outer-token as component of an argument of a macro.)
But looking at the meaning is not totally safe in this context: In case the integer-parameter \escapechar has the value 32—32 is the number of the code-point of the space character both in ASCII and in Unicode, the possible internal character encoding schemes with nowadays' TeX-engines—or has a value outside the range of the TeX-engine's internal character-encoding-scheme's possible code-point-numbers, checking "blankness of the meaning" does not crank out cases where the token is defined to also deliver control-sequences whose names consist of spaces only, e.g., the control space \ , or things constructed via \csname..\endcsname, like:

\def\insertfivechars#1#2{#1#2#2#2#2#2}
\insertfivechars{\expandafter\def\csname}{ }\endcsname{The name of this control sequence consists of five spaces.}
\insertfivechars{\expandafter\show\csname}{ }\endcsname
% But:
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\scratch
\expandafter\expandafter\expandafter{%
\insertfivechars{\csname}{ }\endcsname
}
\escapechar=-1
\message{X\meaning\scratch X}
\bye


For the sake of having fun checking whether the token is undefined is done by checking whether the result of applying \meaning delivers a token-sequence which begins with the tokens u12n12d12e12f12i12n12e12d12.

Probably checking whether the meaning starts with u12 or u12n12 is sufficient.
[If somebody could verify this and add a comment, I'd be glad and thankful. ;-)]
I don't know what I was thinking when asking this.
E.g., there is the \uppercase-primitive which implies that checking for u12 is not sufficient when \escapechar has a neative value.
Phelype Oleinik pointed out that the value of \escapechar needs to be taken into account and that there is the \underline-primitive and that therefore at least checking for u12n12d12e12f12 is needed.

The empty-test \UD@CheckWhetherNull is explained in detail in my answer to the question "Expandable test for an empty token list—methods, performance, and robustness". In that answer its name is not \UD@CheckWhetherNull but is \CheckWhetherEmpty.

\documentclass[a4paper]{article}

\csname @ifundefined\endcsname{pagewidth}{}{\pagewidth=\paperwidth}%
\csname @ifundefined\endcsname{pdfpagewidth}{}{\pdfpagewidth=\paperwidth}%
\csname @ifundefined\endcsname{pageheight}{}{\pageheight=\paperheight}%
\csname @ifundefined\endcsname{pdfpageheight}{}{\pdfpageheight=\paperheight}%
\textwidth=\paperwidth
\oddsidemargin=1.25cm
\marginparsep=.125\oddsidemargin
\marginparwidth=\oddsidemargin
\evensidemargin=\oddsidemargin
\textheight=\paperheight
\topmargin=1.25cm
\footskip=.5\topmargin
\pagestyle{empty}
\parindent=0ex
\parskip=0ex
\topsep=0ex
\partopsep=0ex

\makeatletter
%=====[code for \UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined]=======
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
\newcommand\UD@CheckWhetherNull[1]{%
\romannumeral0\expandafter\@secondoftwo\string{\expandafter
\@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
\@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
\@secondoftwo\string}\@firstoftwo\expandafter{} \@secondoftwo}%
{\@firstoftwo\expandafter{} \@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument is blank (empty or only spaces):
%%.............................................................................
%% -- Take advantage of the fact that TeX discards space tokens when
%%    "fetching" _un_delimited arguments: --
%% \UD@CheckWhetherBlank{<Argument which is to be checked>}%
%%                      {<Tokens to be delivered in case that
%%                        argument which is to be checked is blank>}%
%%                      {<Tokens to be delivered in case that argument
%%                        which is to be checked is not blank>}%
\newcommand\UD@CheckWhetherBlank[1]{%
\romannumeral\expandafter\expandafter\expandafter\@secondoftwo
\expandafter\UD@CheckWhetherNull\expandafter{\@firstoftwo#1{}.}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument's first token is a catcode-1-character
%%.............................................................................
%% \UD@CheckWhetherBrace{<Argument which is to be checked>}%
%%                      {<Tokens to be delivered in case that argument
%%                        which is to be checked has leading
%%                        catcode-1-token>}%
%%                      {<Tokens to be delivered in case that argument
%%                        which is to be checked has no leading
%%                        catcode-1-token>}%
\newcommand\UD@CheckWhetherBrace[1]{%
\romannumeral0\expandafter\@secondoftwo\expandafter{\expandafter{%
\string#1.}\expandafter\@firstoftwo\expandafter{\expandafter
\@secondoftwo\string}\expandafter\expandafter\@firstoftwo{ }{}%
\@firstoftwo}{\expandafter\expandafter\@firstoftwo{ }{}\@secondoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Exchange two arguments. (From each argument an outermost level of
%% surrounding braces will be removed if present.)
%%-----------------------------------------------------------------------------
\newcommand\UD@Exchange[2]{#2#1}%
%%-----------------------------------------------------------------------------
%% Check whether argument's leading tokens form a specific
%% token-sequence that does not contain explicit character tokens of
%% category code 1 or 2:
%%.............................................................................
%% \UD@CheckWhetherLeadingTokens{<argument which is to be checked>}%
%%                              {<a <token sequence> without explicit
%%                                character tokens of category code
%%                                1 or 2>}%
%%                              {a <single non-space token> that does
%%                                _not_ occur in <token sequence> >}%
%%                              {<internal token-check-macro>}%
%%                              {<tokens to be delivered in case
%%                                <argument which is to be checked> has
%%                                <token sequence> as leading tokens>}%
%%                              {<tokens to be delivered in case
%%                                <argument which is to be checked>
%%                                does not have <token sequence> as
\romannumeral0\UD@CheckWhetherNull{#1}%
{\UD@Exchange{ }\expandafter\@secondoftwo}%
{\expandafter\@secondoftwo\string{\expandafter
}%
\expandafter\UD@CheckWhetherNull\expandafter{\@firstoftwo{}#1}%
{\UD@Exchange{\@firstoftwo}}{\UD@Exchange{\@secondoftwo}}%
{\UD@Exchange{ }{\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter}\expandafter\expandafter
\expandafter}\expandafter\@secondoftwo\expandafter{\string}%
}%
%%-----------------------------------------------------------------------------
%% \UD@internaltokencheckdefiner{<internal token-check-macro>}%
%%                              {<token sequence>}%
%% Defines <internal token-check-macro> to snap everything
%% until reaching <token sequence>-sequence and spit that out
%% nested in braces.
%%-----------------------------------------------------------------------------
\newcommand\UD@internaltokencheckdefiner[2]{%
\@ifdefinable#1{\long\def#1##1#2{{##1}}}%
}%
\begingroup
%%-----------------------------------------------------------------------------
%% Check whether argument is a macro that takes arguments
%%.............................................................................
%% Temporary/interim-definition/Usage as scratch-macro:
\newcommand\UD@CheckWhetherArgumentlessMacroMeaning[5]{%
% #1 = phrase "undefined" in catcode-12-character-tokens
% #2 = phrase "macro:->" in catcode-12-character-tokens
% #3 = phrase "\long macro:->" in catcode-12-character-tokens
% #4 = phrase "\protected\long macro:->" in catcode-12-character-tokens
% #5 = phrase "\protected macro:->" in catcode-12-character-tokens
\endgroup
\UD@internaltokencheckdefiner{\UD@ExtractUndefined}{#1}%
\UD@internaltokencheckdefiner{\UD@ExtractMacro}{#2}%
\UD@internaltokencheckdefiner{\UD@ExtractLongMacro}{#3}%
\UD@internaltokencheckdefiner{\UD@ExtractProtectedLongMacro}{#4}%
\UD@internaltokencheckdefiner{\UD@ExtractProtectedMacro}{#5}%
\UD@internaltokencheckdefiner{\UD@ExtractSpace}{ }%
%%-----------------------------------------------------------------------------
%% Check whether argument is a macro that takes arguments
%%.............................................................................
%% \expandafter\UD@CheckWhetherArgumentlessMacroMeaning
%% \expandafter{\meaning <token>}{%
%%   <Tokens to be delivered in case <token> is a macro that does not take
%%    arguments>
%% }{%
%%   <Tokens to be delivered in case <token> is not a macro that does not
%%    take arguments>
%% }%
\newcommand\UD@CheckWhetherArgumentlessMacroMeaning[1]{%
\@secondoftwo
}%
}%
}%
}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument is a token that is undefined and can be defined.
%%.............................................................................
%% \expandafter\UD@CheckWhetherUndefinedMeaning
%% \expandafter{\meaning <token>}{%
%%   <Tokens to be delivered in case <token> is undefined and can be defined.>
%% }{%
%%   <Tokens to be delivered in case <token> is not undefined/cannot be
%%    defined.>
%% }%
\newcommand\UD@CheckWhetherUndefinedMeaning[1]{%
}%
}%
\def\@tempa{\protected macro:->}\@onelevel@sanitize\@tempa
\expandafter\UD@Exchange\expandafter{\expandafter{\@tempa}}{%
\edef\@tempa{\string\protected\long macro:->}\@onelevel@sanitize\@tempa
\expandafter\UD@Exchange\expandafter{\expandafter{\@tempa}}{%
\def\@tempa{\long macro:->}\@onelevel@sanitize\@tempa
\expandafter\UD@Exchange\expandafter{\expandafter{\@tempa}}{%
\def\@tempa{macro:->}\@onelevel@sanitize\@tempa
\expandafter\UD@Exchange\expandafter{\expandafter{\@tempa}}{%
\def\@tempa{undefined}\@onelevel@sanitize\@tempa
\expandafter\UD@Exchange\expandafter{\expandafter{\@tempa}}{%
\UD@CheckWhetherArgumentlessMacroMeaning
}%
}%
}%
}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument is undefined or defined blank (=yields no tokens or
%% only space-tokens)/a single token:
%%.............................................................................
%% \UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{%
%%   <Argument which is to be checked>%
%% }{%
%%   <Tokens to be delivered in case <argument which is to be checked> is a
%%    single token that is undefined or defined blank>%
%% }{%
%%   <Tokens to be delivered in case <argument which is to be checked> is not a
%%    single token that is undefined or defined blank>%
%% }%
\newcommand\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined[1]{%
\romannumeral0%
\UD@CheckWhetherBlank{#1}{%
% Argument is blank:
\@firstoftwo\expandafter{} \@secondoftwo
}{%
\UD@CheckWhetherBrace{#1}{%
% The leading opening brace implies that further examination
% is not needed:
\@firstoftwo\expandafter{} \@secondoftwo
}{%
% Argument's first token is not an opening brace and
% therefore its first token can safely be "hit" by \meaning:
{%
% Argument has a leading space. Thus argument's first token
% cannot be removed by "gobbling" a non-delimited argument.
% The leading space implies that further examination
% is not needed:
\@firstoftwo\expandafter{} \@secondoftwo
}{%
% Argument's first token is a non-space-token that can safely be
% gobbled and argument's first token can safely be "hit" by
% \meaning:
\expandafter\UD@CheckWhetherNull\expandafter{\@firstoftwo{}#1}{%
% Argument consists of a single token which can safely be "hit"
% by \meaning:
\expandafter\UD@CheckWhetherUndefinedMeaning\expandafter{\meaning#1}%
{%
%The meaning denotes that the single token is undefined:
\@firstoftwo\expandafter{} \@firstoftwo
}%
{%
%The meaning denotes that the single token is not undefined:
\expandafter\UD@CheckWhetherArgumentlessMacroMeaning\expandafter{\meaning#1}%
{%
%The meaning denotes that the single token is an argumentless macro:
\expandafter\expandafter
\expandafter            \UD@CheckWhetherBlank
\expandafter\expandafter
\expandafter            {%
\expandafter\strip@prefix
\meaning#1}{%
%The meaning denotes that the single token is defined blank:
%In the edge case of \escapechar having a negative value or
%having the value 32 (32 is the code-point of the space character
%both in ASCII and in Unicode, the possible internal coding-schemes
%of TeX-engines), the definition of the token might also
%contain control sequences whose name consists of spaces
%only, e.g., control spaces \ .
\@firstoftwo\expandafter{} \@firstoftwo
}{%
%The meaning denotes that the single token is defined, but not blank:
\@firstoftwo\expandafter{} \@secondoftwo
}%
}%
{%
%The meaning denotes that the single token is not an argumentless macro:
\@firstoftwo\expandafter{} \@secondoftwo
}%
}%
}{%
% Argument consists of several tokens and the argument's
% first token neither is a space nor is a brace:
% The circumstance of there being severak tokens implies that
% further examination is not needed:
\@firstoftwo\expandafter{} \@secondoftwo
}%
}%
}%
}%
}%
%%===[eof code for \UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined]====
\makeatother

\begin{document}
\makeatletter

\begin{verbatim}
\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{\UndEFiNeD}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%
\end{verbatim}

yields:

\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{\UndEFiNeD}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%

\noindent\null\hrulefill

\begin{verbatim}
\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{\UndEFiNeD\UndEFiNeD}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%
\end{verbatim}

yields:

\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{\UndEFiNeD\UndEFiNeD}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%

\noindent\null\hrulefill

\begin{verbatim}
\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%
\end{verbatim}

yields:

\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%

\noindent\null\hrulefill

\begin{verbatim}
\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{  }{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%
\end{verbatim}

yields:

\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{  }{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%

\noindent\null\hrulefill

\begin{verbatim}
\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{\LaTeX}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%
\end{verbatim}

yields:

\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{\LaTeX}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%

\noindent\null\hrulefill

\begin{verbatim}
\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{\@firstoftwo}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%
\end{verbatim}

yields:

\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{\@firstoftwo}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%

\noindent\null\hrulefill

\begin{verbatim}
\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{\empty}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%
\end{verbatim}

yields:

\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{\empty}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%

\noindent\null\hrulefill

\protected\long\def\myblank{ }%
\begin{verbatim}
\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{\myblank}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%
\end{verbatim}

yields:

\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{\myblank}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%

\noindent\null\hrulefill

\begin{verbatim}
\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{\myblank\myblank}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%
\end{verbatim}

yields:

\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{\myblank\myblank}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%

\noindent\null\hrulefill

\begin{verbatim}
\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{{\myblank}}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%
\end{verbatim}

yields:

\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{{\myblank}}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%

\noindent\null\hrulefill

\begin{verbatim}
\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{\else}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%
\end{verbatim}

yields:

\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{\else}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%

\noindent\null\hrulefill

\begin{verbatim}
\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{#}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%
\end{verbatim}

yields:

\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{#}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%

\noindent\null\hrulefill

\begin{verbatim}
\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{X}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%
\end{verbatim}

yields:

\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{X}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%

\noindent\null\hrulefill

\begin{verbatim}
\catcode\X=13
\protected\defX{}%
\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{X}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%
\end{verbatim}

yields:

\catcode\X=13
\protected\defX{}%
\UD@CheckWhetherArgIsSingleTokenDefinedBlankOrUndefined{X}{%
Arg is a single token which is definable and either currently undefined or defined blank.
}{%
Arg is a not a single token which is definable and either currently undefined or defined blank.
}%

\end{document}


• Re your comment about undefined: For maximum safety, neither u nor un would be enough. If you set \escapechar-1 then the primitive \underline would require you to use at least undef to differentiate :-) (I don't think more than that is necessary though). – Phelype Oleinik Feb 6 at 3:28
• @PhelypeOleinik Thank you. ;-) – Ulrich Diez Feb 6 at 10:05

Use the ifmtarg package (plus some code simplification):

% undefprob.tex  SE 527084

\documentclass{standalone}
\usepackage{ifmtarg}
\makeatletter

The above code checks whether the argument to \myname is empty (blank) or not. If empty then asks for a name, otherwise prints Professor and the argument to\myname.