может кто-нибудь объяснить futureletв пределахвыравнивание-сред?
Пример:
Команда \A должна возвращать «A», если следующий символ — {, «B», если это &, и «C» в любом другом случае.
\gdef\A{\futurelet\thesymbol\B}
\gdef\B#1{\ifx\bgroup\thesymbol A\else\ifx&\thesymbol B\else C\fi\fi}
а в случае обычного текста или встроенной математики это работает вполне нормально:
\A{a},\A&,\A a % -> "A,B,C"
$\A{a}$,$\A&$,$\A a$ % -> "A,B,C"
нов тот момент, когда я использую его в среде align* (amsmath), возникает ошибка «Incomplete \ifx»:
\begin{align*} \A{a},\A&,\A a \end{align*}% --> error.
Кто-нибудь может мне объяснить? Спасибо!
Крис
PS: Есть еще кое-что о futurelet в среде align, чего я не понимаю: если мы определим
\gdef\A{\futurelet\thesymbol\alpha}
\gdef\D#1{\detokenize{#1}}
затем
\begin{align*}
\D&,\A a % -> "&,alpha a" (okay)
\A a,\D{&} % -> "alpha a,&" (okay)
\A a,\D& % -> error: "Argument of D has an extra }." (???)
\end{align*}
решение1
\gdef\B#1{\ifx\bgroup\thesymbol A\else\ifx&\thesymbol B\else C\fi\fi}
когда TeX видит , &
он заменяет остальную часть шаблона на , \halign
как указано в регистре latex c
r
и т. д., поэтому \ifx
будет сравнивать первые два токена шаблона (вероятно \unskip
, и \hfil
затем ячейка (а значит, и группа) закончатся), что-то пойдет не так.
Если вы хотите спрятаться &
при создании группы до фьючерлета и завершении ее после теста, вам нужно
{\ifnum0=`}
...
\ifnum0=`{\fi}
форма, которая появляется во всем табличном коде.
Это дает A, B, C, что, я думаю, и является желаемым результатом.
\documentclass{article}
\usepackage{amsmath}
\gdef\A{{\ifnum0=`}\fi\futurelet\thesymbol\B}
\gdef\B#1{\ifx\bgroup\thesymbol A\else\ifx&\thesymbol B\else C\fi\fi \ifnum0=`{\fi}}
\begin{document}
\begin{align*} \A{a},\A&,\A a \end{align*}
\end{document}
Для вашего второго примера обратите внимание, что &
группа заканчивается, поэтому
a,\D&
похоже {\D}
и оба выдают одну и ту же ошибку:
! Argument of \D has an extra }.
<inserted text>
\par
l.15 {\D}
Там не совсем понятно, что именно нужно исправить, так как не совсем понятно, что именно вы хотите {\D}
сделать.
решение2
Я не могу соревноваться с Дэвидом в понимании кода TeX, поэтому я не буду пытаться исправить ваши макросы (хотя, по моему мнению, то, что вы делаете, в корне неразумно). Однако его комментарий о "когда TeX видит " &
можно расширить следующим образом. При сканировании выравнивания TeX действует способом, который несколько расходится с ментальной моделью его выполнения, которую большинство пользователей (даже опытных и знающих пользователей) имеют. А именно, мыпредставлять себечто TeX всегда делает одну из трех вещей:
Сканирование входных данных с целью токенизации символов для предоставления пищи для «рта» макроанализатора;
Расширение макросов;
Выполнение нерасширяемых токенов: либо директивы программирования, такие как
\def
или\hbox
, либо прямые команды набора текста, такие как символы.
В рамках этой модели все ожидают, что внутри выравнивания (примитивы TeX \halign
или \valign
) символ табуляции &
выполняет свое действие в пункте 3: выполнение. Однако это не совсем так; на самом деле TeX «замечает» символы табуляции в пункте 1! Если TeXкогда-либо читаетамперсанд (или эквивалентная категория символов) немедленно завершит текущую ячейку, закроет группу, вставит « v
часть» шаблона и т. д.
(Редактировать:Я просто бегло просматривал errorlog.pdf
(то есть texdoc errorlog
) и нашел соответствующий комментарий из сеанса отладки от 18 марта 1978 года:
Сделать так, чтобы get next рутина перехватывала
&
и\cr
токены. Я думал, что могу просто вставить&
и\cr
вbig_switch
[т. е. в желудок TeX, а не в глаза]; это была большая ошибка.
(Это интересный частичный взгляд на то, что побудило Кнута сделать вышеуказанный, на первый взгляд странный, выбор поведения этих токенов массива, а также подтверждение того, что это действительно так.)
Исключением, конечно, является случай, когда TeX находится внутри незавершенной группы фигурных скобок (и это должны быть реальные символы фигурных скобок, а не неявные или \begingroup
, которые начинают эту группу), что приводит к конструкции Дэвида {\ifnum0=
}`, которая расширяемо эквивалентна открытой фигурной скобке без фактического создания несбалансированных фигурных скобок внутри определения макроса, где она может быть размещена.
Результатом этого странного правила разбора является то, что нужно быть очень осторожным с тем, что считывается макросом в ячейке таблицы или заключено в окружение. Макросы, такие как ваш, которые фактически считывают свой аргумент через присваивание, а не через разбор макроаргумента, еще более ненадежны, поскольку без необходимых закрывающих скобок табуляция, которая могла бы быть прочитана,нетбыть защищены. Совместимые с таблицами среды включают эту \ifnum
штуку, чтобы защитить любые символы табуляции, которые могут встречаться внутри; более простые будут разделены по ячейкам и, таким образом, вероятно, потерпят неудачу.