0
$\begingroup$

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?

$\endgroup$
  • 4
    $\begingroup$ Look at BeginPackage $\endgroup$ – Carl Woll Mar 9 '17 at 19:57
  • 1
    $\begingroup$ + Begin["`Private`"] to create Package`Private`foo when the Global`foo is screened by BeginPackage. $\endgroup$ – Kuba Mar 9 '17 at 20:04
  • 3
    $\begingroup$ So the answer is, do what is the standard way to write a package. $\endgroup$ – Kuba Mar 9 '17 at 20:04
  • $\begingroup$ related: 75333 and 43629 $\endgroup$ – Kuba Mar 9 '17 at 20:07
2
$\begingroup$

Try something like:

System`Private`NewContextPath[{"System`"}]

BeginPackage["bugOrFeature`"]

yourSymbol::usage

Begin["`Private`"]

yourImplementation

End[]

EndPackage[]

System`Private`RestoreContextPath[]
$\endgroup$
  • 3
    $\begingroup$ I'm glad that many of undocumented functions' examples are shown lately but a word of explanation would be nice :) $\endgroup$ – Kuba Mar 9 '17 at 21:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.