3

I understand that among the ways we can define macros, there are at least three main streams.

The original TeX method: We use the \def command (and similar ones) to define macros. One very attractive feature is being able to customize the argument parsing. When we write \def\mymacro#1.#2-(#3){<macro definition>} we understand that the first argument must be followed by a dot, the second one by a dash, while the third argument must be enclosed between parentheses.

In this method, is it possible to declare an argument to be optional in a straightforward manner?

The LaTeX method: We use \newcommand (and \renewcommand) to define (and redefine) macros. Optional argument declaration is possible, but I don't call it straightforward.

What if there more than one optional arguments? What about several optional arguments scattered among the mandatory arguments? Is it possible to control parsing of the arguments?

Necessitating the use of \renewcommand preventing accidental redefinition of existing ones is a good feature.

\NewDocumentCommand using xparse: Looks like the latest one. The straightforward manner in which I can mix the mandatory and optional arguments is particularly attractive to me. Comes with other loads of features.


I am making this post asking those with really vast experience to tutor us on the relative merits and demerits of the three main streams. If want to stick to only one, which one should we choose? Or do we keep on using them all in the same document and use the one which fits my need of the moment?

(Though there are several sentences ending with question marks in this post, it is not a post with several questions. Rather, these are the talking points which the answerer will find to be helpful when creating the tutorial.)

  • Avoid explicitly delimited arguments, unless they fit within established syntax (such as (x,y) for coordinates). The more arguments a macro has, the harder is to remember their order and their delimiter. – egreg Aug 10 '17 at 10:06
3

The way one uses the \newcommand structure to get multiple optional arguments is to have the called macro use auxiliary macros to absorb an additional optional argument.

\documentclass{article}
\usepackage[T1]{fontenc}
\newcommand\mymacro[2][\Humpty]{\def\tmpA{#1}\def\tmpB{#2}\mymacroaux}
\newcommand\mymacroaux[2][\Dumpty]{%
  \detokenize\expandafter{\tmpA}
  \detokenize\expandafter{\tmpB}
  \detokenize{#1}
  \detokenize{#2}.%
}
\begin{document}
\mymacro{\Charles}{did \relax}

\mymacro[Fat]{\old}{ate \cake}

\mymacro{\Dumpty}[\fell\&]{broke his \crown}

\mymacro[My]{\mom}[is the]{\greatest!}
\end{document}

enter image description here


As to the way to do optional arguments via \def, the standard approach using \futurelet, as documented on p.277 of https://www.tug.org/TUGboat/tb09-3/tb22bechtolsheim.pdf, is

\documentclass{article}
\begin{document}
\def\xxWithOpt[#1]#2{Optional argument #1, Mandatory argument #2}
\def\xxNoOpt#1{No optional argument, mandatory argument #1}

\def\xx {%
  \futurelet\xxLookedAtToken\xxDecide
}

\def\xxDecide {%
  \ifx\xxLookedAtToken [%
    \let\next = \xxWithOpt
  \else
    \let\next = \xxNoOpt
  \fi
  \next
}

\xx{A}

\xx[a]{A}
\end{document}

enter image description here


The xparse approach is discussed at https://tug.org/TUGboat/tb31-1/tb97wright-xparse.pdf, by Joseph. There are many ways to specify arguments with this approach and here I show only one, similar to the first example:

\documentclass{article}
\usepackage{xparse}
\DeclareDocumentCommand \foo
{ o +m o +m } {%
% Four args, #1, #2, #3 and #4
% Only #2 and #4 can include \par tokens
\IfNoValueTF{#1}{%
  a%
}{%
  #1%
}%
.#2.%
\IfNoValueTF{#3}{%
  c%
}{%
  #3%
}%
.#4%
}
\begin{document}

\foo{B}{D}

\foo[A]{B}{D}

\foo{B}[C]{D}

\foo[A]{B}[C]{D}
\end{document}

enter image description here


I myself tend not to use the xparse approach only because it is less familiar to me; however, I suppose current and future students of LaTeX will be schooled in this approach from the start, as it, no doubt is the most robust and flexible. As mentioned by the OP, the feature of \newcommand that checks for the pre-existence of a macro name is very useful. I don't always use \def, but when I do, it is generally for one of two reasons: 1) unique parsing of the arguments is required, as provided for by \def, or 2) I am too lazy to type the 10 letters of \newcommand rather than the 3 of \def.

  • Thanks. Do you want to make a concluding remark? – Masroor Aug 10 '17 at 4:26
  • @Masroor I have supplemented my answer. – Steven B. Segletes Aug 10 '17 at 10:03

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.