6

I would like to define a command with two arguments, say \mycommand{arg1}{arg2} in such a way that if the second argument is absent, then it takes the first argument in place of the second one, in other words, \mycommand{arg1} would be equivalent to \mycommand{arg1}{arg1}.

4

This syntax relies on the fact that one will use braces to enclose arguments (otherwise the question is ambiguous since any subsequent token can be interpreted as a second argument).

\documentclass{article}
\makeatletter
\def\mycommand#1{\@ifnextchar\bgroup{\mycommandhelp{#1}}{\mycommandhelp{#1}{#1}}}
\makeatother
\def\mycommandhelp#1#2{Mycommands arguments: #1 and #2}
\begin{document}
\mycommand{arg1}

\mycommand{arg1}{arg2}
\end{document}

enter image description here

I would only add as a proviso that when only one argument is provided, any subsequent space following that argument is gobbled. If one always wanted to provide a following space, regardless of using 1 or 2 arguments, one could define

\def\mycommandhelp#1#2{Mycommands arguments: #1 and #2\ \ignorespaces}

If one never wanted to auto-provide the space, then

\def\mycommandhelp#1#2{Mycommands arguments: #1 and #2\ignorespaces}

could be used.


As egreg mentions in his answer, LaTeX provides for optional arguments. In your case, a simple implementation of that would be:

\newcommand\mycommand[2][\relax]{\ifx\relax#1 The arguments are #2 and #2\else
  The arguments are #1 and #2\fi}

with the calling syntax as \mycommand{arg1} or else \mycommand[arg1]{arg2}.

  • I confirm that your solution perfectly works. – Name Sep 2 '15 at 7:49
4

Here's a xparse solution using the g specifier as a possible optional 2nd (!!!) argument, the g specifier allows for {} delimited optional arguments, but in my point of view, [] would be a clearer way.

\documentclass{article}

\usepackage{xparse}


\NewDocumentCommand{\xparsecmd}{mg}{%
  \IfValueTF{#2}{%
    optional #1 and #2
  }{%
    Only #1 and #1
  }%
}

\begin{document}

\xparsecmd{hello}

\xparsecmd{hello}{World}

\end{document}

enter image description here

  • I confirm that your solution perfectly works. – Name Sep 2 '15 at 7:50
4

Usually this is realized in the form

\foo{Unique}

and

\foo[One]{Two}

which is clearer than an optional argument in braces.

The classical LaTeX way to do this is

\newcommand{\foo}{\@dblarg\name@foo}
\def\name@foo[#1]#2{Whatever we want to do with #1 and #2}

So calling \foo{X} will result in

Whatever we want to do with X and X

whereas calling \foo[X]{Y} will result in

Whatever we want to do with X and Y

With xparse you might do

\usepackage{xparse}

\NewDocumentCommand{\foo}{om}{%
  \IfNoValueTF{#1}{\realfoo{#2}{#2}}{\realfoo{#1}{#2}}%
}
\NewDocumentCommand{\realfoo}{mm}{%
  Whatever we want to do with #1 and #2%
}
  • I confirm that both solutions works. I just have a question why in the first question , there are [ ] around #1 but not around #2. – Name Sep 2 '15 at 7:55
  • 3
    @Name That's a “delimited argument”: marginis exiguitas non caperet would write old man Fermat. – egreg Sep 2 '15 at 7:57
4

Just in case, here is a Plain solution

  • with optional braced 2nd argument:

    \def\foo#1{\edef\tmp{#1}\futurelet\next\fooaux}
    \def\fooaux{%
      \ifx\next\bgroup
        \expandafter\fooprocess
      \else
        \fooprocess\tmp
      \fi
    }
    \def\fooprocess#1{Something with \tmp\ and #1}
    
    \foo{bar}
    
    \foo{bar}{baz}
    
    \bye
    
  • with optional bracket 1st argument:

    \def\foo{\futurelet\next\fooaux}
    \def\fooaux{%
      \ifx\next[
        \expandafter\fooi
      \else
        \expandafter\fooii
      \fi
    }
    \def\fooii#1{\fooi[#1]{#1}}
    \def\fooi[#1]#2{Something with #1 and #2}
    
    \foo{bar}
    
    \foo[bar]{baz}
    
    \bye
    
  • Why not \futurelet also in the first case? – egreg Sep 2 '15 at 22:58
  • @egreg -- More flavour ;) Alredy thought about equalizing the two things. Did you implicitely request me to? – Ruben Sep 3 '15 at 0:40
  • @Ruben I think \futurelet is more efficient and doesn't require ending with =<space> – egreg Sep 3 '15 at 7:56
  • @egreg, you convinced me! updated the first part. – Ruben Sep 6 '15 at 17:00

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.