0

Below is a toy package that illustrates what I mean by "namespace leaks".

(* /tmp/bug_or_feature.m *)

Begin["bugOrFeature`"];

ClearAll[foo, makeFoo];

makeFoo[] := Module[{foo},
  foo[] := "BUG OR FEATURE?";
  foo
];

foo = makeFoo[]; (*!*)

End[];

The function bugOrFeature`makeFoo creates a function inside a Module's lexical scope, and returns it. This function (i.e. bugOrFeature`makeFoo) is used to create the function bugOrFeature`foo.

One can Get this package repeatedly, without affecting the Global` namespace:

Get["/tmp/bug_or_feature.m"]; Names["Global`*"]
(* {} *)

Get["/tmp/bug_or_feature.m"]; Names["Global`*"]
(* {} *)

This stops being the case, however, if one introduces the symbol foo in the Global` namespace:

Global`foo = 0; Names["Global`*"]
(* {foo} *)

Get["/tmp/bug_or_feature.m"]; Names["Global`*"]
(* {foo, foo$551} *)

Note that now, after evaluating the Get expression, there's an additional item in the Global` namespace, namely foo$551.

What's really troubling, however, is that Global`foo got overwritten during the last evaluation of the Get expression:

Global`foo
(* foo$551 *)

(The line marked with (*!*) in the code for /tmp/bug_or_feature.m is the culprit, AFAICT.)

What can one do to prevent code in one namespace from inadvertently overwritting symbols in another namespace?

Also,

Is the behavior illustrated above a bug or a feature?

kjo
  • 11,717
  • 1
  • 30
  • 89
  • 3
    So the answer is, do what is the standard way to write a package. – Kuba Mar 09 '17 at 20:04
  • related: 75333 and 43629 – Kuba Mar 09 '17 at 20:07