6
$\begingroup$

I'm building a Mathematica application "APPStestI" that contains three packages: SUBappsA.m, SUBappsB.m, SUBappsC.m and APPStestI.m. Where APPStestI.m is the main package; SUBappsA.m and SUBappsB.m contains some functions and SUBappsC.m stores the values of the constants used by other packages.

init.m

Get[ "APPStestI`APPStestI`"]
Get[ "APPStestI`SUBappsA`"]
Get[ "APPStestI`SUBappsB`"]
Get[ "APPStestI`SUBappsC`"]

APPStestI.m

BeginPackage["APPStestI`"]

   Print [Style[" Mathematica application ","Text"]];

EndPackage[]

SUBappsA.m

In this package we use the stored value of x.

BeginPackage["APPStestI`SUBappsA`"]

  Get[ "APPStestI`SUBappsC`"]
  Unprotect["SUBappsA`*"];    
  ClearAll["SUBappsA`*"]; 

  funI::usage = "funI[ x]"

Begin["`Private`"] (* Begin Private Context *)

  funI[xp_] := Module[ {yp}, yp = xp^2+x; yp + 1 ]

End[] (* End Private Context *)

  Protect["SUBappsA`*"];

EndPackage[]

SUBappsB.m

In this package we use the stored value of WW.

BeginPackage["APPStestI`SUBappsB`"]

  Get[ "APPStestI`SUBappsA`"]
  Get[ "APPStestI`SUBappsC`"]
  Unprotect["SUBappsB`*"];
  ClearAll["SUBappsB`*"];

  funII::usage = "funII[w] computes a simple function."

Begin["`Private`"] 

  funII[ wp_] := Module[ {zp}, zp = wp^3+ funI[WW]; zp + 1]

End[]

  Protect["SUBappsB`*"];

EndPackage[]

SUBappsC.m

BeginPackage["APPStestI`SUBappsC`"]

  Unprotect["SUBappsC`*"];
  ClearAll["SUBappsC`*"];

  y::usage= "5" 
  WW::usage= "10" 
  x::usage= "3" 
  z::usage= "4" 

Begin["`Private`"] 

  {  y = 5,  WW = 10,  x = 3,  z = 4 };

End[] 

  Protect["SUBappsC`*"];

EndPackage[]

Then loading APPStestI the following is shown:

<< APPStestI`

z::shdw: Symbol z appears in multiple contexts {APPStestI`SUBappsC`,Global`}; definitions in context APPStestI`SUBappsC` may shadow or be shadowed by other definitions.

The application performs the operations correctly, but I can not solve this problem.

$\endgroup$

1 Answer 1

4
$\begingroup$

Minor issues:

  • Get always loads while Needs only if needed so if someone calls your init.m file then SUBappsC.m will be loaded 3 times. You probablt don't want that.

  • Unprotect["SUBappsB`*"] - this and friends won't do anything because this context does not exist at all.

The main problem is that your SUBappsC.m creates x, y, z, WW in APPStestI`SUBappsC` which is one of exported contexts. (It will appear on a $ContextPath after EndPackage[].

Packages should not export dummy variables because of collisions/shadowing problems. That is why Begin["`Private`"] is used. You however need to share them as they are not just dummy variables. (giving them more meanigful names would be a good idea if they are meant to float around your implementation files)

The common approach to creating symbols which are shared between implementation files but not outside is to use an additional context that is invoked in each file.

Let me show you a problematic code

enter image description here

and a proposed solution:

Remove[z]; (*or restart the kernel*)
z = 1;     (*again global*)

  (*First package*)
BeginPackage["MyPackage1`"];

    BeginPackage["`Common`"];
        z::usage = "here's z from MyPackage1`Common`"; 
        (*symbols exported to a shared context*)
    EndPackage[];


    Begin["`Private`"];
        (*whatever*)
    End[];

EndPackage[];

  (*And in anotherpackage:*)
BeginPackage["MyPackage2`"];
    (*I would use the same MyPackage1` across many subpackages unless there is a reason not to. 
      Here I created another context just to show that it won't break our scheme*)

    Needs @ "MyPackage1`";   (*adds it to a $ContextPath, nothing there anyway*)
    Needs @ "MyPackage1`Common`"; (*z's here*)

    Begin["`Private`"];
        Print[z::usage] (*could it work? yep*)    
    End[];

EndPackage[];

As I said, I'd not use so many different nested context but maybe you have a good reason to do so. Then you need to be in control.

More reading:

$\endgroup$
3
  • $\begingroup$ Does anyone ever -- or rather is it advisable to treat a package like a class object (in OO programming) and make package parameters private but accessible only through methods? E.g. getParam["x"], setParam["x", 3], etc. It also allows one to validate assignments and maintain dependencies. (This seemed to be a common style in Obj-C, AFAIR. But my days of serious programming are long gone.) $\endgroup$
    – Michael E2
    Jan 25, 2019 at 12:40
  • $\begingroup$ @MichaelE2 I think b3m2a1 does a lot of related stuff and can say more. I'd say it makes sense if you have a strong background in OOP. I don't and it was always a pain for me, and not very idiomatic. Moreover I mostly deal with GUI and I need a flexible access to symbols for Dynamic purposes, so I don't have time to set all needed methods. $\endgroup$
    – Kuba
    Jan 25, 2019 at 12:50
  • $\begingroup$ Let us continue this discussion in chat. $\endgroup$ Oct 28, 2019 at 13:48

Your Answer

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

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