2.7.10 Setting Up Mathematica Packages
In a typical Mathematica package, there are generally two kinds of new symbols that are introduced. The first kind are ones that you want to "export" for use outside the package. The second kind are ones that you want to use only internally within the package. You can distinguish these two kinds of symbols by putting them in different contexts.
The usual convention is to put symbols intended for export in a context with a name Package` that corresponds to the name of the package. Whenever the package is read in, it adds this context to the context search path, so that the symbols in this context can be referred to by their short names.
Symbols that are not intended for export, but are instead intended only for internal use within the package, are conventionally put into a context with the name Package`Private`. This context is not added to the context search path. As a result, the symbols in this context cannot be accessed except by giving their full names.
Contexts conventionally used in Mathematica packages.
There is a standard sequence of Mathematica commands that is typically used to set up the contexts in a package. These commands set the values of $Context and $ContextPath so that the new symbols which are introduced are created in the appropriate contexts.
The standard sequence of context control commands in a package.
BeginPackage["Collatz`"]
Collatz::usage =
"Collatz[n] gives a list of the iterates in the 3n+1 problem,
starting from n. The conjecture is that this sequence always
terminates."
Begin["`Private`"]
Collatz[1] := {1}
Collatz[n_Integer] := Prepend[Collatz[3 n + 1], n] /; OddQ[n] && n > 0
Collatz[n_Integer] := Prepend[Collatz[n/2], n] /; EvenQ[n] && n > 0
End[ ]
EndPackage[ ]
The sample package Collatz.m.
Defining usage messages at the beginning of a package is the standard way of making sure that symbols you want to export are created in the appropriate context. The way this works is that in defining these messages, the only symbols you mention are exactly the ones you want to export. These symbols are then created in the context Package`, which is then current.
In the actual definitions of the functions in a package, there are typically many new symbols, introduced as parameters, temporary variables, and so on. The convention is to put all these symbols in the context Package`Private`, which is not put on the context search path when the package is read in.
This reads in the sample package given above.
In[1]:= <<Collatz.m
The EndPackage command in the package adds the context associated with the package to the context search path.
In[2]:= $ContextPath
Out[2]=
The Collatz function was created in the context Collatz`.
In[3]:= Context[Collatz]
Out[3]=
The parameter n is put in the private context Collatz`Private`.
In[4]:= ?Collatz`Private`*
In the Collatz package, the functions that are defined depend only on builtin Mathematica functions. Often, however, the functions defined in one package may depend on functions defined in another package.
Two things are needed to make this work. First, the other package must be read in, so that the functions needed are defined. And second, the context search path must include the context that these functions are in.
You can explicitly tell Mathematica to read in a package at any point using the command <<context`. (Section 2.12.5 discusses the tricky issue of translation from systemindependent context names to systemdependent file names.) Often, however, you want to set it up so that a particular package is read in only if it is needed. The command Needs["context`"] tells Mathematica to read in a package if the context associated with that package is not already in the list $Packages.
Functions for specifying interdependence of packages.
If you use BeginPackage["Package`"] with a single argument, Mathematica puts on the context search path only the Package` context and the contexts for builtin Mathematica symbols. If the definitions you give in your package involve functions from other packages, you must make sure that the contexts for these packages are also included in your context search path. You can do this by giving a list of the additional contexts as a second argument to BeginPackage. BeginPackage automatically calls Needs on these contexts, reading in the corresponding packages if necessary, and then making sure that the contexts are on the context search path.
Context manipulation functions.
Executing a function like Begin which manipulates contexts changes the way that Mathematica interprets names you type in. However, you should realize that the change is effective only in subsequent expressions that you type in. The point is that Mathematica always reads in a complete input expression, and interprets the names in it, before it executes any part of the expression. As a result, by the time Begin is executed in a particular expression, the names in the expression have already been interpreted, and it is too late for Begin to have an effect.
The fact that context manipulation functions do not have an effect until the next complete expression is read in means that you must be sure to give those functions as separate expressions, typically on separate lines, when you write Mathematica packages.
The name x is interpreted before this expression is executed, so the Begin has no effect.
In[5]:= Begin["a`"]; Print[Context[x]]; End[ ]
Out[5]=
Context manipulation functions are used primarily as part of packages intended to be read into Mathematica. Sometimes, however, you may find it convenient to use such functions interactively.
This can happen, for example, if you go into a dialog, say using TraceDialog, while executing a function defined in a package. The parameters and temporary variables in the function are typically in a private context associated with the package. Since this context is not on your context search path, Mathematica will print out the full names of the symbols, and will require you to type in these full names in order to refer to the symbols. You can however use Begin["Package`Private`"] to make the private context of the package your current context. This will make Mathematica print out short names for the symbols, and allow you to refer to the symbols by their short names.
