В документации l3skip
предупреждают\dim_eval:n
Это [...] требует соответствующего завершения, если используется в задании в стиле TeX, поскольку это не ⟨внутренние размеры⟩.
Аналогичные предупреждения можно найти в описаниях для \skip_eval:n
и \muskip_eval:n
с ⟨внутренний клей⟩ и ⟨внутренний клей⟩ на месте ⟨внутренние размеры⟩.
Я довольно хорошо знаком с обработкой пропусков и размеров в TeX, но никогда раньше не сталкивался с выражениемвнутренние размеры. В TeXbook я не смог найти никакого объяснения этой фразы, кроме довольно технической грамматической записи в главе 24, которая, безусловно, содержит всю необходимую информацию, но не особо мне помогла.
Итак, что же такоевнутренние размеры? Каковы другие типы измерений? (Внешние измерения?) Каковы примеры различного поведения этих двух измерений (например, упомянутого в предупреждении выше)?
решение1
Сначала я расскажу об общей концепции TeX, а затем о том, почему она важна в документации этих expl3
функций.
Внутреннее измерение (или внутренний счет или что-то еще) — это то, что было проанализировано TeX и теперь сохранено в правильной форме. Таким образом, TeX «знает», что внутреннее измерениеявляетсядопустимое измерение, и не должно «искать» какой-либо дополнительный материал. В отличие от внешнего измерения (и т. д.) — это то, что состоит из дискретных токенов и должно быть повторно проанализировано TeX для использования. Таким образом, когда мыписать 12.0pt
, мы даемвнешнийпредставление (TeX должен был бы проанализировать его, чтобы узнать, является ли он допустимым измерением), но после
\newdimen\mydimen
\mydimen=12pt %
Я могу использовать \mydimen
и TeX делает этонетнужно что-то разобрать: \mydimen
содержит внутреннее измерение.
Почему это важно? Все дело в правилах разбора TeX, в частности, в том, что TeX допускает необязательный завершающий пробел после измерений, целых чисел,и т. д., и что еще важнее, при внешнем представлении TeX не прекращает парсинг, пока не найдет что-то, что не «подходит». Например
\def\foo{123}
\newcount\fooint
\fooint=123 %
\newcount\testint
%%%
\testint=\foo 456 %
\showthe\testint
\testint=\fooint 456 %
\showthe\testint
вы увидите, что первый случай дает неправильный результат: у нас есть макрос, который просто расширяется до 123
, и TeX продолжает искать целое число, пока мы не наткнемся на необязательный пробел. Напротив, с внутренним представлением счетчика нет вопроса о разборе:\fooint
является 123
.
Ключевым моментом является то, что внутреннее представление «безопаснее» в использовании (плюс быстрее): никогда не возникает вопроса о том, где оно заканчивается.
Как это связано с expl3
? Что-то вроде \dim_eval:n
используется для того, чтобы взять выражение и превратить его в измерение. Однако, оказывается удобным разрешить, чтобы это также было просто набрано, сохранено путем расширения в макросе ( tl
),и т. д.Для этого нам нужно сделать так, чтобы результаты оценки быливнешнийпредставление, а невнутреннийодин. Это означает, что эти функции ведут себя так, как будто сохраняют значение в виде макроса: вам нужно следить за завершением.
Для всех 'чистых' expl3
применений это не проблема, так как у нас есть правильное завершение в нужных местах. Но если вы смешиваете использование этих функций с более классическим программированием TeX, вам нужно знать, как они будут себя вести.ответ от egregЭто хорошо видно.
Для тех, кто хочет узнать подробности TeX, \dim_eval:n
в примитивных терминах
\the\dimexpr #1\relax
в то время как если мы хотим получить внутреннее представление, нам нужно только
\dimexpr #1\relax
Однако его нельзя использовать при наборе текста или (успешно) внутри x
расширения -type, поэтому он не подходит для нужного нам определения.
решение2
Рассмотрим следующий пример.
\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\cs_set_eq:NN \dimeval \dim_eval:n
\ExplSyntaxOff
\newlength{\mylen}
\begin{document}
Do an assignment \mylen=\dimeval{3pt+1cm} plus something else.
\end{document}
что вызывает ошибку
! Missing number, treated as zero.
<to be read again>
s
l.12 ...assignment \mylen=\dimeval{3pt+1cm} plus s
omething else.
Именно об этом и идет речь в interface3
.
An <internal dimension>
— это любой \dimen
регистр или любой внутренний регистр, который хранит (жесткую) длину, например \parindent
, ; с расширениями e-TeX также \dimexpr
является экземпляром <internal dimension>
.
Другим важным фактом является то, что \newlength
выделяет \skip
регистр, поэтому TeX будет ожидать спецификаций plus
или minus
; этого не происходит при \setlength
использовании , поскольку макрос обеспечивает подходящее \relax
завершение.