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

0

4 Answers 4

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

1
  • I confirm that your solution perfectly works.
    – Name
    Sep 2, 2015 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

1
  • I confirm that your solution perfectly works.
    – Name
    Sep 2, 2015 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%
}
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, 2015 at 7:55
  • 3
    @Name That's a “delimited argument”: marginis exiguitas non caperet would write old man Fermat.
    – egreg
    Sep 2, 2015 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
    
4
  • Why not \futurelet also in the first case?
    – egreg
    Sep 2, 2015 at 22:58
  • @egreg -- More flavour ;) Alredy thought about equalizing the two things. Did you implicitely request me to?
    – Ruben
    Sep 3, 2015 at 0:40
  • @Ruben I think \futurelet is more efficient and doesn't require ending with =<space>
    – egreg
    Sep 3, 2015 at 7:56
  • @egreg, you convinced me! updated the first part.
    – Ruben
    Sep 6, 2015 at 17:00

You must log in to answer this question.

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