Mathematica Programming » Higher-Level Functionality
Packages
Packages are a convenient way to partition code into chunks that don't interact with each other needlessly, allowing for simpler programming. Mathematica even has a special package file type, the .m file, which is closer to plain-text than a .nb file.
A package is really just a collection of symbols in a given context, defined so as to interact with only the System
context and whichever contexts the user loads, which protects from name overlaps and things.
Definition
A package may be defined anywhere, using BeginPackage
and EndPackage
. Usually one inserts a Private context into the package, however, to make definitions cleaner, and only exposes a certain subset of functions, which are given usage messages. For example let's define a simple package:
BeginPackage["BabysFirstPackage`"];
function1::usage="an exposed function";
function2::usage="another one!"
$constant::usage="a package constant";
Begin["`Private`"];
function1[x_]:=function2[1,x];
function2[x_,y_]:=($constant=RandomReal[]*x*y);
End[];
EndPackage[];
Note that the symbols must be used before they are given private definitions or else the definitions will be on private symbols.
Get and Needs
Once the package is defined, it's later imported using Get
or Needs
, the difference between which can be found in the documentation (there are no subtleties to be warned about, here).
Note that both Get
and Needs
only work on these very plain .m and .wl files. One cannot run Get
on a notebook file and evaluate the expressions contained within so simply.
AutoGeneratedPackage and InitializationGroups
Happily there is a way to define packages within notebooks, using the AutoGeneratePackage
option for the notebook. When this is set to Automatic
, every time the notebook is saved it saves all of the initialization cells within to a package file with the same file name.
If this were all, that wouldn't be too useful, as having to specify all of the initialization cells is a pain. Happily we evade that problem by using an InitializationGroup
, which is simply a cell group where all of the evaluatable cells are automatically initialization cells.
The way I often go about using this is creating two cell groups:
I put all of my package code here.
And run all of my tests here.
Then I make the Package cell an InitializationGroup
. This way I can simply add and subtract from the package at will, but still get all the benefits of a notebook for testing and formatting.
Packages are also a great way to store useful tricks and things you develop for doing problem sets or similar projects. Just toss all of your tricks in one package and you can get them all at once.