8
$\begingroup$

I am using a package that was written for Mathematica 3 while I am now working on Mathematica 8. I have issues with 2 functions in particular, Order and GraphComplement. They are a part of this package but are also present in Mathematica 8 by default but with distinctly different arguments and working. (I am assuming they weren't around in Mathematica 3)

Now when I make use of some other functions in this package they make calls to both Order and GraphComplement and it keeps trying to use the in built wolfram version. I instead want it to use the one that comes with the package.

Can anyone point me to the right direction?

$\endgroup$
  • $\begingroup$ How hard would it be to edit the package file and do a search and replace? (just curious how large a package it is) $\endgroup$ – Jason B. Jan 7 '16 at 7:57
  • $\begingroup$ Or basically overwrite all existing functions whenever an external one is imported with the same name? $\endgroup$ – jasonheush12 Jan 7 '16 at 8:38
8
$\begingroup$

If I understand the problem I think I can help, but what I propose is a bit weird. I think you have a package that uses the unqualified Symbol name Order internally, and you need the package not to see the System`Order Symbol while it is defined. To effect this you can temporarily change the Context of Order, then put it back after loading the package.

As an example here is a bare-bones package defining a function foo that uses an internal definition for Order:

BeginPackage["MyStuff`"]

foo::usage = "my function";

Begin["`Private`"]

Order[args___] := {args} === Sort[{args}];

foo[a_, b_] := If[Order[a, b], "Arguments are in order", "Arguments are out of order"]

End[]

EndPackage[]

After saving this to foo.m if I call Get[foo.m] and try to use foo I have a problem:

Get["foo.m"]

foo[1, 2]

SetDelayed::write: Tag Order in Order[args___] is Protected. >>

If[1, "Arguments are in order", "Arguments are out of order"]

But if, after restarting the kernel, I first move Order out of the System context before loading the package:

Context[System`Order] = "hold`";

Get["foo.m"]

Context[hold`Order] = "System`";

I can now call my foo as intended:

foo[1, 2]
foo[4, 2]
"Arguments are in order"

"Arguments are out of order"

This works because while the package is being defined Order is not found in the context path, and a new Symbol MyStuff`Private`Order is created and defined instead:

Definition[foo]
foo[MyStuff`Private`a_, MyStuff`Private`b_] := 
 If[MyStuff`Private`Order[MyStuff`Private`a, MyStuff`Private`b],
   "Arguments are in order",
   "Arguments are out of order"]

And Order still works elsewhere as its context is restored:

Order["a", "b"]
1
$\endgroup$
  • $\begingroup$ This is... exactly what I was looking for. It seems to work flawlessly for Order however when I try to do this for GraphComplement I get this: SystemGraphComplement::shdw: Symbol GraphComplement appears in multiple contexts {System,GrafPackBasics}; definitions in context System` may shadow or be shadowed by other definitions. >> Any idea what went wrong here? $\endgroup$ – jasonheush12 Jan 7 '16 at 10:16
  • $\begingroup$ Just checked. The warning is there but it seems to work fine anyway. Much thanks my friend. Accepted. :) $\endgroup$ – jasonheush12 Jan 7 '16 at 10:31
  • $\begingroup$ @jasonheush12 Thanks for the Accept. Don't hesitate to remove it if you find this fails. Your warning is probably caused by a background (re)load of GraphComplement. Try using that System function in some trivial application before changing its context and loading your package, and see if the message goes away. (Incidentally I ran into these background load consequences myself here.) $\endgroup$ – Mr.Wizard Jan 7 '16 at 10:57
  • 1
    $\begingroup$ +1, Nice use of this change-symbol-context capability. However, I personally still view this as a hack (although probably the best one can do). The real way out would be to implement an alternative loader (Get / Needs) with a read stage (access to code in box form, and then fully parsed but not yet evaluated, using hooks to inject user-defined operations). In this way, we might for example get a code in held form, already parsed, and then simply replace all System`Order symbols to MyPackage`Order. $\endgroup$ – Leonid Shifrin Jan 7 '16 at 15:25
  • $\begingroup$ @Leonid That sounds like a more robust approach, but I'm far too lazy. :^) Oh, and thank you. $\endgroup$ – Mr.Wizard Jan 7 '16 at 15:39

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.