Errores al usar condicionales en el argumento opcional de la clase de documento

Errores al usar condicionales en el argumento opcional de la clase de documento

He encontrado una interacción extraña entre los parámetros opcionales \documentclassy \iflas declaraciones. Por alguna razón, el código se compila si hay una \elsedeclaración, incluso si no tiene contenido:

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

Si bien esta solución no es particularmente onerosa, no he podido aislar el error real involucrado ni resolver lo que he entendido mal. ¿Hay alguna razón por la que mi intuición me lleva a utilizar una sintaxis no válida y, de ser así, dónde/qué/por qué?

Respuesta1

El \documentclasscomando hace algo de contabilidad y luego llama

\@fileswithoptions\@clsextension

A estas alturas aún no se han analizado las opciones y el argumento. La macro \@fileswithoptionsabsorbe su argumento y luego mira si [sigue. Después de esta decisión, ejecuta

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

que busca un argumento opcional adicional; al final llegamos a

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

porque no especifica el argumento opcional final. Esta macro hace

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

entonces deberíamos preguntarnos qué pasa si lo hacemos con sus opciones. Después de la tokenización, obtenemos

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

La definición de \zap@spacees

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

Para la primera llamada, #1está vacío, por lo que obtenemos

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

Esto sale \iffulversion twoside,en el flujo de entrada y luego lo hace.

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

¿Puedes ver lo que sale mal? El condicional \filos compara \ifdraftversiony los elimina.

Si usa \else\fi, entonces la comparación es entre estos dos; podrías usar \relax\fio \whateverevenundefined\fi.

En este punto el desequilibrio \fies claro. En su aplicación, el error se descubre más tarde, pero esto debería ser suficiente para explicar que se deben evitar los condicionales en las opciones de clase.

Esto funciona, por cierto:

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

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

Respuesta2

La "solución alternativa" usando \else\fisóloparecetrabajar. Sus opciones están divididas entre comas, por lo que tiene las opciones \iffullversion twoside, \fi\ifdraftversion drafty \fi 11pt.

El siguiente códigoparecepara funcionar como se esperaba (solo verificado mediante experimento):

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

información relacionada