在组中设置 catcode

在组中设置 catcode

有人可以向我解释为什么在这个例子中\foo\bar不一样(在某种意义上):\ifx

\documentclass{article}
\begingroup
  \catcode`|=3\relax
  \gdef\abc{|}
\endgroup
\makeatletter
\newcommand\foobar{
  \begingroup
    \catcode`|=3\relax
    \def\abc{|}
    \@foobar
}
\newcommand\@foobar[1]{
  \xdef\foo{#1}
  \endgroup
}
\edef\bar{\abc}
\foobar{\abc}

\begin{document}
foo means ``\meaning\foo'' and bar means ``\meaning\bar'', but the ``meanings'' are
\ifx\foo\bar
  same
\else
  different
\fi
\end{document}

我之所以包括它,\@foobar是因为我在某处读到过,catcode在读取宏参数之前必须更改它(我认为它不适用于此处,但我不知道我在做什么)。

\abc(用 定义的)的全局定义\gdef是 | ,catcode 为 3。我希望\abc(用 定义的\def) 的局部定义也是 | ,catcode 为 3。在我的示例中,局部\abc是 | ,catcode 为 12。最终,我希望\foobar{\abc}扩展为 | ,catcode 为 3,而无需进行\abc全局定义。

答案1

问题就出在这里:

\newcommand\foobar{
  \begingroup
    \catcode`|=3\relax
    \def\abc{|}
    \@foobar
}

\def\abc{|}由 读取,\newcommand然后其 catcodes 被修复。\catcode|=3\relax is executed when the\foobar` 宏是用过的不是当定义

您可以使用以下命令:

\begingroup
\newcommand\foobar{}% to get the name check 
\catcode`\|=3\relax
\gdef\foobar{%
  \begingroup
    \catcode`\|=3\relax
    \def\abc{|}%
    \@foobar
}
\endgroup

这也为定义将 catcode 更改为 3。如果允许用户在参数中添加 catcode 3,则|只需使用。否则,您只需让其读取参数并直接在内部使用。那么您也不需要第二行,即内部的\|=3\relax` 行。\@foobar|\foobar\xdef\foo{#1}\foobar\catcode

此外,您应将 放在%{或结尾的行},否则源代码换行符将被视为插入文档中的空格。

答案2

我不知道你想实现什么。但是输入的 catcode 是在 TeX 时分配的第一次输入。读取 foobar 的定义主体时,| 的 catcode 为“other”,因此无论实际执行时的 catcode 值如何,您\foobar始终都会定义“ \abc= ” 。| with catcode other\foobar

如果您想要更改输入的 catcode,您可以通过将其写入外部文件然后重新输入或使用来实现\scantokens

答案3

它们是不同的,因为一个包含数学移位字符,另一个包含标点符号(catcodes 3 和 12),如果你排版,你就会看到这一点

foo \foo 1*2*3 \foo

bar \bar 1*2*3 \bar

您可以在本地将定义\abc为具有\catcode 3 |各种习语的,例如,这个习语在各处使用(通常用以~获得活动字符而不是),例如latex.ltx 中$的定义。\verb

\begingroup\lccode`$=`\|\lowercase{\endgroup\def\abc{$}}

定义为没有任何全局定义的\abc数学移位。|

相关内容