NB: In this post, by fully qualified names I mean names like Global`x
or SomePackage`y
, which include their complete context information, and they are to be contrasted with unqualified names, such as x
or ArcSin
. Also by the current namespace I mean the set of all unqualified names that Mathematica can interpret at any given time during a session. To "pollute the current namespace" means to add unwanted names to it.
For some time now I've been trying (unsuccessfully) to find a way to mimic in Mathematica Python's import
functionality.
Specifically, in Python one can gain access to symbols implemented in external modules, without adding those symbols to the current namespace.
For example, suppose some function hello
is defined in a module foo.py
. Then client code can access this function like this:
import foo
foo.hello()
The crucial point here is that, after import foo
, client code must still use the fully qualified name foo.hello
. In fact, the following variant bombs:
import foo
hello() # fails with "NameError: name 'hello' is not defined"
(Of course, Python also has a mechanism to add externally defined symbols to the current namespace, but that's another matter.)
My problem with Mathematica is that it seems to be extremely hard to use externally defined symbols without polluting the current namespace.
AFAICT, one cannot import symbols defined within a BeginPackage["..."]
/EndPackage[]
pair without polluting the current namespace. For example, if the file foo.m
contains this:
(* foo.m *)
BeginPackage["foo`"];
hello[] := Print["I'm here!"];
EndPackage[];
...then the following client code succeeds (assuming that foo.m
is in $Path
):
Needs["foo`"];
hello[]
(* I'm here! *)
(The same thing happens if one uses Get
instead of Needs
.)
If, on the other hand, I use Begin
/End
instead of BeginPackage["..."]
/EndPackage[]
, like this:
(* foo.m *)
Begin["foo`"];
hello[] := Print["I'm here!"];
End[];
...then at least, importing this code with Get
1, hello
can be accessed only as foo`hello
:
Get["/tmp/foo.m"];
hello[]
(* hello[] *)
foo`hello[]
(* I'm here! *)
I thought that this was the way achieve what I was after, but today I discovered that this scheme can lead to really bewildering bugs.
So I'm back to square 1.
Is there some other way to import externally defined symbols without making them accessible as unqualified names?
1 This doesn't work so well with Needs
.
Block $ContextPath
to query. Done ;) $\endgroup$