3

I want to define a conditional command that I can easily use with \ifnum, hence such a command should expand to a number. However, I sometimes need to define temporary commands which breaks such usage, as the following MWE illustrates.

\documentclass{article}

\def\isEqualTFO#1#2#3#4{%
  % return #2 if \entry is defined and equals #1
  % return #3 if \entry is defined and is not equal to #1
  % otherwise returns #4
  \ifdefined\exclusiveEntry
    \def\tmp{#1}
    \ifx\exclusiveEntry\tmp
      #2
    \else
      #3
    \fi
  \else
    #4
  \fi}
\begin{document}

Test

\def\exclusiveEntry{Hello}

\isEqualTFO{Hello}{1}{2}{3}
\isEqualTFO{World}{1}{2}{3}

% This returns an error "Missing number, treated as zero."
% \ifnum\isEqualTFO{Hello}{1}{2}{3}=2
% First\else Second\fi

\end{document}

My command \isEqualTFO returns one of three inputs depending on the value of \entry. However, because I am having to \def\tmp to be able to compare \entry with the input using \ifx, this break the usage of my command in \ifnum since it does not expand to a simple number.

How do I correctly use isEqualTFO with ifnum? by either modifying the command definiton or changing the way I call it? For example, I thought calling

\expandafter\ifnum\isEqualTFO{Hello}{1}{2}{3}

would do the trick, but it still gives the same error.

2
  • you can't use your command with \ifnum. You will have to change it. Commented Aug 2 at 16:33
  • you need an expandable comparison, so use \pdfstrcmp (called \strcmp in some engines or lua expl3 provides a version that works in all engines Commented Aug 2 at 16:33

2 Answers 2

4

You need an expandable comparison, expl3 provides one in the str module

\documentclass{article}

\ExplSyntaxOn
\NewDocumentCommand\isEqualTFO{mmmm}{%
  % return #2 if \entry is defined and equals #1
  % return #3 if \entry is defined and is not equal to #1
  % otherwise returns #4
  \cs_if_exist:NTF\exclusiveEntry
  {
    \str_if_eq:VnTF \exclusiveEntry {#1}
     { #2 }
     { #3 }
   }
  { #4 }
}

\ExplSyntaxOff
\begin{document}

Test

undef: \isEqualTFO{Hello}{1}{2}{3}

\def\exclusiveEntry{Hello}

equal: \isEqualTFO{Hello}{1}{2}{3}

not equal: \isEqualTFO{World}{1}{2}{3}


\end{document}
3

LaTeX as a programming language does not have the concept of "return values" that you can plug into the input of other commands. It only has macro definitions that might be nested to some degree.

For example the following is valid:

\def\mytext{\textbf{abc}}
\textit{\mytext}

This will expand to \textit{\textbf{abc}} which will output bold italic text in the document. This is allowed because \textbf{abc} is something that is well-formed as argument of \textit{}.

In your case however, you try to use \isEqualTFO{Hello}{1}{2}{3} as argument to \ifnum. This will expand to something like

\ifnum\ifdefined\exclusiveEntry\def\tmp{#1}\ifx[...etc etc...]=2

This is by no means an input that \ifnum understands, as it needs a number, or a macro containing a number.

So, an approach is to set the number you want to a helper macro with \gdef (global def) and compare those.

MWE:

\documentclass{article}

\def\setnum#1#2#3#4{%
  % set #2 if \entry is defined and equals #1
  % set #3 if \entry is defined and is not equal to #1
  % otherwise set #4
  \ifdefined\exclusiveEntry
    \def\tmp{#1}
    \ifx\exclusiveEntry\tmp
      \gdef\mynum{#2}
    \else
      \gdef\mynum{#3}
    \fi
  \else
    \gdef\mynum{#4}
  \fi}
\begin{document}

Test

\def\exclusiveEntry{Hello}

\setnum{Hello}{1}{2}{3}

\ifnum\mynum=2
First\else Second\fi

\setnum{World}{1}{2}{3}
\ifnum\mynum=2
First\else Second\fi

\end{document}

This prints:

Test
Second
First

As mentioned in the comments, there are also comparison commands that do expand (i.e., "execute") the arguments before the comparison, such as \pdfstrcmp. The same logic holds for these: the input needs to be strings and not macro calls, but they are made in such a way that they first store the result of the macro call and then compare, which is conceptually similar to the approach in this answer.

2
  • why gdef? you don't need a global definition here surely? Commented Aug 2 at 20:07
  • @DavidCarlisle just in case the \setnum command is used inside of a group and the \ifnum test outside of that group (which is not the case in the current MWE, but it might be in the real code - or maybe not).
    – Marijn
    Commented Aug 3 at 14:11

You must log in to answer this question.

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