3

In many programming languages, e.g. Python, to use a function we should explicitly declare the function name and the package containing that function. However, in Latex when we use \usepackage{<package-name>}, it imports all the commands(macros) from the package, so we cannot control which commands are imported, thus, we usually end up with the error: multiple definitions for a commands.

Is there a way to explicitly import a certain command instead of using all commands from the package?

Leonard Neon
  • 139
  • 4
  • 4
    Only by copy&paste. But normally there aren't so many clashes, if you get them often it indicates an overloaded preamble. – Ulrike Fischer Dec 28 '22 at 08:48
  • 1
    Many times, macros are dependent on other macros which are defined by the package. So you'd also need to somehow figure out what those macros are load them as well. If you just need a single macro with no dependencies, you can do {\usepackage{package} \global\let\macro=\macro}. Alternatively, if what you really want to do is save the definition of a macro before you load a package you can try \let\oldmacro=\macro \usepackage{package} \let\macro=\oldmacro. – Slurp Dec 28 '22 at 08:53
  • 7
    @Slurp never load a package in a group unless you know exactly what the package does and that this doesn't harm. Don't forget that a package can also setup global definitions and load other packages and if you put a group around it can give a hell of a mess. And don't use \let with robust commands, this can led to loops, use \NewCommandCopy. – Ulrike Fischer Dec 28 '22 at 09:06
  • 2
    also you can not load a single character from a font so you have to load the entire font whatever you do, but if "usually end up with the error: multiple definitions " that indicates user error or at least unusual use, so perhaps you should instead ask about an example of that. – David Carlisle Dec 28 '22 at 10:03
  • 1
    https://tex.stackexchange.com/questions/14386/importing-a-single-symbol-from-a-different-font – David Carlisle Dec 28 '22 at 10:05
  • If you have control over the package source code, e.g. if it is a custom package, you can use the catchfilebetweentags package to load only certain parts of the code. – samcarter_is_at_topanswers.xyz Dec 28 '22 at 13:53

2 Answers2

3

An answer from the perspective of someone who programs in both Python and TeX.

In Python, by default if a package does something like

def f():
    pass

def g(): f()

the functions f and g are defined in the "global" namespace, but it's not "true global", rather it's just the "module global", as such it does not interfere with the code that imports it.

If you do from my_module import g, then when g is called and it tries to call f, the name f is looked up in the globals of the module my_module, which does not require the f itself to be available in the globals of the importing code.

In TeX however, by default everything are in true global scope; furthermore, by default all the names are looked up in the global scope.

For an analog, Python has a "true global" namely builtins module, variables of this module is available to every modules. In that case the TeX equivalent of the snippet above would be

import builtins

def f(): pass builtins.f=f

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

In this case, even if you copy the g to some other name, for it to work correctly the global function named f must be the f of this module.

Which explains the difficulty when you try to import two different modules which both has functions named f and g.


From the TeX perspective, the equivalent of the above would be

\cs_new_protected:Npn \__mymodule_f: {
}

\cs_new_protected:Npn __mymodule_g: { __mymodule_f: }

then an \usepackage{mymodule} would make the names available as \__mymodule_f: and \__mymodule_g: respectively, and the equivalent of from mymodule import f would be the above plus \cs_new_eq:NN \f \__mymodule_f:.

Needless to say, most user-level modules are not implemented this way because the typical user have no idea what \cs_new_eq:NN is.

(although to be fair it's still possible to make a command namely \importFromMymodule \f to explicitly define the \f etc. and \importAllFromMymodule etc. but usually nobody needs these things anyway)


Nevertheless, if you really insist, most of the time the "command juggling" can be done by

\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}

For "nicely implemented" packages this should mostly work.

In the rare few cases that it doesn't, restoring all the names that the hidden package is needed before calling the functions of the old package.

user202729
  • 7,143
2

Suppose, by way of example, that you just want to import \qty from siunitx. The definition is easy to find, namely

   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   }

(line numbers added for reference). Can you think to just copy this definition in your file, maybe changing the name, and \qty (or the command name you chose) to work as expected?

Sorry, no. This definition is just the iceberg tip and it depends on pretty much all the 8243 lines that precede it. Never compare TeX with other programming languages: it has no concept of a namespace, for instance, although good package programming emulates it.

I believe that when you load a particular function from a Python package, Python itself is able to guess what auxiliary functions from the package it has to load, but this is essentially impossible in TeX.

If you find name clashes when loading two packages, it may be possible to solve the issue by doing some renaming and juggling. But this is not always possible. If you like a feature from algorithm2e that's not present in algpseudocode, say, it's quite hard (if ever possible) to mix them; one can try reimplementing the feature in algpseudocode, using this package's features and infrastructure.

By the way, it's very possible that if you look in a package for the definition of some command you'll not find it as such.

egreg
  • 1,121,712