Using the compulsory argument for the optional argument?

The classical approach for this is to use \@dblarg:

\documentclass{article}

\makeatletter
\newcommand{\foo}{\@dblarg\ah@foo}
\def\ah@foo[#1]#2{#1 foo(#2)}
\makeatother

\begin{document}

No optional argument: \foo{xyz}

Optional argument: \foo[abc]{xyz}

\end{document}

enter image description here

With xparse it's easier:

\documentclass{article}
\usepackage{xparse}

\NewDocumentCommand{\foo}{om}{%
  \IfNoValueTF{#1}{#2}{#1} foo(#2)%
}

\begin{document}

No optional argument: \foo{xyz}

Optional argument: \foo[abc]{xyz}

\end{document}

Wherever you need the optional argument, you type \IfNoValueTF{#1}{#2}{#1}.

There's a much slicker way if you have xparse released 2017/02/10 (or later): an optional argument O can take as default any of the mandatory argument:

\documentclass{article}
\usepackage{xparse}

\NewDocumentCommand{\foo}{ O{#2} m }{%
  #1 foo(#2)%
}

\begin{document}

No optional argument: \foo{xyz}

Optional argument: \foo[abc]{xyz}

\end{document}

So we're telling \foo that, if the optional argument is missing (first call), the mandatory argument #2 should be used also as value for #1. In the second call, the optional argument is given, so it's substituted for #1.


This is pretty easy with \NewDocumentCommand from xparse, checking whether the optional argument (o) was given or not with \IfValueTF{#1}{}{}.

Not so easy with \newcommand, however. Define a command without arguments, say \foobar and check with \@ifnextchar[{}{} whether the next character is a [ and branch into a command that uses []{} arguments and another one, that does only use the mandatory argument, i.e. {}. This technique is called 'moving arguments'. This way does not need other extra packages and applies LaTeX core features. The only 'tricky' point is to use the \makeatletter...\makeatother pair.

\@ifnextchar[ looks for [ and if this is found, the character is basically 'shifted' back such that \foobar@opt can find it again as start of a command with optional argument (Actually, [ is stored to a temporary macro and expanded for the true branch if [ has been found)

\documentclass{article}

\usepackage{xparse}

\makeatletter
\newcommand{\foobar}{%
  \@ifnextchar[{\foobar@opt}{\foobar@noopt}
}{}

\newcommand{\foobar@opt}[2][]{%
  #1 foo(#2)%
}

\newcommand{\foobar@noopt}[1]{%
  #1 foo(#1)%
}
\makeatother

\NewDocumentCommand{\foo}{om}{%
  \IfValueTF{#1}{%
    #1 foo(#2)%
  }{%
    #2 foo(#2)%
  }%
}


\begin{document}
\foo[hello]{hi}

\foo{hi}       


\foobar[hello]{hi}

\foobar{hi}       

\end{document}

enter image description here


You can supply a default value for the optional argument, and use this to condition on whether or not it was supplied in the first place.

enter image description here

\documentclass{article}

\newcommand{\foo}[2][\relax]{%
  \ifx\relax#1\relax #2\else #1\fi
  ~foo(#2)%
}

\begin{document}

\foo[hello]{hi}

\foo[]{hi}

\foo{hi}       

\end{document}

Above I specified that the optional argument will default to \relax if it is not supplied, and then check \ifx\relax#1\relax to either place #2 or #1. \ifx compares the following two tokens for equivalence.