Я столкнулся со странным взаимодействием между необязательными параметрами в операторах \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}