1

I'm having an hard time understanding how to use the various options etoolbox has for comparing strings. Let's consider this MWE:

\documentclass[11pt, a4paper]{article}

\usepackage{etoolbox}

\newcounter{ContNationality}
\setcounter{ContNationality}{2}

\newcommand{\Nationality}{%
    \ifcase\value{ContNationality}\or%
        {ita}\or{eng}\or{fra}%
    \fi%
}%

\begin{document}

\expandafter\ifdefstring{\Nationality}{ita}{You are italian}{}%
\expandafter\ifdefstring{\Nationality}{eng}{You are english}{}%
\expandafter\ifdefstring{\Nationality}{fra}{You are french}{}%

\end{document}

I put that \expandafter because \ifdefstrings won't expand the content of the command, according to the package guide. Yet, if I execute such code, with or without the \expandafter, the resulting pdf will only include a paragraph with a "b". Quite of an astonishing outcome, I have to say.

So, how can I manage this situation and have the conditionals there to work as I want?

EDIT:

As you pointed out, I wrote \ifvalue instead of \ifcase\value. My mistake.

EDIT 2:

I didn't state this because I thought it wasn't important: the value of \Nationality needs to be dynamic, because actually in the main document I'm working on it is called 100 times, always with a different value of the ContNationality counter.

The fact that there is such counter is more or less fixed by the fact that the value of \Nationality needs to be random, and that I'm using the lcg package which assigns random values to counters. So, basically, I give a random value to that counter and then I use it to determine the random value of \Nationality.

A larger MWE would be the following. I implemented Steven B. Segletes's solution - which works perfectly, I see - which looked like the most user-friendly option to me. I saw egreg's one, and I'm sure it works, but if I copy-paste it in my document I receive a very long list of errors, probably given by the fact that I don't have the very-last version of LaTeX, and I don't understand how to download it. Moreover, I would like to avoid LaTeX3-based solutions because I really don't know anything of that language and I'd prefer to use answers that I understand how they work, so that of course I can work with them in case I need to change my code's behaviour.

\documentclass{article}

\usepackage{etoolbox}
\usepackage[last=2147483647]{lcg}
\usepackage{xifthen}

\newcounter{ContNationality}
\setcounter{ContNationality}{2}
\newcounter{Cycles}
\newcounter{SEED}

