Saturday, February 3, 2007

[Tech tips] Package Reloading for Mathematica Development

One problem with developing in Mathematica has been that some operations, such as data I/O and iterative number crunching, were pretty slow. This has been resolved with J/Link, which allows very transparent use of Java classes. (If you write decent number-crunching code in Java, it runs nearly as fast as in C. It also speeds up the coding process, since Java is 100% portable, and the architecture encourages good, modular programming.)

Another problem was that you were limited to the Notebook interface. This was resolved by the GUI kit (which, by the way, seems much more stable than the horrible GUIDE module in Matlab). You can also use J/Link to integrate Mathematica with any Java interface that you program. It also allows you to take advantage of the vast amount of free Java code available online. This gives you complete universality (unlike Matlab, Mathematica can be called directly from Java. Matlab can call Java, but calling Matlab from Java is not well supported at all.)

A third problem was the lack of of a good IDE environment for programming .m files (which are Mathematica scripts, which share syntax with the Mathematica notebook .nb files). Wolfram has made a good start in addressing this by creating the Wolfram Workbench. Since it is based on Eclipse, it is already much more flexible and universal than Matlab (although, given the Mathematica integration with Swing, NetBeans may have been a better choice in the long run).



The problem I will address today is related to the development cycle. When you are developing a Mathematica .m package, it is often necessary to test new versions of a function repeatedly. You can just quit the Kernel and reload the package you are working on, but sometimes, you have a time-consuming calculation upstream of the function in question, and you do not want to throw away all the upstream results stored in memory each time you test a new version of your code.

Unfortunately, as of version 5.2, Mathematica does not provide a function to "unload" a package, or in effect to reverse the commands Needs["..."] or Get["..."] (<<). (There is a standard add-on package, cleanslate.m, in \AddOns\ExtraPackages\Utilities of the standard installation.)



The following minimal code block "un-Needs" all relevant packages and reloads the newest version of each.

Begin["Global`"];
Remove["XXX`Package1`*"];
Remove["XXX`Package2`*"];
...

$ContextPath=DeleteCases[$ContextPath,"XXX`Package1`"];
$ContextPath=DeleteCases[$ContextPath,"XXX`Package2`"];
...
Unprotect[$Packages];
$Packages=DeleteCases[$Packages,"XXX`Package1`"];
$Packages=DeleteCases[$Packages,"XXX`Package2`"];
...
Protect[$Packages];

Get["XXX`Package1`"];
Get["XXX`Package2`"];
End[];


The Begin["Global`"]...End[] is necessary if you insert this code block into a Package, with its own context.

I inserted this segment into the package body of the package which is run by ExecutionBuildCommand[] in Wolfram Workbench every time a package .m file is saved.

Now, every time I save an .m file in Wolfram Workbench, the proper .m files are unloaded and reloaded automatically, so that in the Mathematica notebook window, I can just evaluate the command again and get results from the new code.

No comments: