18
$\begingroup$

When dealing with namespaces in Mathematica (BeginPackage, $ContextPath ...) one is unavoidably confronted with the problem of shadowing (see e.g. question 1, question2). What are good strategies to handle or avoid these problems?

As a package developer, the most obvious strategy is to use unique names, but to be on the save side one would probably need to use very long names and prefixes like

MyPackageMyNameAndMyBirthday

This has drawbacks: the code will be harder to read than necessary, you still can't be sure about uniqueness and the names will be hard to remember and type, just to name some. (And yes, it spoils most of the fun and beauty of Mathematica).

Thus I have used other strategies like using strings instead of symbols for option names. I just have learned that this also has drawbacks and of course it is not applicable to function names.

Another problem is that as a user of a package, you can't control what the symbol names in these are: It might happen that you want to load two packages that define symbols with the same name. It might happen that you want to use a package written for an older version of Mathematica that defines a symbol with a name that meanwhile exists in the System` context. I have loaded packages (Needs) and explicitly removed the corresponding context from $ContextPath in such situations, but I feel that's somewhat hacky.

Are there better ways to deal with this?

(I found an article available by Wagner which discusses some ideas about the topic, but don't think it gives answers to the examples I gave)

EDIT 2022-08-28

since version 13 there is the new feature "$ContextAliases" which allows to use aliases like: Needs["context`"->"alias`"] which solves exactly the problem I was addressing. This questions and all answers can thus be considered "deprecated" and are only relevant for version < 13.

$\endgroup$
4
  • 4
    $\begingroup$ I use strings for options now too and note that it is becoming more common in Mathematica functions now. I noted the discussion between you and Leonid about this. For me the only drawback is that you can't type command K to autocomplete the typing $\endgroup$ Commented Jan 19, 2012 at 23:45
  • $\begingroup$ The other drawback of string options is that you can't use ? to remind yourself of what they do, thus forcing you to dig through the manual... $\endgroup$ Commented Jan 20, 2012 at 3:24
  • $\begingroup$ I have realized that there were no new answers for quite a while and this is probably more a discussion type of Questions than an Q&A type. I accepted Marks answer because I think it basically reflects what I also have experienced: if there are problems with shadowing the best is to use full contexts for the symbols you use. I prefer to even clean up my $ContextPath for those cases to avoid the red syntax highlighting and accidental use of short symbol names. Thanks everyone for answering. $\endgroup$ Commented Jan 21, 2012 at 17:44
  • $\begingroup$ @MikeHoneychurch There's also no incorrect-syntax coloring for string options. So, a misspelled string option doesn't turn red. $\endgroup$ Commented May 21, 2012 at 19:54

4 Answers 4

11
$\begingroup$

When this is unavoidable, I just refer to full contexts. This happens all the time when using Combinatorica, which defines Graph objects that conflict with V8's new built in Graph object. Here's a sample session (presented as an image to show highlighting and such): enter image description here

$\endgroup$
6
$\begingroup$

I am somewhat late to the party, but anyways. While the solution to use fully qualified names is totally legitimate, I dislike it because it couples the packages together stronger than I'd like. In this answer, I desribes a simple alternative. I was discussing the worst case scenario, where you actually do need both functions with conflicting names within a single function you are writing. In most cases, it should be easy to isolate pieces of code which The technique there can be further automated.

I will reproduce here a modified version of that approach, which I like better because I don't have to deal with strings:

BeginPackage["Test0`"];
g[x_?NumericQ] := x^2;
EndPackage[]

BeginPackage["Test1`"];
g[x_?NumericQ] := x^3;
EndPackage[]

and the main package:

BeginPackage["Main`"];
f::usage = "A test function of a single  argument";

Begin["`Private`"];

start = Needs;
end = Function[cont,$ContextPath = DeleteCases[$ContextPath,cont]];

start@"Test0`";  
(*Define first delegate private function*)  
g1 = g; 
end@"Test0`"; 


start@"Test1`";
(*Define second delegate private function*)
g2 = g
end@"Test1`";

f[x_] := g1[x]*g2[x]

End[]
EndPackage[]

So, it is some work, and you still have to indicate the contexts, but if you have many functions where you need to resolve conflicts, you still need only two code sections. Also, in this way, this is not hidden in some function's long name, but is exposed on the level of package's sections. This is also more amenable to meta-programming, should you later decide to automate this further.

In any case, let's look:

??f
A test function of a single  argument
f[Main`Private`x_]:=Main`Private`g1[Main`Private`x] Main`Private`g2[Main`Private`x]

?Main`Private`g1
Main`Private`g1
Main`Private`g1=Test0`g

?Main`Private`g2
Main`Private`g2
Main`Private`g2=Test1`g

So, we see that our delegates were assigned properly resolved function names.

$\endgroup$
4
  • $\begingroup$ @Nasser What I meant is that the use of fully-qualified names makes code harder to refactor. In Java, project of any significance is hard to imagine doing without IDE like Eclipse or IntelliJ Idea, which have strong refactoring support. Besides, cases like that in Java are quite rare, also because Mathematica package is on the average heavier (has more functionality) than Java class. A typical refactoring use case: package with a context MyPackage` becomes now MyLargerProject`MyPackage` , if the previously stand-alone package becomes a part of a larger project. You will have then ... $\endgroup$ Commented Jan 23, 2012 at 12:19
  • $\begingroup$ @Nasser ...to hunt for all these symbols manually, which is quite error-prone. For cases you list, this is not likely to happen, but we see such cases not very often only because people yet did not start actively re-using each other's code in their projects, on an industrial level (compared say to Java). My approach makes this at least easier to do, since you have to change context names in just a few well-defined places. $\endgroup$ Commented Jan 23, 2012 at 12:23
  • $\begingroup$ Very nice, it does what I have described and what I do on certain occassions plus adds the delegate symbols -- altogether much more elegant and readable. I'm not sure whether this could fail due to evaluation order when the symbols define UpValues&Attributes, but for all regular "function" definitions that only define DownValues this should be save, I think even when considering attributes, right? $\endgroup$ Commented Jan 23, 2012 at 14:22
  • $\begingroup$ @Albert Oops, I did not notice your mention of this method - indeed just what I did here. Yes, I think it is safe - this should IMO be safe in all cases. While it looks like there is CompundExpression (and indeed, the output is suppressed), the parser parses these one by one (and this is why, if we use my original solution I linked to, we have to use strings like Symbol["g"] - whicj I dislike - due to the Block wrapped around, because only top-level lines are parsed one by one. $\endgroup$ Commented Jan 23, 2012 at 16:08
4
$\begingroup$

What I did for the IMTEK Mathematica Suppmenent (IMS) was to prefix every function with imsMyFunction. That worked reasonably well. As for context, as Mark pointed out you could use the full context path.

$\endgroup$
1
  • $\begingroup$ @NasserM.Abbasi, if you load the package and that package has a symbol that is also on, say, System` context it may conflict. I had some occasions of this, when new stuff was introduced in M-, with names I had in some package; at some stage I decided to prefix everything with small letters and never had a problem after that. $\endgroup$
    – user21
    Commented Jan 23, 2012 at 12:51
2
$\begingroup$

Since all names in System` start with an uppercase letter (or a non-letter), the easiest way to avoid name clashes with future versions of Mathematica is to start your names with lowercase letters. That doesn't prevent name clashes with other packages, of course.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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