Erros ao usar condicionais no argumento opcional da classe do documento

Erros ao usar condicionais no argumento opcional da classe do documento

Encontrei uma interação estranha entre os parâmetros opcionais \documentclasse \ifas instruções. Por alguma razão, o código é compilado se houver uma \elseinstrução, mesmo que não tenha conteúdo:

\newif\ifdraftversion \draftversionfalse
\newif\iffullversion  \fullversionfalse

\documentclass[
  \iffullversion  twoside,  \fi %works if the \fi here are
  \ifdraftversion draft,    \fi % \else\fi instead
  11pt
]{article}

\begin{document}
This is a MWE, although it generates an extra warning that would
disappear if I added substantially more content to the document
\end{document}

Embora essa solução alternativa não seja particularmente onerosa, não consegui isolar o bug real envolvido ou descobrir o que entendi mal. Existe alguma razão pela qual minha intuição está me levando a usar sintaxe inválida e, em caso afirmativo, onde/o quê/por quê?

Responder1

O \documentclasscomando faz alguma contabilidade e depois chama

\@fileswithoptions\@clsextension

Neste ponto, as opções e o argumento ainda não foram analisados. A macro \@fileswithoptionsabsorve seu argumento e então verifica se [segue. Após esta decisão, ele executa

\@fileswith@ptions\@clsextension[<options>]{article}

que procura mais um argumento opcional; no final chegamos a

\@fileswith@pti@ns\@clsextension[<options>]{article}[]

porque você não especifica o argumento opcional final. Esta macro faz

\xdef\@classoptionslist{\zap@space<options> \@empty}

então devemos perguntar o que acontece se fizermos isso com suas opções. Após a tokenização, obtemos

\zap@space \iffullversion twoside, \fi\ifdraftversion draft, \fi 11pt \@empty

A definição de \zap@spaceé

% latex.ltx, line 7764:
\def\zap@space#1 #2{%
  #1%
  \ifx#2\@empty\else\expandafter\zap@space\fi
  #2}

Para a primeira chamada, #1está vazio, então obtemos

\zap@space\iffullversion twoside, \fi\ifdraftversion draft, \fi 11pt \@empty

Isso sai \iffulversion twoside,no fluxo de entrada e depois faz

\ifx\fi\ifdraftversion draft, \fi 11pt \@empty

Você consegue ver o que está errado? A condicional \fios compara \ifdraftversione os remove.

Se você usar \else\fi, a comparação será entre esses dois; você poderia usar \relax\fiou \whateverevenundefined\fi.

Neste ponto o desequilíbrio \fié claro. Na sua aplicação, o erro é descoberto posteriormente, mas isso deve ser suficiente para explicar que as condicionais nas opções de classe devem ser evitadas.

A propósito, isso funciona:

\newif\ifdraftversion \draftversionfalse
\newif\iffullversion  \fullversionfalse
\def\safetybelt{\empty}

\documentclass[%
  \safetybelt\iffullversion  twoside,\fi
  \safetybelt\ifdraftversion draft,\fi
  11pt
]{article}

Responder2

A "solução alternativa" usando \else\fiapenasparecetrabalhar. Suas opções são divididas entre vírgulas, então você tem as opções \iffullversion twoside,, \fi\ifdraftversion drafte \fi 11pt.

O seguinte códigoparecefuncionar conforme esperado (verificado apenas por experimento):

\documentclass[
  \iffullversion  twoside\fi, %works if the \fi here are
  \ifdraftversion draft\fi, % \else\fi instead
  11pt
]{article}

informação relacionada