在写入 .cls 文件时 \myname 和 \my@name 之间有什么区别?

在写入 .cls 文件时 \myname 和 \my@name 之间有什么区别?

在编写 .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

相关内容