4

I was looking in the file book.cls and I noted there is no mandatory argument in the definition of \section, \subsection, and \paragraph commands

\newcommand\section{\@startsection {section}{1}{\z@}%
           {-3.5ex \@plus -1ex \@minus -.2ex}%
           {2.3ex \@plus.2ex}%
           {\normalfont\Large\bfseries}}
\newcommand\subsection{\@startsection{subsection}{2}{\z@}%
           {-3.25ex\@plus -1ex \@minus -.2ex}%
           {1.5ex \@plus .2ex}%
           {\normalfont\large\bfseries}}
%etc.

i.e. the commands are all in the form \newcommand\foosection{\@startsection{foo}{foo}{foo}...}. Then I looked into the \@startsection definition and there is the \@sect command which takes 8 arguments but I didn't quite understand very well which one represents the heading to be printed for the section neither how can a command can be defined with a mandatory argument without declaring it.

Do you know how is the title of the section entering in its definition and if the mandatory argument is in some way implicitly defined inside the command definition itself?

GiuTeX
  • 1,309
  • 2
    The answer to how to declare a macro that seems to take an argument, without declaring that it does is here: https://en.wikipedia.org/wiki/Currying – Skillmon Sep 23 '19 at 14:18

1 Answers1

10

Let's take the example of \section (all of them behave more or less the same, except for \chapter and \part). The definition is:

\newcommand\section{\@startsection {section}{1}{\z@}%
           {-3.5ex \@plus -1ex \@minus -.2ex}%
           {2.3ex \@plus.2ex}%
           {\normalfont\Large\bfseries}}

so when you do \section you are actually doing \@startsection with a bunch of parameters, which will be used to know: #1: the name of the command, counter to be used, etc.; #2: the level of the section heading; #3: the indentation of the heading, in case of a \paragraph-type heading; #4: space before the heading, #5: space after the heading, and #6: style. There are a few conditions when #4 or #5 are negative to produce run-in headings, like \paragraph, but I'll not get into that here.

If you look at the definition of \@startsection you will see it takes these 6 arguments:

\def\@startsection#1#2#3#4#5#6{%

At this point, all that was done is the \section command: TeX has not looked at anything beyond that yet. Now, at the end of the definition of \@startsecion you see:

  \@ifstar
    {\@ssect{#3}{#4}{#5}{#6}}%
    {\@dblarg{\@sect{#1}{#2}{#3}{#4}{#5}{#6}}}

here, the \@ifstar checks for a * following \section.

If there is a * then four of the arguments of \@startsection are passed to \@ssect: \@ssect{#3}{#4}{#5}{#6}. But \@ssect has 5 arguments:

\def\@ssect#1#2#3#4#5{%

so the fifth argument is the section title. Here no optional argument is expected. Try \section*[optional]{mandatory} to see.

If there is no * then \@dblarg{\@sect{#1}{#2}{#3}{#4}{#5}{#6}} is used.

\@dblarg checks for a following [...]-delimited argument (<optional>) and then a <mandatory> argument. If there is a [, then \@dblarg{<code>}[<optional>]{<mandatory>} expands to just <code>[<optional>]{<mandatory>}, otherwise it expands to <code>[<mandatory>]{<mandatory>}. In short, it duplicates the mandatory argument if no optional argument is given; thus the name \@dblarg.

After \@dblarg is completed, you are left with:

\@sect{#1}{#2}{#3}{#4}{#5}{#6}[<optional-or-copy-of-mandatory>]{<mandatory>}

where the (possible) optional argument is taken from the input stream, right after \section, and the mandatory argument right after that.

Finally, \@sect is expanded, which takes 6 arguments, a [...]-delimited argument, and another argument:

\def\@sect#1#2#3#4#5#6[#7]#8{%

finishing the argument parsing of \section.


In short, the \section command itself does not take any argument. However it expands to a sequence of commands that will parse the input stream and handle possible optional arguments and use them. A closely related question was asked earlier today on the subject of optional arguments. You may find it useful: Optional Arguments Based on Position