# What is the difference between \somecmd and \csname somecmd\endcsname?

This is a demo

\documentclass{article}
\usepackage{soul}
\makeatletter
\newcommand{\mydef}[2]{%
\expandafter\def\csname my#1\endcsname {#2}
}
\newcommand{\mygetdef}[1]{%
\ifcsname my#1\endcsname \csname my#1\endcsname \else #1 not defined \fi%
}
\makeatother

\def\test{some text to complete}
\mydef{xxx}{some text to complete}

\begin{document}
\ul\test                 % it works
%%%% if uncomment, the below one does not work, an error is reported
% \ul\mygetdef{xxx}
\end{document}


As the comment says, if \ul\mygetdef{xxx} takes place, there comes a error:

! Argument of \SOUL@@ has an extra }.

UPDATE:

I switch to package ulem where \uline can underline \fbox. Everything works (see MWE below). Then I try to make colorful box. However, I find that once I include package xcolor or tcolorbox (as the comment in MWE), some weird error comes up immediately even before I actually use them in the document.

\documentclass{article}
%%% uncomment either of the packages below, it reports errors.
%\usepackage{xcolor}
%\usepackage{tcolorbox}

\usepackage[normalem]{ulem}
\makeatletter
\newcommand{\mydef}[2]{%
\expandafter\def\csname my#1\endcsname {#2}
}
\newcommand{\mygetdef}[1]{%
\ifcsname my#1\endcsname \csname my#1\endcsname \else \protect\fbox{#1} \fi%
}

\def\test{some text to complete}
\mydef{xxx}{some text to complete}

\begin{document}
\uline{\test}

\edef\mytmp{\mygetdef{xxx}}
\uline{\mytmp}

\edef\mytmp{\mygetdef{yyy}}
\uline{\mytmp}

\end{document}


After all my efforts, I can not figure out why and solve it. So I updated my original problem.

Try

\edef\tmp{\mygetdef{xxx}}
\ul\tmp


The \mygetdef needs to be expanded before being passed to \ul.

\documentclass{article}
\usepackage{soul}
\makeatletter
\newcommand{\mydef}[2]{%
\expandafter\def\csname my#1\endcsname {#2}
}
\newcommand{\mygetdef}[1]{%
\ifcsname my#1\endcsname \csname my#1\endcsname \else #1 not defined \fi%
}
\makeatother

\def\test{some text to complete}
\mydef{xxx}{some text to complete}

\begin{document}
\ul\test                 % it works
%%%% if uncomment, the below one does not work, an error is reported
% \ul\mygetdef{xxx}

\edef\tmp{\mygetdef{xxx}}
\ul\tmp
\end{document}


SUPPLEMENTAL NOTE TO OP

