我想知道是否有可能将 catcode 更改为仅在宏定义中使用。在这种情况下,我需要将一个宏定义为\example#1#2
,将另一个宏定义为\example^#1#2
。如果省略 ,则下面的代码可以正常工作\test{\example^25}
。提前致谢(请仅提供简单的答案)。
\catcode`^=11
\def\example^#1#2{%
this is \#1: #1. this is \#2: #2}
\catcode`^=7
\def\test#1{%
\catcode`^=11
#1
\catcode`^=7}
\test{\example^25}
\bye
答案1
这主要取决于\example
应该做什么。标准方法是延迟读取参数:如果你期望它的参数中\test
可以同时包含\example
和\example^
,则将其定义为
\def\test{\begingroup\catcode`^=11 \dotest}
\def\dotest#1{#1\endgroup}
所以类别代码发生了变化前参数被抓取,catcode 被冻结。当然,这有一个限制,即\test
它本身不能用作另一个命令的参数。
另一种策略是只使用一个\example
宏:
\def\example{\futurelet\next\doexample}
\def\doexample{\ifx^\next\let\next\examplehat
\else\let\next\examplenohat\fi\next}
\def\examplehat^#1#2{this is \#1: #1. this is \#2: #2}
\def\examplenohat#1#2{No hat (#1,#2)}
类别代码无变化。
完整代码:
\def\example{\futurelet\next\doexample}
\def\doexample{\ifx^\next\let\next\examplehat
\else\let\next\examplenohat\fi\next}
\def\examplehat^#1#2{this is \#1: #1. this is \#2: #2}
\def\examplenohat#1#2{No hat (#1,#2)}
\example25
\example^25
\def\test#1{#1}
\test{\example25}
\test{\example^25}
\bye
我们\scantokens
仍然需要延迟抓取参数,否则它将在类别代码更改和形成控制序列时被标记化。
\begingroup
\catcode`^=11
\gdef\example^#1#2{this is \#1: #1. this is \#2: #2}
\endgroup
\def\example#1#2{No hat (#1,#2)}
\def\test{\begingroup\catcode`^=11 \dotest}
\def\dotest#1{\scantokens{#1\noexpand}\endgroup}
X\test{\example25}X
X\test{\example^25}X
\bye