using \def in \newcommand

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
• No. @ just emphasizes that this is not a user command. – Henri Menke Feb 26 at 21:52

\secdef is defined as

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


\@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.