Creating New Functions Using Procedural Programming
George E. Hrabovsky
MAST
Introduction
Welcome to lesson two, in this lesson we will begin our discussion of programming in MMA/WL. In this lesson we will describe what we mean by procedural programming. We will then discuss, at great lengths, how we assign symbols to expressions. We will then discuss input and output. We will then get the the heart of procedural programming, how we handle loop-type programming structures. Related to the loops are conditional statements that are directly related to procedural programming. We will end with a discussion of flow control.
It is true that procedural programming is not the most efficient use of MMA/WL. That being true, why address it first? It is mostly due to tradition. The vast majority of programming languages are procedural. It would be foolish to avoid these capabilities. Most people who are familiar with programming are familiar with procedural styles of language. MMA/WL are completely capable of procedural programming. So we begin here.
What is Procedural Programming?
If we have a programming problem and we break it up into smaller tasks that need to be accomplished, each task is composed of a set of specific instructions (an algorithm). Each such task is called a procedure. A procedural program is then built up out of a set of procedures to be performed.
This is an example of a very direct translation of an algorithm into code. Each element of an algorithm has its own procedure. If there are ten elements of an algorithm there will be at least ten elements of the procedural code. One reason why this is the first programming style, or paradigm, learned is that it is so direct. Other paradigms require a more sophisticated view in order to use them, so rather than amping up the learning curve right away, this type of programming is the easiest to understand.
This is all very abstract. How do we make it concrete? We look at an example. What is a good example of a problem we can solve by procedural programming? Say we watch a walnut fall out of a tree and we want to use the computer to tell us how long the nut takes to fall to the ground. How do we set up this problem for procedural programming?
It is an easy problem to solve by hand, if we ignore the air resistance against the fall of the nut. Since we have a computer, let’s use it solve the more difficult problem. Let’s say that we have derived a formula that governs the situation given the initial height above the ground, h. The formula we need to use from the time of fall is,
Here b is a constant based on the geometry of the nut and the viscosity of the air, we will assume this to be close -1, m is the mass of the nut, we will assume that it is about 0.25 kg, and g is the acceleration due to gravity, about 9.8 . If we insert these values into (2.1) we get,
All we need to do is input the value of h.
So let's break this down into a set of procedures.
Input the value of h.
Calculate the value of t using (2.2).
Output the value of t.
how do we input the value of h? We will see as we go.
We can use Clear[symbol] to remove all values from a symbol. You can clear a list of symbols in this way.
We can use ClearAll[] to remove all assignments for a symbol.
Input and Output
Input is most often performed by typing into a call. It can also include typing into the arguments slot for a function. We can assign a symbol as input, using the Input command, where the command allows you to treat an expression as input.
Note that a dialog box shows up. This is if you are using a notebook front end. If we want to be clearer we can include a prompt.
You can also specify a default value.
Output is handled automatically as an output cell.
The simplest output command returns whatever expression you tell it to, the Print command.
We can style our output using the Style command.
Row can be used to produce nicely readable output. It processes a list where each element has its own fixed location in the row.
Column works the same way only vertically. Here is a simple example from the documentation.
1 |
12 |
123 |
1234 |
Grid is a column of rows.
a | b | c |
x | y | z |
There are a great many options for creating styled output. You can create your own GUI type programs. As an exercise look up the functions Frame, Background, Alignment, Dividers, and Spacings.
Loops
A loop is an algorithmic construct that repeats in some way until told not to.
This simplest looping structure is the Do loop, where we write Do[expression,the number of iterations]. For example, let’s take the squares of the first ten natural numbers.
Why didn’t this display anything? Because we didn’t tell it to display anything. We need to tell it to output the result at each step.
We can, of course apply all of the iteration commands for MMA/WL. We can specify a minimum and a maximum value
We can specify a step size.
We can even specify specific values.
Another loop is accomplished using the While command. We will often want to initialize symbols we are going to use. Here we see how to calculate the GCD of two integers.
We can use the Break subcommand to remove us from the While loop to prevent errors. This is an example from the system documentation. Here we use the test InegerQ, the statement !IntegerQ to generate a true result only if the input value is not an integer. So this will only work for positive integers (whole numbers).
Note that if we input a decimal fraction the program stops due to the Break command.
The For loop begins with an initialization, then it requires a test, then it requires a method of incrementing the value being tested, then it has the body of the program.
Table is a much more useful alternative to these looping structures.
5. | 25. |
5.25 | 27.5625 |
5.5 | 30.25 |
5.75 | 33.0625 |
6. | 36. |
6.25 | 39.0625 |
6.5 | 42.25 |
6.75 | 45.5625 |
7. | 49. |
7.25 | 52.5625 |
7.5 | 56.25 |
7.75 | 60.0625 |
8. | 64. |
8.25 | 68.0625 |
8.5 | 72.25 |
8.75 | 76.5625 |
9. | 81. |
9.25 | 85.5625 |
9.5 | 90.25 |
9.75 | 95.0625 |
10. | 100. |
Throw and Catch work together. A Throw is a value sent out (thrown) in the form of a value and sometimes a tag. A corresponding Catch has an expression and possibly a form, if the form matches the tag of the the throw. Here we have a value that is not tagged. We define a function with a Throw.
Now we try some corresponding catches.
Procedural Conditionals
A conditional is some statement to the effect that if one thing happens, then something else happens.
The most elementary conditional in MMA/WL is the If command. If[conditional statement,is true, is false]. For example, we can define an absolute value command.
We can cheat and use a pattern matching command to make this work on a list. The /@ symbols tells MMA/WL to apply the function to what follows.
This illustrates the advantage of using MMA/WL as you can mix programming paradigms seamlessly.
There are a vast number of ways to test expressions. As a homework assignment, you should go to the documentation system and type in Testing Expressions. All of these tests can be used in conditional statements.
The Which command offers a collection of tests and outcomes
Flow Control
We can create patterns of flow in the implementation of an algorithm, where we want a specific part of the program to be used.
One way to implement flow control is to use a Module to make a program. We will explore this in more depth in a future lesson. For now we can treat it is device to make self-contained programs. We type Module[{local variables isolated from other work},the list of statements for the modular program;the end result to be displayed].
We can use the Label command to identify places in the program that we want to be able to refer to later.
The Goto command directs the program to go to a specific label. Here is an example drawn from the built-in documentation.
Sometimes you want to give the system time for you to respond. You can use the Pause command to stop things for a specified number of seconds.