有人可以向我解释为什么在这个例子中\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
数学移位。|