If you read deep in the LaTeX code you can find lots of examples where this is done. Any command that has optional arguments actually does this already: there are actually two different commands and which one is called depends on whether or not it is called with an optional command. The TeX trick is to use \@ifnextchar[
. For example,
\def\mycmd{\@ifnextchar[{\@with}{\@without}}
\def\@with[#1]#2{hello #1, have you met #2?}
\def\@without#1{goodbye #1}
What happens there is that the TeX interpreter meets the \mycmd
macro and expands it (swallowing following white-space, of course). The first thing it then encounters is a test on the next character (which, incidentally, is non-destructive - the next character is simply observed, not processed). If it is a square bracket, then it puts \@with
in the stream and starts again. \@with
is defined to take two arguments, the first of which is surrounded by square brackets. It therefore matches the first optional argument and the next thingy in the TeX stream. If the next character wasn't a square bracket then \@without
is put into the stream. This takes one (normal) parameter. But since \@with
and \@without
are two completely separate commands, they can do whatever they like with the input.
(Note: For commands defined with \newcommand
which take an optional parameter then sort-of what happens is that the two commands \@with
and \@without
expand to the same command, but the optional parameter of \@with
gets passed to it as the first parameter whereas in \@without
the default value is passed. It's not quite like that, but the difference is more in conciseness of programming than anything else.)
Here's a fully compilable example, including the mysterious and mystical duo \makeatletter
and \makeatother
:
\documentclass{article}
%\url{https://tex.stackexchange.com/a/314/86}
\makeatletter
\def\mycmd{\@ifnextchar[{\@with}{\@without}}
\def\@with[#1]#2{Hello #1, have you met #2?}
\def\@without#1{Goodbye #1.}
\makeatother
\begin{document}
\mycmd[Polyphemus]{Odysseus}
\mycmd{Circe}
\end{document}
Produces:
Hello Polyphemus, have you met Odysseus? Goodbye Circe.