
У меня есть следующий простой Tex-код:
\def\xx{ABC}
\def\temp #1 {\def\tempii{#1}}
\temp\xx a b c
\tempii\tempii
Я ожидаю увидеть следующий результат:
a b c ABCABC
Но на самом деле я вижу это:
b c ABCaABCa
Почему «а» попало в определение \tempii?
решение1
Я все еще думаю, почему это так, но эта доработка (включающая в себя \xx
) дает вам то, что вы хотите.
Я думаю, ответ в том, что при использовании \temp\xx a b c
пробел после \xx
с точки зрения анализатора TeX вообще не является пробелом, а просто обозначает конец имени макроса \xx
. Например, если вы просто поместите \xx A
строку отдельно, вы увидите, что она будет напечатана как ABCA
без пробела. Таким образом, анализатор всасывает завершающую "A", как связанную с \xx
. Можно также использовать \temp\xx{} a b c
, как способ сообщить анализатору, что пробел является разделителем, а не просто следующим символом после \xx
.
\documentclass{article}
\begin{document}
\def\xx{ABC}
\def\temp #1 {\def\tempii{#1}}
\temp{\xx} a b c
\tempii\tempii
\end{document}
решение2
Для ясности я буду обозначать пробелы как •
, так как они очень важны в обсуждении; пробелы в следующих примерах кода следует игнорировать.
Текст параметра \temp
:
#1•
в то время как текст замены
\def\tempii{#1}
Ваш звонок \temp
-
\temp\xx a•b•c•\tempii\tempii
Обратите внимание, что после этого \xx
идет пробел, который служит только для разграничения макроса.нетпробел: это ничто, потому что TeX всегда игнорирует пробелы, следующие за controlслова(не контрольсимволы). Пробел после этого c
берется из конца строки в вашем коде.
Следующие токены \temp
сканируются (без расширения) для поиска совпадения с текстом параметра, где аргумент отделен пробелом, поэтому #1
заканчивается, \xx a
а следующим состоянием входного потока является
\def\tempii{\xx a}b•c•\tempii\tempii
Теперь TeX выполняет определение и удаляет его из входного потока:
b•c•\tempii\tempii
и часть b•c•
передается на этап набора. После расширения двух копий \tempii
это эквивалентно набору
b•c•\xx a\xx a
или
b•c•ABCaABCa
именно это вы и получили.
Если бы вы использовали \?
вместо этого \xx
последние две строки были бы преобразованы в
\temp\?•a•b•c•\tempii\tempii
потому что \?
это управляющий символ и TeX не игнорирует пробелы после них. В этом случае результат будет
a•b•c•ABCABC
Обратите внимание, что
\expandafter\temp\xx a•b•c
\tempii\tempii
приведет к тому же результату, потому что после действия \expandafter
TeX будет представлено
\temp ABCa•b•c
(то же соглашение для пробелов, что и раньше, конечно). Вы получите тот же результат, что и with \?
вместо \xx
with
\expandafter\temp\expandafter\xx\space a•b•c
потому что тогда TeX будет представлен
\temp\xx•a•b•c
Действительно, пробелы после контрольных слов игнорируются только в процессе токенизации.