Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load a mathematica package from within a package

I have more or less the following setting. In ~/path/to/my/packages I have two packages package1.m and package2.m. Each package's outline is, for example, the following:

BeginPackage["package1`"]
Unprotect@@Names["package1`*"];
ClearAll@@Names["package1`*"];

Begin["`Private`"]

vecNorm[vec_?VectorQ]:=Module[{},Return[Sqrt[vec.vec]]];

End[]
Protect@@Names["package1`*"];
EndPackage[]

Now, my problem is that I want to use vecNorm defined in package1.m in package2.m. How can I load (safely) package1 from within package2?

At the moment, I load manually both packages as follows:

SetDirectory[StringJoin[NotebookDirectory[], "packages"]];
Needs["package1`"]
Needs["package2`"]

from a notebook saved in ~/path/to/my. I want to load manually only package2 which in turn will load automatically and safely package1. In general I want a solution which changes as little as possible paths etc. of mathematica. What should be the best practice to accomplish this?

PS: By safely I mean that in the future, when I'll define package3 which will be using vecNorm as well and will be loading package1 as well no conflicts will happen.

like image 326
Dror Avatar asked Dec 05 '11 12:12

Dror


1 Answers

There are two generally recommended ways to load a package. One is so-called public import, and in your setting it will be done as

BeginPackage["package2`",{"package1`"}]

(* Usage messages etc *) 

Begin["`Private`"]

(* code here *)

End[]
EndPackage[]

Here, you indicate the context name of the package you want to load, in the list which is a second optional argument to BeginPackage. This way of importing is called public because the loaded package will remain on the $ContextPath after your main package is loaded, and will thus be publicly available.

The second method is called private import, and is schematically done as

BeginPackage["package2`"]

(* Usage messages etc *) 

Begin["`Private`"]
Needs["package1`"]

(* code here *)

End[]
EndPackage[]

In this method, your loaded second package will only be available to the package that loads it (with Needs), thus private import.

Which way you need will depend on the situation. I try to make all my imports private unless I have to make them public. For debugging, however, it may be handy to first make a public import, since then you can play with the second package directly at the top-level.

As for the safety, you can load a package by any number of packages, and this will be safe. When you load several packages into the same context simultaneously, this will be safe as long as those packages don't have public symbols with the same short name. Otherwise, you will run into what is called a shadowing problem, but it is best to make the effort needed to avoid that (it is always possible).

like image 96
Leonid Shifrin Avatar answered Sep 28 '22 11:09

Leonid Shifrin