Making It All Work

George E. Hrabovsky

MAST

Introduction

In this lesson we will explore how to make your own packages and larger programs. Examine some alternative developer environments. And then we will discuss debugging and testing.

We will begin with what a package is. How to load a package effectively. Then we will discuss how to write a package of your own.

A more recent development is the paclet. I will explain what a paclet is. Where you can find new paclets. How to write a paclet.

We will then turn to discussing developer environments and tools that are available.

We will end our discussion with exploring some of the tools available for debugging and testing.

Larger Programs and Packages

What is a package? A package is a collection of functions that form an extension to the MMA/WL system. Many are user-created. For example, if you find yourself programming the same thing across multiple notebooks, you might consider bringing the similar functions into a package that you can create. Many packages have a theme, for example the free package xAct is devoted to tensor analysis and differential geometry, I use it all the time for general relativity.

There are two commands to use to load a package into active memory. The first is preferred, but there is no shortcut for it. You write Needs[“context`”]. This adds the context to the current $ContextPath. What does that accomplish? It allows you to access all of the built-in symbols of the package. Should you find the context cumbersome when you refer to it later, you can create an alias for it in the current instance by writing Needs[“context`”->”alias`”].

What is wrong with using Get? It seems easier to write <<context` than Needs[“Context`”]. The problem with Get is that it doesn’t place all symbols under one hat, you might have two function names that are identical and then you have a shadowing conflict that will eventually cause problems. Use Needs instead.

What is the advantage of using a package? If what you are doing is a small task, then there is no advantage. If you are going to be using a lot of new functions, then a  package is the way to go.

How do I write a package? Go to the File Menu, then choose New then choose Package.

Here is an example from the documentation. It is a short 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[ ]

You start by putting it all into a your new package notebook. Then you write the command BeginPackage[“Context`”]. This tells MMA/WL the context you are creating.

The next step is to list the usage statements for all of the functions you are making. This will produce what you see if you write ?function name. You write function_name::usage=”help listing”

Once you have written out the help description for each, you now have to tell MMA/WL: to begin the package. Begin[“`Private`”] tells the system that you are now entering a private subcontext that will contain all of the code that the user will not see.

You then write all of the necessary code to make the functions work as you want them to.

You enter the Private context with the End[] command. Then you tell the system that the package is finished with the EndPackage[] command.

Save your work. Make sure your package name ends with a .wl.

Paclets

What is a paclet? It is tempting to think of a paclet as a miniature package. It might be that, no question. It can also include packages, links, stylesheets, palettes, system settings, documentation, and even data.

Where do we find paclets? Some are built into the system, some are in the cloud, some are in the paclet server at Wolfram Research, some are stored at GitHub. There is talk of a paclet repository in the future.

We can use the command PacletSites[] to list where we can get paclets from.

l6_1.png

l6_2.png

Some paclets are built in to MMA/WL. Here is a paclet that handles web searching.

l6_3.png

l6_4.gif

Expanding the box tells you where to find the paclet on your system. We can see its properties.

l6_5.png

l6_6.png

Here we find the paclets installed in the current version.

l6_7.png

Here we determine how many are present that are not compatible.

l6_8.png

l6_9.png

So the number of paclets that are valid will be here.

l6_10.png

l6_11.png

Here they are.

l6_12.png

l6_13.png

How do we load a paclet?

l6_14.png

l6_15.gif

We can also uninstall it.

l6_16.png

How do I write a paclet? It is very similar to writing a package, though there can be more to it. This is taken from the tech note “Creating Paclets” included in the documentation.

We begin by loading the PackletTools` package.

l6_17.png

We then create a blank object that will become our paclet.

l6_18.png

l6_19.gif

Let’s take a look at what we have right now.

l6_20.png

This opens a system folder in another window that described the files found in this new directory. Note that we have a WL file, so the blank paclet is there. Here is what we find if we open the paclet.

l6_21.png

If we open the Kernel subfolder, we can click on the MyPaclet to get the structure of the package.

l6_22.gif

l6_23.gif

This is a template that you can expand this as you like to build the functionality of your paclet. Otherwise it behaves just like a package. If I included this directory in the directory path I can open this paclet as I would any package.

Integrated Developer Environments

What is an integrated developer environment (IDE)? Any application that you use to write code is an IDE. Before IDEs became prevalent code was produced in text editors. A modern IDE has tools for developing, running, and testing code. Outside of MMA there are three widely used IDEs: Visual Studio, Eclipse, and Android Studio.

The notebook is a developer environment. It has color codes that identify code fragments and it points out errors in coding. So the notebook is the fundamental IDE.

Eclipse is a popular and free IDE available from the website https://www.eclipse.org/ . Eclipse works by loading a number of subsystems along with a small runtime engine. The interface is through a desktop graphical IDE. There are many modules that you can plug in. As with any IDE you can write your code, debug it, and then run your code.

Wolfram Workbench is an Eclipse plug-in that allows you to develop MMA/WL code in Eclipse. It is a free download. This is an alternative to the traditional notebook IDE.

Another free resource is the Wolfram Engine for developers. This being free, you can link it to the Wolfram Workbench and code in the WL for free.

There are other IDE plug-ins too. You can pick the plug-in for the IDE you like.

So, with the free Wolfram Player, this brings the entire panoply of WL/MMA to the hobbyist for free.

Debugging

What is debugging? Debugging is the process of locating and removing errors, bugs, in coding. It is possible that the term bug comes from a notebook of noted computer scientist Admiral Grace Hopper when a moth was discovered in a Mark II computer relay in 1947. They removed the bug and taped it into her notebook. This might have been the first debugging of a computer system... Debugging is performed by software developers to make sure their software is error-free at the point of development.

Software testing is a formal part of a developer cycle within the larger topic of software engineering. This usually employs a group of software testers who employ a testing framework. This is pretty far removed from a code monkey cobbling together a program for a specific purpose. This is more in the realm of developing a professional product for public or private release. As we will see, MMA/WL has such a framework in place.

So, what do we do when an error shows up? Say we do something like this.

l6_24.png

l6_25.png

l6_26.png

Note the structure of the warning message: l6_27.png . If you click on the ellipses button you get a popup display with two interesting items. The first is Show Stack Trace. The second is Power::infy. If you select the first option you get a stack trace of the evolution of the evaluation.

l6_28.png

l6_29.png

l6_30.png

l6_31.png

This is in reverse order. The evaluation begins with the last cell.

l6_32.png

This is just the command we entered. The next cell performs the first step.

l6_33.png

Then it evaluates until it finds the problem.

l6_34.png

Then it gives the message generated.

l6_35.png

You can trace each step in an evaluation by using the Trace[] command.

l6_36.png

l6_37.png

l6_38.png

This is more readable in TableForm.

l6_39.png

l6_40.png

l6_41.png
n -2
l6_42.png
l6_43.png
l6_44.png l6_45.png
n -1
l6_46.png
-1
1 (-1) -1
n 0
l6_47.png
l6_48.png
l6_49.png
TemplateBox[{Power,infy,\"Infinite expression \\!\\(\\*FractionBox[\\\"1\\\", \\\"0\\\"]\\) encountered.\",2,16,5,27373262728610673869,Local},MessageTemplate]
Null
ComplexInfinity
1 ComplexInfinity ComplexInfinity
n 1
l6_50.png
1
1 1 1
n 2
l6_51.png
l6_52.png
l6_53.png l6_54.png
l6_55.png

You can click on the other part, Power::infy, a new window opens up with detailed information about the error. There might even be suggestions for how to avoid the error.

Sometimes, as is the case here, the error message is correct, but we want to ignore it. We use Quiet.

l6_56.png

l6_57.png

If your code is not working right, but it is not throwing an error you can get a clue by dynamically monitoring one or more variables as they change. This example is based on the documentation.

l6_58.png

Sometimes it is useful to know at what iteration a function goes off the rails. Here is an example taken from the documentation.

l6_59.png

l6_60.png

Say we want to see how far i gets.

l6_61.png

l6_62.png

l6_63.png

l6_64.png

l6_65.png

l6_66.png

l6_67.png

In recent versions there are two new features in the Evaluation  Menu. Analyze Notebook and Analyze Cells. Here is an example of code. If you highlight the cell and go to Analyze Cell we will see if MMA/WL can catch the error.

l6_68.png

You can perform such a static analysis on any code cell or on an entire notebook.

You can also run an official test on a single function.

l6_69.png

l6_70.gif

We can get a report on how it failed.

l6_71.png

l6_72.gif

You would then perform the code analysis to find out what happened. You could then correct it.

You can create a notebook specifically to test code. You begin with the File Menu. Choose New. Choose Programmatic Notebook. Then choose Testing Notebook. You select New to produce a test field. Follow the directions. There is an excellent example in the Tech Note “Using the Testing Framework” included with the documentation.

Created with the Wolfram Language