1

I just went through part of the wikipage for LaTeX Macros and tried the following syntax to create a new command with an optional argument:

\documentclass{article}

\newcommand{\wbalTwo}[2][Wikimedia]{This is the Wikibook about LaTeX supported by {#1} and {#2}}

\begin{document} \wbalTwo[lots of users]{John Doe}

\end{document}

This compiles fine and I get a result as follows: enter image description here

I also tried switching the optional and required argument above:

\documentclass{article}

\newcommand{\wbalTwo}[2][Wikimedia]{This is the Wikibook about LaTeX supported by {#1} and {#2}}

\begin{document} \wbalTwo{John Doe}[lots of users]

\end{document}

This also compiles fine, but in the resulting pdf the square brackets are preserved:

enter image description here

Which indicates to me that LaTeX needs to have the optional arguments specified first before specifying the required arguments for the newly defined command to work properly.

However, in page 4 of the titlesec manual the following is stated:

\titleformat{<command>}[<shape>]{<format>}{<label>}{<sep>}{<before-code>}[<after-code>]

I'm guessing titleformat is a command just like any other. How is it that it allows for square bracket arguments to be placed in between braced arguments? Am I missing something here?

user32882
  • 1,594
  • 1
    Commands defined with \newcommand can only have one optional argument and that optional argument must be the first. It is possible to code more complex argument structures using tools other than \newcommand. Previously this would have been quite painful with internal commands like \@ifnextchar[, but since xparse was baked into the LaTeX kernel you can now use \NewDocumentCommand for a more flexible argument structure (https://tex.stackexchange.com/q/29973/35864, https://www.texdev.net/2020/08/20/newdocumentcommand-versus-newcommand-versus). – moewe Aug 16 '21 at 14:59
  • Am I to gather that vanilla LaTeX only allows one default argument, and up to 9 required arguments? How arbitrary don't you think!? – user32882 Aug 16 '21 at 15:10
  • Mhhh. Something along those lines, yes. This is certainly true for commands defined the normal way with \newcommand (though the total number of arguments is 9, not the total number of mandatory arguments). Though notably \newcommand itself has two optional arguments. So go figure. – moewe Aug 16 '21 at 15:12
  • @user32882 not really \NewDocumentCommand is defined by default in latex just as \newcommand is so (in current latex releases) you can't say one is "vanilla" and the other not. – David Carlisle Aug 16 '21 at 15:16
  • the restriction to 9 arguments #1 to #9 is not due to latex that is built in to tex. – David Carlisle Aug 16 '21 at 15:18
  • So then why don't they just deprecate \newcommand? Why keep both newcommand and NewDocumentCommand? – user32882 Aug 16 '21 at 15:18
  • 4
    because if we didn't keep both, 30 something years of existing latex documents would break. – David Carlisle Aug 16 '21 at 15:18
  • 1
    The total number is a constraint introduced by TeX. (Commands defined with \def can't have more than nine arguments, either.) So that might be rooted in a mixture of performance considerations and 'no one in their right mind should use more than nine arguments for a macro'. (Plus in a way any limit can feel arbitrary, so 9 might not be too bad if you consider how macro arguments declared and are parsed in TeX.) The \newcommand limitation is a bit odd, but given the interface it is understandable and again one probably felt that normal commands wouldn't need to be too complex. – moewe Aug 16 '21 at 15:19
  • 2
    you can of course define a command that is followed by 25 brace groups if you really want to do that but you can not refer to the groups in code using #1 to #25. But really if there are more than a couple of arguments better to use a key=value syntax like \includegraphics[width=3pt, clip, angle=90]{zzz] – David Carlisle Aug 16 '21 at 15:21
  • @DavidCarlisle I see what you're saying about backwards compatibility, but surely there are better alternatives than making a new command such as NewDocumentCommand. Why not simply refactor the newcommand code in the new LaTeX release instead of making a whole new function? That would ensure backwards compatibility... Or the LaTeX developers could simply communicate to their user base that they are "dropping" support for \newcommand. Consider all the code that had to be ported from python2 to python3 when this became a necessity.... – user32882 Aug 16 '21 at 15:22
  • 3
    No really we (not they) could not do that. – David Carlisle Aug 16 '21 at 15:29
  • 3
    @user32882 The syntax of \newcommand is fundamentally different from \NewDocumentCommand, plus they have (deliberately) different behaviour w.r.t. expansion. For 'shortcuts', \newcommand remains the better choice, but for 'real' document commands I would use \NewDocumentCommand. – Joseph Wright Aug 16 '21 at 17:54
  • Regarding the #9 limitation, you can use something like \foo(\bar{a}{b}}{\bar{c}{d}}... to pass more than 9 arguments (indirectly). – John Kormylo Aug 16 '21 at 18:35

1 Answers1

1

At a primitive level TeX does not have optional arguments.

While your declaration

\newcommand{\wbalTwo}[2][Wikimedia]{... #1  #2}

may be thought of as defining a command with one optional argument and one mandatory argument, the command \wbalTwo has no arguments at all (as you can check using \meaning\wbalTwo It is defined to be a command that looks ahead for [ and branches acording to whether [ is there or not, with internal helper commands actually picking up the arguments.

\newcommand provides a syntactic shorthand for declaring commands with mandatory arguments or one optional initial argument. \NewDocumentCommand provides a simple syntax for a much wider set of commands, but you can always define the helper macros individually and build up the argument syntax that you want so for example to define your trailing optional argument with \newcommand:

\documentclass{article}

\newcommand{\wbalTwo}[1]{This is the Wikibook about LaTeX supported by {#1} and \wbalTwoaux} \newcommand{\wbalTwoaux}[1][Wikimedia]{#1}

\begin{document} \small

1 \wbalTwo{John Doe}

2 \wbalTwo{John Doe}[lots of users]

\end{document}

enter image description here

David Carlisle
  • 757,742