我经常会sty
因为诸如变量名之类的简单问题而遇到不同文件之间的冲突。
最新的一个是proof.sty
(允许将证明自动移动到附录)和llncs.sty
(许多会议和期刊都要求确保外观和感觉一致)之间,它们都定义了一个名为的变量exercise
,因此产生冲突。
一种解决方案是期望每个sty
文件在其所有变量前面加上所实现库的名称,但这不是一个干净的解决方案。LaTeX 中是否有任何方法可以提供一些封装,或者至少定义一些局部变量,因为我认为这是现代编程语言中的用法?
答案1
(La)TeX 中没有封装,但即使有封装,由于作者命令的性质,它仍然可能存在问题。我的意思是什么?由于 (La)TeX 本质上是一种标记语言,如果您要开发一个包,例如为标记练习提供宏,那么在用户级别,您很可能希望提供:
\begin{exercise}
…
\end{exercise}
命令类型而不是\begin{MXexercise}
。但是为了尽量减少与其他包的问题和冲突,包和类作者确实使用了前缀和符号@
。一个很好的例子是 LaTeX3 约定,尽管在我看来,这种极端保守的方法可能会损害代码的可读性。
TeX 还具有分组机制,您可以在其中本地定义宏和其他命令。组之间的任何内容都是本地定义的。例如:
\def\acommand{43}
\bgroup
\def\acommand{42}
In group \acommand
\egroup
Outside group \acommand
以上代码将在组外打印 43,但在组内打印 42。\bgroup
和\egroup
只是 的简写形式{}
。您可以根据需要嵌套任意数量的组,效果相同。
我认为,好的做法是让软件包专注于单一目的并尽量减少作者命令。在内部,它们可以使用前缀或后缀来避免冲突。
对于类作者来说,类本身应该加载一组推荐的软件包以供其常用使用,并且类需要应用任何补丁。有些类走向另一个极端(例如 KOMA 和 Memoir),定义自己的软件包或将功能合并到主代码中。
我理解你的痛苦,因为我已经是 的用户hyperref
很长时间了。但是,冲突可以通过以下方式轻松绕过:
\usepackage{packageA}
\let\oldcommand\culprit % command from package A causing errors in package B.
\let\culprit\undefined
\usepackage{packageB}
如果您想使用\culprit
某处,请做相反的操作。
答案2
这savesym
包裹提供了一种将处理多重定义宏的责任转嫁给用户的方法。目前,这可能是您处理不周全的宏命名的最佳选择。
进入幻想领域,软件包作者采用以下策略并不难:
放全部它们的宏在包“命名空间”中。我赞成这种约定,我在我的ytableau 包,使用命名空间作为后缀而不是前缀,因此宏可以按字母顺序索引。
\ytableaushort@YT
等等。提供所有公开可用的宏名称列表,格式为
\ThisPackageDefinesMacros{ytableaushort, ydiagram, ytableausetup}
和\ThisPackageDefinesEnvironments{ytableau}
。或者,\newcommand
和\newenvironment
宏可以用执行此操作的软件包版本替换(例如\RequirePackage
软件包应该使用的宏而不是\usepackage
)。这些只会将其内容转储到一些将被解析的内部列表宏中...然后,包的用户可以使用诸如
\UsingMacros[ytableau]{ytableaushort, ydiagram}
或 之类的命令来显示他们想要的宏(可能是所有宏)。(为了方便起见,第一个参数应默认为最后加载的包。为了进一步方便起见,如果您不想挑选,\UsingEnvironments[ytableau]{ytableau}
可能应该有类似的内容。)\UsingAllMacros[ytableau]
这些宏应该是 LaTeX 本身提供的标准工具,或者至少是独立于其他包的包提供的标准工具(即每个人都不应该尝试定义自己的“使用”宏)。我花了十分钟来编写这样一个东西,但当然,除非大多数包都将其编辑到代码中,否则它将毫无用处。
这也可以回答我们可以轻松找到包中定义的所有命令、标记等等吗?,我认为值得好好回答一下。TeX 是一种过时的编程语言,但这并不意味着它不能用来提供一些现代的便利。
答案3
有最简单的名字包装,叫什么块结构:
\def\foo{\begingroup{%
\def\bar{bar}\endgroup}
其中\bar
仅在 的分组内可用\foo
,即词汇范围\foo
在调用.的组内
(带参数,例如:\def\foo#1{{\def\bar##1{##1}\bar{#1}}}
)
我不知道为什么在 TeX 中不经常使用块;这可能有原因。