NB: In this post, by fully qualified names I mean names like
SomePackage`y, which include their complete context information, and they are to be contrasted with unqualified names, such as
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
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
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
Needs["foo`"]; hello (* I'm here! *)
(The same thing happens if one uses
Get instead of
If, on the other hand, I use
End instead of
EndPackage, like this:
(* foo.m *) Begin["foo`"]; hello := Print["I'm here!"]; End;
...then at least, importing this code with
hello can be accessed only as
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