Latex 的包,如何导入特定的命令/宏而不是使用全部?

Latex 的包,如何导入特定的命令/宏而不是使用全部?

在许多编程语言中,例如 Python,要使用函数,我们应该明确声明函数名称包含该函数的包。然而,在 Latex 中,当我们使用时\usepackage{<package-name>},它会从包中导入所有命令(宏),因此我们无法控制导入哪些命令,因此,我们通常会得到以下错误:一个命令的多个定义

有没有办法明确导入某个命令而不是使用包中的所有命令?

答案1

从使用 Python 和 TeX 编程的人的角度来回答。

在 Python 中,默认情况下,如果一个包执行类似以下操作

def f():
    pass

def g():
    f()

函数fg在“全局”命名空间中定义,但它不是“真正的全局”,而只是“模块全局”,因此它不会干扰导入它的代码。

如果您这样做from my_module import g,那么当g被调用并且它尝试调用时,会在模块的全局变量中查找f名称,而这并不要求它本身在导入代码的全局变量中可用。fmy_modulef

然而在 TeX 中,默认情况下所有内容都处于真正的全局范围内;此外,默认情况下所有名称都在全局范围内查找。

类似地,Python 有一个“真正的全局变量”,即builtins模块,该模块的变量可供每个模块使用。在这种情况下,上述代码片段的 TeX 等效代码将是

import builtins

def f():
    pass
builtins.f=f

def g():
    builtins.f()
builtins.g=g

在这种情况下,即使你将 复制g到其他名称,为了使其正常工作,命名的全局函数必须ff这个模块

这解释了当您尝试导入两个具有名为f和 的函数的不同模块时遇到的困难g


从 TeX 的角度来看,上面的内容等同于

\cs_new_protected:Npn \__mymodule_f: {
}

\cs_new_protected:Npn \__mymodule_g: {
    \__mymodule_f:
}

那么将使\usepackage{mymodule}名称分别可用作和\__mymodule_f:\__mymodule_g:并且的等效项from mymodule import f将是上面的加上\cs_new_eq:NN \f \__mymodule_f:

不用说,大多数用户级模块都不是这样实现的,因为典型的用户不知道这\cs_new_eq:NN是什么。

(虽然公平地说仍然可以创建一个命令,\importFromMymodule \f即明确定义\f等等\importAllFromMymodule。但通常没人需要这些东西)


尽管如此,如果你真的坚持的话,大多数时候“命令杂耍”可以通过

\usepackage{first package that defines f}
\NewCommandCopy \firstPackageF \f  % optional, if you want to call the first package's \f
\let \f \undefined  % delete the first package's \f so the second package can define it -- as explained above any "\g" in the first package might cease to work
\usepackage{second package that defines f}

对于“实施良好”的软件包来说,这应该基本可以起作用。

在极少数情况下,不需要这样做,在调用旧包的函数之前,需要恢复隐藏包的所有名称。

答案2

举例来说,假设你只想\qty从导入siunitx。定义很容易找到,即

   8244 \NewDocumentCommand \qty { O { } m > { \TrimSpaces } m }
   8245   {
   8246     \mode_leave_vertical:
   8247     \group_begin:
   8248       \siunitx_unit_options_apply:n {#3}
   8249       \keys_set:nn { siunitx } {#1}
   8250       \siunitx_quantity:nn {#2} {#3}
   8251     \group_end:
   8252   }

(添加了行号以供参考)。您是否可以考虑将此定义复制到文件中,也许更改名称,以及\qty(或您选择的命令名称)以按预期工作?

抱歉,不是。这个定义只是冰山一角,它依赖于它前面的几乎所有 8243 行。永远不要将 TeX 与其他编程语言进行比较:例如,它没有命名空间的概念,尽管好的包编程会模拟它。

我相信,当你从 Python 包中加载特定函数时,Python 本身能够猜测它必须从包中加载哪些辅助函数,但这在 TeX 中基本上是不可能的。

如果在加载两个包时发现名称冲突,则可以通过重命名和调整来解决问题。但这并不总是可行的。如果您喜欢 中的某个功能,但algorithm2e在 中却不存在algpseudocode,那么将它们混合起来就相当困难(如果可能的话);您可以尝试algpseudocode使用此包的功能和基础结构重新实现 中的该功能。

顺便说一句,如果你在包中寻找某个命令的定义,很可能你不会找到它。

相关内容