5

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.

1
  • 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
    Commented Feb 6, 2012 at 15:49

2 Answers 2

6

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
}
12
  • 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
    Commented Feb 6, 2012 at 16:06
  • Would you prefer \unexpanded or \detokenize in this case?
    – egreg
    Commented Feb 6, 2012 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
    Commented Feb 6, 2012 at 16:16
  • So I guess this can be closed as a duplicate, as your answer is already included in mine.
    – egreg
    Commented Feb 6, 2012 at 16:19
  • 1
    @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. Commented Feb 6, 2012 at 18:39
3

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}
3
  • Why not use \tl_if_empty:nTF?
    – Joseph Wright
    Commented Feb 6, 2012 at 16:35
  • @JosephWright: Because of the Argument #1 I don't know the contents and I want to avoid unwanted expansion. Commented Feb 6, 2012 at 16:46
  • \tl_fi_empty:nTF does no expansion, and is therefore safe with any input.
    – Joseph Wright
    Commented Feb 6, 2012 at 17:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .