Monday, June 1, 2015

Use Packages to Extend Mathematica with Your Own Functions

The framework for extending Mathematica with user-created programs, like library functions in many programming languages, is provided by Packages. 

Generally use Needs to load Packages, not Get. Needs checks to see if a Package is already loaded. But use Get when developing a Package since in that case you want to overwrite the old Package.

Here are the essentials of what you need to know to create Packages of your own. This table steps through an example of a Package. See the line-by-line comments below the table for an explanation of what’s going on in each step.

Line/Comment #
Command
$Context
$ContextPath
1
Times[4, Pi, Power[2, 2]]
Global`
{Global`, System`}
2
area@radius_:= 4*Pi*r^2
Global`
{Global`, System`}
3
BeginPackage@“MyFunctions`”]
MyFunctions`
{MyFunctions` , System`}
4
sphereArea::usage=” sphereArea @radius calculates the area of a sphere of radius r.”
MyFunctions`
{MyFunctions `, System`}
5
Begin@” MyFunctions `Private`”
MyFunctions `Private`
{MyFunctions `, System`}
6
sphereArea@radius_:= 4*Pi*r^2
MyFunctions `Private`
{MyFunctions `, System`}
7
circumference@radius_:= 2*Pi*r
MyFunctions `Private`
{MyFunctions `, System`}
8
End[]
MyFunctions`
{MyFunctions `, System`}
9
EndPackage[]
Global`
{MyFunctions `, Global`,System`}

Comment by Line Number

  1. A Mathematica session begins in the Global` Context. All built-in commands reside in the System` Context, which is always on the Context search path stored in $ContextPath) so they can be found no matter what Context you are in. This is the FullForm of a calculation for the surface area of a sphere with radius = 2 using built-in commands Times, Power, and constant Pi.
  2. All user-defined symbols, including function names and definitions, reside in the Global` Context and are globally visible, along with built-in commands in the System` Context, unless the user changes the Context. This function is a one-off for calculating the surface area of a sphere.
  3. BeginPackage changes the current Context to that of the Package it names, removes all Contexts except System (so built-in commands are accessible) from $ContextPath, and adds the Package name to $ContextPath. BeginPackage removes all Contexts, especially the Global` Context, from $ContextPath so that no globally-visible, previously-defined symbols can foul you up while you develop your Package. Thus you can use the same names while fooling around in Global` that you may end up using in the Package.
  4. Usage messages not only return their content when queried with Information@symbol (“?symbol”) but expose the function name for use outside the Package.
  5. Symbols in a Private` Context are not visible on the Context search path. But since a usage message declared sphereArea in the public Package Context, it will be found when used in any Context. I suspect while we always see short ‘nicknames’ for symbols, which are the last Context path element, Mathematica always sees the full Context path names, thus is omniscient and ambiguity between identical names is resolved.
  6. A function for calculating the surface area of a sphere, like the one-off one in Global`, is more formally defined for repeated use in the future, corresponding to the usage message placed in the public area of the Package (see #4). This definition, in the Private area of the Package, is invisible while any definition in the usage message is visible (e.g. using “?sphereArea”).
  7. A private function calculating the circumference of a circle is defined for use within the Package by other functions but not for public export. It cannot be seen outside the Package (unless its full Context path is entered).
  8. End[] ) - no argument is used - is the command used to exit a Context, in this case, “MyFunctions`Private`”, which removes the most recent Context entered in $ContextPath and returns us to the previous Context, “MyFunctions`”.
  9. EndPackage[]- no argument is used - exits the Package and adds any other Contexts, in this case Global`, to the Context search path. 

Further guidance:

For consistency, make the name of a Package file the same as Context it uses (e.g. here, "MyFunctions.m"). Put the Package file in a directory in $Path (the directory List searched by Mathematica), such as that specified by $UserBaseDirectory, which is the location Mathematica provides for user Packages, or add your Package file’s directory to $Path with PrependTo.

Test your Package with typical parameter values for which it was designed, but also incorrect datatypes and values outside the range for which it was designed,
You can Protect a symbol from alteration by a user with SetAttributes[aSymbol, Protected].

You can Protect a symbol’s definition from being read by a user with SetAttributes[aSymbol, ReadProtected]

Whether in a Notebook or Package (.m) file, cells that you want to be automatically evaluated must be Initialization cells (Cell => Cell Properties => Initialization Cell).

Sources
Programming in Mathematica Course by Roman Maeder, Wolfram Research, Inc.
David Wagner, Power Programming with Mathematica: The Kernel  (New York: McGraw-Hill, 1996. out of print).
StackExchange discussion here.

No comments:

Post a Comment