2

Consider this example:

\documentclass{report}
\def\startnewpart{FALSE}
\makeatletter
\renewcommand\chapter{\if@openright\cleardoublepage\else\clearpage\fi                                                                                                                                       
%                    \def\startnewpart{FALSE} 
                    \thispagestyle{plain}%                                                                                                                                                                  
                    \global\@topnum\z@
                    \@afterindentfalse
                    \secdef\@chapter\@schapter
%                    \def\startnewpart{FALSE}                                                                                                                                                               
}
\makeatother
\begin{document}
\tableofcontents
\chapter{Methods}
Some text
\end{document}

If in \renewcommand\chapter I uncomment the first \def\startnewpart{FALSE} the document compiles fine.

If instead I uncomment the second \def\startnewpart{FALSE} I get an error:

Chapter 1.
! Missing { inserted.
\@makechapterhead ...1\par \nobreak \vskip 40\p@ }

l.21 \tableofcontents

Where is the difference?

In this example I am exploring how to use a control variable \startnewpart to control the execution of \chapter. \def\startnewpart{FALSE} is meant to reset the value of \startnewpart.

  • \@chapter and \@schapter look ahead to collect arguments, so they have to be last in the definition. – Henri Menke Feb 26 at 21:45
  • @HenriMenke, is that the purpuse of using @? – Viesturs Feb 26 at 21:46
  • 1
    No. @ just emphasizes that this is not a user command. – Henri Menke Feb 26 at 21:52
3

\secdef is defined as

% latex.ltx, line 6086:
\def\secdef#1#2{\@ifstar{#2}{\@dblarg{#1}}}

In your case you get

\@ifstar{\@schapter}{\@dblarg{\@chapter}}

Now \@ifstar looks at the following token. If you uncomment the second \def line, the next token is not a *, but \def. Thus LaTeX finds

\@dblarg{\@chapter}\def\startnewpart{FALSE}

Here's the definition of \@dblarg:

% latex.ltx, line 1105:
\long\def\@dblarg#1{\kernel@ifnextchar[{#1}{\@xdblarg{#1}}}

Thus you get

\kernel@ifnextchar[{\@chapter}{\@xdblarg{\@chapter}}\def\startnewpart{FALSE}

The macro \kernel@ifnextchar absorbs three arguments, here [, {\@chapter} and {\@xdblarg{\@chapter}} and checks whether the next token is [. It isn't, because it's \def, so the effect is to get

\@xdblarg{\@chapter}\def\startnewpart{FALSE}

OK, let's look at \@xdblarg:

% latex.ltx, line 1106:
\long\def\@xdblarg#1#2{#1[{#2}]{#2}}

Here #1 is {\@chapter} (but the braces will be removed by rule), so you end up with

\@chapter[{\def}]{\def}\startnewpart{FALSE}

which is surely not something you'd like to have in your code.

It's not really tied to \def. Commands such as

\secdef\A\B
\@ifstar{A}{B}
\@ifnextchar<char>{A}{B}

should always come last in a definition code, because they want to look at what comes next.

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.