有没有办法仅在宏内设置 catcode?

有没有办法仅在宏内设置 catcode?

我想知道是否有可能将 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

在此处输入图片描述

相关内容