Ошибки при использовании условных операторов в необязательном аргументе класса документа

Ошибки при использовании условных операторов в необязательном аргументе класса документа

Я столкнулся со странным взаимодействием между необязательными параметрами в операторах \documentclassи \if. По какой-то причине код компилируется, если есть оператор \else, даже если у него нет содержимого:

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

Хотя этот обходной путь не особенно обременителен, мне не удалось выделить фактическую ошибку или понять, что я неправильно понял. Есть ли какая-то причина, по которой моя интуиция заставляет меня использовать недопустимый синтаксис, и если да, то где/что/почему?

решение1

Команда \documentclassвыполняет некоторую бухгалтерию, затем вызывает

\@fileswithoptions\@clsextension

На этом этапе опции и аргумент еще не рассматривались. Макрос \@fileswithoptionsпоглощает свой аргумент и затем смотрит [, следует ли. После этого решения он выполняет

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

который ищет еще один необязательный аргумент; в конце концов мы приходим к

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

потому что вы не указали завершающий необязательный аргумент. Этот макрос делает

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

поэтому мы должны спросить, что произойдет, если мы сделаем это с вашими вариантами. После токенизации мы получаем

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

Определение \zap@spaceесть

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

Для первого вызова #1пусто, поэтому получаем

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

Это оставляет \iffulversion twoside,входной поток и затем делает

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

Видите, что не так? Условное предложение сравнивает \fiих \ifdraftversionи удаляет.

Если вы используете \else\fi, то сравнение будет между этими двумя; вы можете использовать \relax\fiили \whateverevenundefined\fi.

На этом этапе несбалансированность \fiочевидна. В вашем приложении ошибка обнаруживается позже, но этого должно быть достаточно, чтобы объяснить, что условных операторов в опциях класса следует избегать.

Кстати, это работает:

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

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

решение2

«Обходной путь» с использованием \else\fiтолькокажетсяработать. Ваши варианты разделены запятыми, поэтому у вас есть варианты \iffullversion twoside, \fi\ifdraftversion draft, и \fi 11pt.

Следующий кодкажетсячтобы работать так, как и ожидалось (проверено только экспериментом):

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

Связанный контент