# String test, with complicated arguments

I have a command \mycom{} which takes 1 argument. The command should perform a test on the argument and do something accordingly. For simple arguments, I can use \ifthenelse, but I need to consider more general arguments, e.g. containing commands or environments. The following MWE follows a solution for a more robust string test, which was given in this post:

\documentclass{article}
\makeatletter
\newcommand{\strtest}[2]{%
\ifnum\pdfstrcmp{#1}{#2}=\z@
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi}
\makeatother

\newcommand{\mycom}[1]{%
\strtest{#1}{}%
{content :  empty}%
{content : #1}%
}

\begin{document}
\mycom{}

\mycom{coucou}
\end{document}


This works. But if i try to call \mycom{\textbf{coucou}}, then the compilation fails.

-
Ah, now I see! The quoted answer tells you that this test works only for simple strings, and suggests a way to cope with more complicated input. – egreg Feb 6 '12 at 15:49

The \pdfstrcmp primitive fully expands its argument. Thus things go wrong with macros that cannot be expanded, which includes \textbf. You can prevent this using the \unexpanded primitive:

\newcommand{\strtest}[2]{%
\ifnum\pdfstrcmp{\unexpanded{#1}}{\unexpanded{#2}}=\z@
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}

-
BTW, if you want this to work cross-engine, you should load the pdftexcmds package and use \pdf@strcmp, which deals with the fact that XeTeX calls the primitive \strcmp and LuaTeX requires it is implemented in Lua. – Joseph Wright Feb 6 '12 at 16:06
Would you prefer \unexpanded or \detokenize in this case? – egreg Feb 6 '12 at 16:09
@egreg We've used \unexpanded in LaTeX3, as the idea is to prevent expansion rather than turn into a string per se (which happens anyway). That I know of, there is no technical reason to prefer one approach over another. – Joseph Wright Feb 6 '12 at 16:16
So I guess this can be closed as a duplicate, as your answer is already included in mine. – egreg Feb 6 '12 at 16:19
@egreg, Joseph, there is one technical reason to prefer \unexpanded: it is slightly more efficient since we move around less tokens: \pdfstrcmp converts the tl to a string internally, rather than having to first produce character tokens. For instance, \edef\x{\exp_not:c{\prg_replicate:nn{100000}x}} \edef\x{\prg_replicate:nn{1000}\x} \str_if_eq:xxTF{\tl_to_str:N\x}{}{}{} blows up when trying to build a string with 100002000 tokens, whereas using \exp_not:o works fine. – Bruno Le Floch Feb 6 '12 at 18:39

I want to show an alternative. Based on the LaTeX3 engine one approach is:

\documentclass{article}
\usepackage{xparse,expl3,}
\ExplSyntaxOn

\NewDocumentCommand{ \mycom } { m } {
\tl_if_empty:nTF { #1 }
{content:~empty}
{content:~#1}
}
\ExplSyntaxOff
\begin{document}
\mycom{}

\mycom{coucou}

\mycom{\textbf{coucou}}
\end{document}


Base on the comments question you can compare strings with:

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\mystringcase}{  m }
{
\prg_case_str:nnn { #1 }
{
{ a }  { Your~string~\textbf{a} }
{ b }  { Your~string~\textbf{b} }
{ c }  { Your~string~\textbf{c} }
}
{ Not~in~list }
}
\ExplSyntaxOff
\begin{document}
\mystringcase{a}

\mystringcase{b}

\mystringcase{d}
\end{document}

-
Why not use \tl_if_empty:nTF? – Joseph Wright Feb 6 '12 at 16:35
@JosephWright: Because of the Argument #1 I don't know the contents and I want to avoid unwanted expansion. – Marco Daniel Feb 6 '12 at 16:46
\tl_fi_empty:nTF does no expansion, and is therefore safe with any input. – Joseph Wright Feb 6 '12 at 17:05
@JosephWright: Thanks. I changed it. – Marco Daniel Feb 6 '12 at 17:26