Setting Up Wolfram Language Packages

In a typical Wolfram Language 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 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 . 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.

Package`symbols for export
Package`Private`symbols for internal use only
System`builtin Wolfram Language symbols
Needed1`, Needed2`, other contexts needed in the package

Contexts conventionally used in Wolfram Language packages.

There is a standard sequence of Wolfram Language 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.

BeginPackage["Package`"]set to be the current context, and put only on the context search path
f::usage="text", introduce the objects intended for export (and no others)
Begin["`Private`"]set the current context to
f[args]=value, give the main body of definitions in the package
End[]revert to the previous context (here )
EndPackage[]end the package, prepending the to the context search path

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 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 , 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 , 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]:=
Click for copyable input
The EndPackage command in the package adds the context associated with the package to the context search path.
In[2]:=
Click for copyable input
Out[2]=
The function was created in the context .
In[3]:=
Click for copyable input
Out[3]=
The parameter is put in the private context .

In the package, the functions that are defined depend only on builtin Wolfram Language 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 the Wolfram Language to read in a package at any point using the command . ("Files for Packages" 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 the Wolfram Language to read in a package if the context associated with that package is not already in the list $Packages.

Get["context`"] or <<context`read in the package corresponding to the specified context
Needs["context`"]read in the package if the specified context is not already in $Packages
BeginPackage["Package`",{"Needed1`", }]
begin a package, specifying that certain contexts in addition to are needed

Functions for specifying interdependence of packages.

If you use BeginPackage["Package`"] with a single argument, the Wolfram Language puts on the context search path only the context and the contexts for builtin Wolfram Language 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.

Begin["context`"]switch to a new current context
End[]revert to the previous context

Context manipulation functions.

Executing a function like Begin which manipulates contexts changes the way that the Wolfram Language 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 the Wolfram Language 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 Wolfram Language packages.

The name is interpreted before this expression is executed, so the Begin has no effect.
In[5]:=
Click for copyable input
Out[5]=

Context manipulation functions are used primarily as part of packages intended to be read into the Wolfram Language. 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, the Wolfram Language 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 the Wolfram Language print out short names for the symbols, and allow you to refer to the symbols by their short names.