\newcommand{\Random}[3]{%
    \providecommand{\NewSeed}{%
        \reinitrand[last=2147483647, seed=\value{SEED}]%
        \rand%
        \setcounter{SEED}{\therand}%
        \typeout{Il seed attualmente è \theSEED}%
    }%
    \reinitrand[first=#1,last=#2,seed=\value{SEED}]%
    \rand%
    \setcounter{#3}{\value{rand}}%
    \NewSeed%
}

\newcommand{\Nationality}{%
    \edef\theNationality{%
        \ifcase\value{ContNationality}%
            \or ita%
            \or eng%
            \or fra%
        \fi%
    }%
}

\begin{document}%
    %
    \rand%
    \setcounter{SEED}{\value{rand}}%
    \setcounter{Cycles}{0}%
    \whiledo{\value{Cycles}<10}{%
        \addtocounter{Cycles}{1}%
        \Random{1}{3}{ContNationality}%
        \Nationality%
        \ifdefstring{\theNationality}{ita}{You are Italian}{}%
        \ifdefstring{\theNationality}{eng}{You are English}{}%
        \ifdefstring{\theNationality}{fra}{You are French}{}%
    \\
    }%  
\end{document}
2

David already explained why the \epandafter is useless. But the second one which would expand \Nationality wouldn't help either, since the definition of \Natioanlity never is the same as the strings you are testing it with. At some point you must expand it completely before the comparison. The easiest way is to \edef \Nationality (unless you don't want it to be fixed but be able to change it mid-document). BTW: there is no \ifvalue that I know of. I guess you want \ifcase\value{...}:

\documentclass{article}

\usepackage{etoolbox}

\newcounter{ContNationality}
\setcounter{ContNationality}{2}

\newcommand{\Nationality}{}
\edef\Nationality{%
  \ifcase\value{ContNationality}
  \or ita%
  \or eng%
  \or fra%
  \fi
}

\begin{document}

\ifdefstring{\Nationality}{ita}{You are Italian}{}%
\ifdefstring{\Nationality}{eng}{You are English}{}%
\ifdefstring{\Nationality}{fra}{You are French}{}%

\end{document}

PS: just seeing that egreg already explained the issues. I'll leave the answer anyway as it doesn't use expl3.

10
  • Of course, the way you have it set up, you can only use it once. – Steven B. Segletes May 25 '17 at 16:57
  • @StevenB.Segletes that's what I mean by “unless you don't want it to be fixed but be able to change it mid-document” – it's not clear from the question how the use-case will be… – cgnieder May 25 '17 at 16:58
  • If you define it \newcommand{\Nationality}{% \edef\theNationality{% \ifcase\value{ContNationality}% \or ita% \or eng% \or fra% \fi% }}, then you can perform the test repeatedly with \Nationality \ifdefstring{\theNationality}{ita}{You are Italian}{}% \ifdefstring{\theNationality}{eng}{You are English}{}% \ifdefstring{\theNationality}{fra}{You are French}{}%, that is, by reinvoking \Nationality prior to the next test. – Steven B. Segletes May 25 '17 at 17:02
  • \Nationality would in fact be called several times across the document. This of course is just a MWE; in the main document there is a cycle that is repeated 100 times, and every time it calls \Nationality with a possibly different value of ContNationality. – il mietitore May 25 '17 at 17:04
  • 1
    @ilmietitore I think clemens deserves the credit. Maybe he can incorporate a revision to show either my approach or a better one that achieves re-usability of the macro. – Steven B. Segletes May 25 '17 at 17:46
1
\expandafter\ifdefstring{\Nationality

applies expansion to { which doesn't expand, you meant

\expandafter\ifdefstring\expandafter{\Nationality

However that will still only expand \Nationality one step

0

You are misunderstanding what \ifdefstring does. Its first argument is a macro and its first level expansion is compared to the second argument. The first level expansion of \Nationality is not a string, but the whole \ifcase\value...\fi.

Here's an expandable test based on expl3.

\documentclass[11pt, a4paper]{article}

\usepackage{xparse}

\newcounter{ContNationality}
\setcounter{ContNationality}{2}

\ExplSyntaxOn
\NewExpandableDocumentCommand{\Nationality}{}
 {
  \int_case:nn { \value{ContNationality} }
   {
    {1}{ita}
    {2}{eng}
    {3}{fra}
   }
 }

\NewExpandableDocumentCommand{\ifdefstringx}{mmmm}
 {
  \str_if_eq_x:nnTF { #1 } { #2 } { #3 } { #4 }
 }
\ExplSyntaxOff

\begin{document}

\ifdefstringx{\Nationality}{ita}{You are italian}{}\par
\ifdefstringx{\Nationality}{eng}{You are english}{}\par
\ifdefstringx{\Nationality}{fra}{You are french}{}\par

\setcounter{ContNationality}{1}

\ifdefstringx{\Nationality}{ita}{You are italian}{}\par
\ifdefstringx{\Nationality}{eng}{You are english}{}\par
\ifdefstringx{\Nationality}{fra}{You are french}{}\par

\end{document}

enter image description here

If you want a solution based on etoolbox, you can do as follows (but, differently from the above solution this is not expandable).

\documentclass[11pt, a4paper]{article}

\usepackage{etoolbox}

\newcounter{ContNationality}
\setcounter{ContNationality}{2}

\newcommand{\Nationality}{%
  \ifcase\value{ContNationality}\or
  ita\or
  eng\or
  fra\fi
}

\makeatletter
\newcommand{\ifdefstringx}[2]{%
  \begingroup
  \edef\x{#1}%
  \ifdefstring{\x}{#2}{\endgroup\@firstoftwo}{\endgroup\@secondoftwo}%
}
\makeatother

\begin{document}

\ifdefstringx{\Nationality}{ita}{You are italian}{}\par
\ifdefstringx{\Nationality}{eng}{You are english}{}\par
\ifdefstringx{\Nationality}{fra}{You are french}{}\par

\setcounter{ContNationality}{1}

\ifdefstringx{\Nationality}{ita}{You are italian}{}\par
\ifdefstringx{\Nationality}{eng}{You are english}{}\par
\ifdefstringx{\Nationality}{fra}{You are french}{}\par

\end{document}

If you want an expandable text:

\documentclass[11pt, a4paper]{article}

\usepackage{etoolbox}

\newcounter{ContNationality}
\setcounter{ContNationality}{2}

\newcommand{\Nationality}{%
  \ifcase\value{ContNationality}\or
  \expandafter\itastring\or
  \expandafter\engstring\or
  \expandafter\frastring\fi
}
\newcommand{\itastring}{ita}
\newcommand{\engstring}{eng}
\newcommand{\frastring}{fra}

\newcommand{\ifdefstringx}[1]{%
  \expandafter\ifstrequal\expandafter{\romannumeral-`Q#1}%
}

\begin{document}

\ifdefstringx{\Nationality}{ita}{You are italian}{}\par
\ifdefstringx{\Nationality}{eng}{You are english}{}\par
\ifdefstringx{\Nationality}{fra}{You are french}{}\par

\setcounter{ContNationality}{1}

\ifdefstringx{\Nationality}{ita}{You are italian}{}\par
\ifdefstringx{\Nationality}{eng}{You are english}{}\par
\ifdefstringx{\Nationality}{fra}{You are french}{}\par

\end{document}

Alternatively

\documentclass[11pt, a4paper]{article}

\usepackage{pdftexcmds}

\newcounter{ContNationality}
\setcounter{ContNationality}{2}

\newcommand{\Nationality}{%
  \ifcase\value{ContNationality}\or
  ita\or
  eng\or
  fra\fi
}

\makeatletter
\newcommand{\ifdefstringx}[2]{%
  \ifnum\pdf@strcmp{#1}{#2}=\z@
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}
\makeatother

\begin{document}

\ifdefstringx{\Nationality}{ita}{You are italian}{}\par
\ifdefstringx{\Nationality}{eng}{You are english}{}\par
\ifdefstringx{\Nationality}{fra}{You are french}{}\par

\setcounter{ContNationality}{1}

\ifdefstringx{\Nationality}{ita}{You are italian}{}\par
\ifdefstringx{\Nationality}{eng}{You are english}{}\par
\ifdefstringx{\Nationality}{fra}{You are french}{}\par

\end{document}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.