在编写 .cls 文件时,\myname
和有什么区别?它们等效吗? 如果需要发布一个最小示例,请告诉我。\my@name
编辑:
让我更清楚地提出我的问题:
以下两行有什么区别?
\def\myname#1{\gdef\@myname{#1}}
\newcommand*{\myname}[1]{\gdef\my@myname{#1}}
我对这些线条有点困惑。我确切地知道\myname
和之间的区别\@myname
,但是我不知道\myname
和\my@name
之间的区别.cls
文件。
答案1
\my@name
并且\myname
位于 TeX 的不同“命名空间”中。
的文件和文件中的catcode@
不同。在或文件中是一个字母(catcode 11);但在 文件中是一个“其他字符” (catcode 12)。(参见 TeXbook,第 8 章).tex
.cls
@
.cls
.sty
.tex
因此,您的类文件的用户不能\my@name
直接在.tex
文件中使用,它受到保护;但他/她可以\myname
自由使用。
@
带like 的宏\my@name
用于内部宏,一般用户不能访问;不带@
like 的宏\myname
用于接口宏,一般用户才能使用。
一个例子(很愚蠢,仅用于演示):
% setname.sty
\providecommand\setname@name{}
\newcommand\setname[1]{%
\renewcommand\setname@name{#1}}
\newcommand\getnameinparens{%
(\setname@name)}
\endinput
包用户可以使用\setname
来设置名称并\getnameinparens
获取(名称)。但是,\setname@name
除非\makeatletter
使用 ,否则他们无法访问 。
答案2
不同之处在于用户不太可能重新定义和破坏,\my@name
因为控制序列中的@通常不允许出现在常规 TeX 文件中。
这就是使用 @ 的目的;它将控制序列标记为“内部”而不是供最终用户使用。用户不应期望 @ 宏在不同版本之间保持不变或以相同的方式工作。
此命名空间不是自动的;如果两个包都定义了,则\my@name
其中一个将覆盖另一个。这就是为什么最好选择一个(希望是相对的)唯一的“命名空间”,并在内部宏前加上 @。因此,如果您的包名为baz
,则请调用您的内部宏\baz@foo
,等等。
我上面说“通常”是因为 LaTeX 使用能在其 TeX 文件中放入\makeatletter
...并使用 @ 作为字母。但这样做的用户知道自己在做什么和/或承担这样做的风险。\makeatother
答案3
回答我们的更新问题:
以下两行有什么区别?
\def\myname#1{\gdef\@myname{#1}} \newcommand*{\myname}[1]{\gdef\my@myname{#1}}
看,\def
是一个 TeX原始即未使用其他宏定义但执行某个预定义硬编码函数的宏(然而名称可以将原语重新定义为用户宏)。这里将\def
的定义设置\myname
为\gdef\@myname{#1}
。原始是宏像一个公理到证明。证明依赖于其他证明,而其他证明又依赖于其他证明,最终这些证明又依赖于一些公理。宏也是一样,它们被定义为其他宏(实际上是其他标记),这些宏可以再次定义为其他宏,最终以原语结束。
TeX 允许您访问较低级别,而 LaTeX 为您提供简洁的用户界面。 的一个缺点\def
是它只是设置宏的定义,即它定义或重新定义它而不检查它是否之前已经定义过。如果所有或大多数 LaTeX 宏都是使用 定义的\def
,则包可能会覆盖其他包的宏而不会发出警告,这会很快导致混乱。调试这种情况将非常困难。
因此,LaTeX 会\newcommand
检查宏是否已定义,如果已定义,则会触发错误。它还允许您简单地将参数数量作为数字(例如[3]
)给出,而不是写成 eg #1#2#3
。在完成所有检查(还有更多检查)后,它会\def
在内部使用它来最终定义宏。
因此,\newcommand
更安全但速度较慢(但这并不重要),而\def
为您提供了定义参数列表。例如,你可以说:
\def\mymacro(#1,#2){...}
定义一个宏,等待(<something>,<something more>)
并返回这两个值作为#1
和#2
。如果模式不匹配,则会触发错误。可选参数的[ ]
实现非常相似。如果所有宏都使用 定义,那么像 TikZ 中使用的更复杂的语法将是不可能的\newcommand
。