2

I am trying to create a command test that takes 3 arguments. The first argument is optional, while the second and third arguments are mandatory.

I am trying to use the xifthen package, and specifically the \xifthen and \isempty commands therein, to test whether the optional argument is given.

  • If the optional argument is NOT given, test should return "A".
  • If the optional argument is given, test should return "B".

Here is my MWE:

\documentclass{article}
\usepackage{xifthen}

\newcommand{\test}[3]{%
\ifthenelse{\isempty{#1}}{A}{B}
}

\begin{document}

\test{u}{v}
\\
\test[something]{u}{v}

\end{document}

But I get the following output. What is/are my mistake(s)?

output

6
  • 1
    your command has no optional argument but three mandatory arguments. Use \newcommand{\test}[3][]{... Oct 22 '20 at 18:05
  • 1
    you have defined a command with three mandatory arguments, you need to supply the default value in \newcommand to make the first argument optional Oct 22 '20 at 18:05
  • 1
    don't you want to use #1 somewhere? Oct 22 '20 at 18:06
  • @DavidCarlisle Yes, I do; I was just debugging. As you can see, I am a total novice.
    – Andrew
    Oct 22 '20 at 18:07
  • @UlrikeFischer Ahhh, thank you. I'm rather embarrassed, but thank you for being kind.
    – Andrew
    Oct 22 '20 at 18:08
3

You're defining a macro with three mandatory (that is, braced) arguments. You need a slightly different syntax in order to make the first argument optional.

On the other hand, you can use \NewDocumentCommand, provided by the xparse package that is currently part of the kernel.

\documentclass{article}
%\usepackage{xparse}% not needed with LaTeX 2020-10-01 or later

\NewDocumentCommand{\test}{omm}{%
  \IfNoValueTF{#1}{A}{B}%
}

\begin{document}

\test{u}{v}

\test[something]{u}{v}

\end{document}

This will print “A” and “B”.

The idea is basically the same as

\newcommand{\test}[3][SoMeTHiNGweIrd]{%
  \ifthenelse{\equal{#1}{SoMeTHiNGweIrd}}{A}{B}%
}

but the implementation is better; for instance, the \IfNoValueTF test is expandable, which \ifthenelse isn't. Care is taken that the string, here represented by SoMeTHiNGweIrd is really something that needs extra effort to be produced.

In omm we state the argument types:

  • o is an optional argument with no default value; its absence makes the \IfNoValueTF test to return true;

  • m is a mandatory argument.


Why are you getting that output? As I said, your macro takes three mandatory arguments. In the first call the arguments found are

  1. u
  2. v
  3. \\

Since u is not empty, you get B.

In the second call the arguments are

  1. [
  2. s
  3. o

Thus you get B, a space (because of the endline at the end of the \ifthenelse line, and then mething]uv

There are two spaces between the B's: one is generated by the endline in the definition (as explained before) and one is the endline after \\. This token is not executed, because it has been absorbed as an unused argument, so the endline counts as a space.

2

enter image description here

You need to use the second optional argument of \newcommand so that #1 is optional.

\documentclass{article}

\usepackage{ifthen}

\newcommand{\test}[3][--zzz--]{%
\ifthenelse{\equal{#1}{--zzz--}}{A}{B with #1} [#2][#3]%
}

\begin{document}

\test{u}{v}

\test[something]{u}{v}

\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.