\documentclass{article}
\usepackage{soul}
\makeatletter
\newcommand{\mydef}[2]{%
\expandafter\def\csname my#1\endcsname {#2}
}
\newcommand{\mygetdef}[1]{%
\ifcsname my#1\endcsname \csname my#1\endcsname \else
#1 not defined \fi%
}
\newcommand{\myulgetdef}[1]{%
\ifcsname my#1\endcsname \expandafter\ul{\csname my#1\endcsname}%
\else\fbox{#1 not defined} \fi%
}
\newcommand{\myxgetdef}[1]{%
\ifcsname my#1\endcsname \expandafter\csname my#1\endcsname%
\else\protect\protect\protect\fbox{#1 not defined} \fi%
}
\newcommand\exul[1]{\edef\tmp{#1}\ul\tmp}
\makeatother

\def\test{some text to complete}
\mydef{xxx}{some text to complete}

\begin{document}
\ul\test                 % it works

\exul{\mygetdef{xxx}}

1. \mygetdef{yyy}

2. \myulgetdef{yyy}

3. \myxgetdef{yyy}

4. \exul{\mygetdef{yyy}}

5. \exul{\myxgetdef{yyy}}% HOWEVER, \fbox IS NOT UNDERLINED

%6. \exul{\myulgetdef{yyy}}% FAILS; CANNOT \ul{\fbox{...}}

\end{document}


• Is there any way putting \edef part in \mygetdef to make it work? – jiewuza Mar 23 at 3:01
• @jiewuza It would be easier to define \newcommand\exul[1]{\edef\tmp{#1}\ul\tmp} and then invoke it as \exul{\mygetdef{xxx}}. – Steven B. Segletes Mar 23 at 3:07
• Well, then I have to define more \newcommand for others besides \ul. But it works anyway. Thanks. – jiewuza Mar 23 at 4:00
• I just got another problem. I added \fbox in \mygetdef, that is, \ifcsname my#1\endcsname \csname my#1\endcsname \else \fbox{#1 not defined} \fi. And when I try \mygetdef{yyy} (which is not defined), it brokes with some Undefined control sequence error. – jiewuza Mar 23 at 4:26
• @jiewuza The command \newcommand{\mygetdef}[1]{% \ifcsname my#1\endcsname \csname my#1\endcsname \else \fbox{ #1 not defined} \fi% } works just fine if invoked directly as \mygetdef{yyy}. However, \exul{\mygetdef{yyy}} does not work in that case because you can't \ul an \fbox. – Steven B. Segletes Mar 23 at 4:58

The command \ul is defined as \SOUL@ulsetup\SOUL@. The first command sets up some commands that will be later delivered after a group has started and is of no concern here.

The macro \SOUL@ is defined as

% soul.sty, line 99:
\def\SOUL@{%
\futurelet\SOUL@@\SOUL@expand
}


which means that the following token is looked up and stored in \SOUL@@; then \SOUL@expand is executed

% soul.sty, line 102:
\def\SOUL@expand{%
\ifcat\bgroup\noexpand\SOUL@@
\let\SOUL@n\SOUL@start
\else
\bgroup
\def\\##1##2{\def##2{\noexpand##2}}%
\the\SOUL@cmds
\SOUL@buffer={%
\\\TeX\\\LaTeX\\\soulomit\\\mbox\\\hbox\\\textregistered
\\\\%
}%
\def\\##1{\def##1{\noexpand##1}}%
\the\SOUL@buffer
\let\protect\noexpand
\xdef\SOUL@n##1{\noexpand\SOUL@start{\SOUL@@}}%
\egroup
\fi
\SOUL@n
}


Quite a mouthful! The behavior depends on whether the token stored in \SOUL@@ is a left brace or not. In your case it isn't.

The part of the code above which is of primary interest is

            \let\protect\noexpand
\xdef\SOUL@n##1{\noexpand\SOUL@start{\SOUL@@}}%


Note that \SOUL@@ is the token found at the first step, in your case \mygetdef. At the end, \SOUL@n is executed, which discards the next token (your \mygetdef) and does

\SOUL@start{<full expansion of \mygetdef>}


The place where the error happens is at the \xdef, because \mygetdef does not find its argument, but just the closing brace. What you want is that

\ul\mygetdef{xxx}


becomes

\ul\myxxx


You need to do some clever expansion for this, but it becomes very awkward, mainly because of the conditionals. If you do

\expandafter\ul\myxxx


you get

\ul\ifcsname myxxx\endcsname\csname myxxx\endcsname\else xxx not defined \fi


With three \expandafters

\ul\csname myxxx\endcsname\else xxx not defined \fi


With seven \expandafters

\ul\myxxx\else xxx not defined \fi


That's it! Let's see what happens with \mygetdef{noway} (assuming it's undefined). You'd get

\ul noway not defined \fi


which is not really what you want, but can be easily fixed.

\documentclass{article}
\usepackage{soul}

\newcommand{\mydef}[2]{%
\expandafter\def\csname my#1\endcsname{#2}
}
\newcommand{\mygetdef}[1]{%
\ifcsname my#1\endcsname
\csname my#1\endcsname
\else
{}#1 not defined%
\fi
}

\def\test{some text to complete}
\mydef{xxx}{some text to complete}

\begin{document}

\ul\test

\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter
\expandafter\ul\mygetdef{xxx}

\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter
\expandafter\ul\mygetdef{noway}

\end{document}


My proposal is to define differently \mygetdef, if you plan to use it after soul macros, but not only.

\documentclass{article}
\usepackage{soul}

\makeatletter
\newcommand{\mydef}[2]{%
\@namedef{my#1}{#2}
}
\newcommand{\mygetdef}[2][\relax]{%
\@ifundefined{my#2}%
{{}#2 not defined}%
{\expandafter#1\csname my#2\endcsname}%
}
\makeatother

\mydef{xxx}{some text to complete}

\begin{document}

\mygetdef{xxx}

\mygetdef[\ul]{xxx}

\mygetdef[\textit]{xxx}

\mygetdef[\ul]{noway}

\end{document}


• Although it is now beyond my understanding, your explanation is really helpful. I am learning the expanding rules. And your redefination of \mygetdef` is quite interesting. I will dig more. – jiewuza Mar 23 at 14:27