\typeout (或可扩展命令)可以扩展一次 - 或者具有可变的扩展级别?

\typeout (或可扩展命令)可以扩展一次 - 或者具有可变的扩展级别?

考虑以下 MWE:

\documentclass[12pt]{article}

\begin{document}

\def\aaa{something}
\typeout{=1==\aaa==}
\typeout{=1==\meaning\aaa==}
\typeout{}

\def\bbb{else \aaa, else}
\typeout{=2==\bbb==}
\typeout{=2==\meaning\bbb==}
\typeout{}

\def\ccc{third \bbb, level}
\typeout{=3==\ccc==}
\typeout{=3==\meaning\ccc==}
\typeout{}

\end{document}

它向终端输出以下内容:

=1==something==
=1==macro:->something==

=2==else something, else==
=2==macro:->else \aaa , else==

=3==third else something, else, level==
=3==macro:->third \bbb , level==

因此,我会考虑(在这种情况下)\meaning提供宏的未扩展内容(即“空”扩展级别);而\typeout进行“无限”扩展(直到没有更多标记需要扩展)。我注意到\typeout调用\write

$ texdef -t latex -c book -p titletoc typeout -f
\typeout is defined by (La)TeX.

\typeout:
macro:#1->\begingroup \set@display@protect \immediate \write \@unused {#1}\endgroup 

...因此这种“无限”扩张行为可能是由于\write

 

我最终想要的是一个可扩展的函数,它将接受数字的“扩展级别”,并且可以像这样调用:

# just a fake interface definition for testing
\def\expandlevel#1\nil#2\nil{
---#1---#2--
}

\edef\yyy{\expandlevel0\nil\ccc\nil}
\typeout{\yyy}

...例如:

  • 当我调用级别空扩展时 - 我输入时得到的是未扩展的内容(如\meaning);伪:
    * \typeout{==\expandlevel0\nil\ccc\nil==}
    ==第三 \bbb ,级别==
  • 当我调用单次扩展时 - 我得到的是(伪):
    * \typeout{==\expandlevel1\nil\ccc\nil==}
    ==第三否则\aaa,否则,级别==
  • 当我要求无限扩展 - 也就是 99 个级别:)- 我得到的结果与执行的结果相同\typeout;伪:
    * \typeout{==\expandlevel99\nil\ccc\nil==}
    ==第三其他某事,其他,级别==

不可扩展/受保护的令牌将保留(或显示为\inaccessible),如\typeout当前执行的那样。

在缺少像那样的“真正的”可扩展宏的情况下,是否有任何技巧可以诱导其\typeout以类似的方式运行(如果可能的话)?

答案1

这与 无关,\typeout除非它的参数由于 而完全展开\write,如您所指出的。您可以对 提出同样的问题\edef,答案是使用\expandafter\noexpand和的足够复杂的组合\unexpanded来强制每个标记展开所需的次数。例如:

*\def\a{\b} \def\b{\c} \def\c{c}

*\edef\x{\noexpand \a}

*\show\x 
> \x=macro:
->\a .
<*> \show\x

? 

*\edef\x{\expandafter\noexpand \a}

*\show\x
> \x=macro:
->\b .
<*> \show\x

? 

*\edef\x{\expandafter\expandafter\expandafter\noexpand \a}

*\show\x
> \x=macro:
->\c .
<*> \show\x

? 

*\edef\x{%
  \expandafter\expandafter\expandafter\expandafter
  \expandafter\expandafter\expandafter\noexpand\x}

*\show\x
> \x=macro:
->c.
<*> \show\x

s的数量\expandafter呈指数增长。如何编写单身的可扩展命令,扩展所需的次数被寻址这里。请注意,那里给出的答案仍然只是扩展标记,因此您不能将其应用于整个文本。可以使用\unexpanded\noexpand表示许多标记)和标记列表寄存器(在内部\edef,扩展到其内容,然后使结果暂时不扩展)来玩弄技巧,以实现类似的效果。

您可能想知道,如果允许对整个文本进行零次扩展和无限次扩展,为什么不允许一次或多次扩展?答案是,事实上,“无限”扩展是逐个标记进行的,没有扩展“整个文本”的概念。要进行零次扩展,TeX 只需转储给定的标记列表;\meaning显然进行一次扩展的方式是它实际上更改了\catcode输出的 s,使其不再可扩展:您看到的那些不是真正的宏。如果您将 in\scantokens与 change 结合使用,您可以自己实现相同的效果\catcode……除了\catcode不可扩展,因此您无法在\edef或中执行此操作。或者更确切地说,如果您这样做,您只会在结果中\write看到字符串“ ”。\catcode

无论如何,如果您想将“整个文本”扩展一定次数,则可能意味着以下三件事之一:

  1. 扩展第一个标记,然后扩展结果的第一个标记,依此类推,多次。

  2. 扩展第一个可扩展标记,然后扩展结果的第一个可扩展标记,依此类推,多次。

  3. 展开第一个可扩展标记;然后,在展开的文本中,以相同的方式展开所有内容 (n - 1) 次。完成后,移动到第一个“未触及”标记,并以此方式继续到文本末尾。(因此,扩展到整个文本的某个“深度”。)

规则 1 和 2 有不同的结果:

\def\a{a}
a\a

其中,扩展“once”会\a根据规则给出“a”或“aa”。规则 1 相对容易使用\multiexpandafter(来自另一个问题)和来实现。如果不将和嵌入到所有宏中\unexpanded,规则 2 可能就无法实现。规则 3 可能是图灵完备的。\expandafter\noexpand

相关内容