Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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)

share|improve this question
3  
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 –  Mike Honeychurch Jan 19 '12 at 23:45
    
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... –  J. M. Jan 20 '12 at 3:24
    
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. –  Albert Retey Jan 21 '12 at 17:44
    
@MikeHoneychurch There's also no incorrect-syntax coloring for string options. So, a misspelled string option doesn't turn red. –  Sjoerd C. de Vries May 21 '12 at 19:54
add comment

4 Answers

up vote 6 down vote accepted

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

share|improve this answer
add comment

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.

share|improve this answer
    
@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. –  user21 Jan 23 '12 at 12:51
add comment

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.

share|improve this answer
add comment

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.

share|improve this answer
    
@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 ... –  Leonid Shifrin Jan 23 '12 at 12:19
    
@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. –  Leonid Shifrin Jan 23 '12 at 12:23
    
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? –  Albert Retey Jan 23 '12 at 14:22
    
@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. –  Leonid Shifrin Jan 23 '12 at 16:08
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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