usando \def em \newcommand

usando \def em \newcommand

Considere este exemplo:

\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}

Se \renewcommand\chaptereu descomentar o primeiro, \def\startnewpart{FALSE}o documento será compilado corretamente.

Se, em vez disso, eu descomentar no segundo, \def\startnewpart{FALSE}recebo um erro:

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

l.21 \tableofcontents

Onde está a diferença?

Neste exemplo estou explorando como usar uma variável de controle \startnewpartpara controlar a execução de \chapter. \def\startnewpart{FALSE}destina-se a redefinir o valor de \startnewpart.

Responder1

\secdefé definido como

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

No seu caso você consegue

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

Agora \@ifstaranalisa o seguinte token. Se você descomentar a segunda \deflinha, o próximo token não será *, mas \def. Assim, o LaTeX encontra

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

Aqui está a definição de \@dblarg:

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

Assim você consegue

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

A macro \kernel@ifnextcharabsorve três argumentos, aqui [, {\@chapter}e {\@xdblarg{\@chapter}}verifica se o próximo token é [. Não é, porque é \def, então o efeito é obter

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

OK, vamos dar uma olhada em \@xdblarg:

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

Aqui #1está {\@chapter}(mas os colchetes serão removidos por regra), então você acaba com

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

o que certamente não é algo que você gostaria de ter em seu código.

Não está realmente vinculado a \def. Comandos como

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

devesemprevêm por último em um código de definição, porque eles querem ver o que vem a seguir.

informação relacionada