![]() |
CPSC 110-08: Computing on Mobile Phones
|
In this lecture and demo we visit the topic of procedural abstraction. Recall that abstraction is the ability to filter out information that is not necessary to a problem and to generalize those details that are significant.
In previous lectures we have seen how to define and use procedures. A procedure is a named module that can be called or invoked at one or more places in the program. A procedure contains an algorithm in its do slot.
We have already used the following block to define procedures that
perform a sequence of actions but do not return a result:
We now want to learn to define and use special types of procedures
that do return results. These are typically called functions.
A function is procedure that takes 0 or more arguments and returns a
value. In App Inventor a function is defined using the following block:
Notice the additional slot labeled return at the bottom of the block.
You are already familiar with functions from mathematics. For example, the sqrt function, takes a real number argument and returns its square root:
sqrt(25.0) = 5.0 sqrt(4) = 2 sqrt(5) = 2.23606798
App Inventor comes with a number of built-in functions under its Math
menu where you will find: sqrt, min, abs, round and many others. Here's
what calling the sqrt function looks like in App Inventor:
The sqrt function has one slot for an argument (here 100) and returns the square root of its argument (here 10). Note that the argument slot serves as a place holder into which you must plug a value.
In this example, we are calling the sqrt function
and plugging in the value 100. We also say we are passing
the value 100 to the function. It will return the value
10, which we can then plug in to any slot that takes a value -- e.g.,
into a text box or into a math expression or into a variable.
Note that we don't always want to plug literal values, like 100, into the argument slot. We can also plug in the value of a variable. For example, suppose we have previously set the variable X to 25. Then calling sqrt(X) will return the value 5.
Because a function returns a value, you can compose function operations as
in the following example:
App Inventor gives us the ability to write our own functions using the procedureWithResult
block. Note that it has an open slot for an argument and an open slot for a result
and a body where we can do a sequence of operations:
Here's a simple example in which we define a function that calculates the square of any number
and then we call the function and pass it the argument 10.
Note that calling our square function looks just the same (except for the colors) as calling the sqrt function.
In this case the function is so simple that there is nothing to "do" other than perform the calculation and return the result. So we can just put our calculation in the return slot.
Of course, we wouldn't typically define a procedure for such a simple calculation. So let's look at a more likely example.
Our simple square function contains an argument where you plug in the value that you want to square. So, rather than having to define separate functions to calculate specific values -- e.g., squareOf10, squareOf2, squareOfMinus3 -- you define a much more general function, square(X) where any value can be plugged in for X.
Thus, arguments make our functions and procedures more general, giving them wider application. This generality is an important characteristic of procedural abstraction.
Suppose your app needs to calculate the hypotenuse of a right triangle. You probably remember the Pythagorean Theorem from high school geometry -- i.e., the formula for calculating the length of the hypotenuse of a right triangle based on the lengths of its other two sides. The length of the hypotenuse is equal to the square root of the sum of the squares of the other two sides:
c = √ a2+ b2
The Pseudocode algorithm for computing the hypotenuse is quite simple. The only thing we need to do is return the square root of the sum of the squares of a and b:
# Comment: A function to compute the hypotenuse # Notice that we put the parameters, a and b, in a list following the function's name. To hypotenuse(a, b): Return: sqrt(a * a + b * b)
Here again, there is nothing to "do" besides perform the calculation so we just return the result of calculating √ a2+ b2 .
Note that we don't need a global variable to calculate the hypotenuse. We can just return the value of the hypotenuse.
A parameter (or an argument as they are called in App Inventor) is a place holder in a function or procedure definition. When you call the function you substitute a value for the parameter and the function uses that value in its computation.
For example, the hypotenuse(a,b) function has two parameters, a, and b. When I call this function, I would replace a and b with specific values. For example if I call hypotenuse(4, 3), it will compute √ 42+ 32 = 5.
The values that are used as arguments don't have to be literal values like 4 and 3. They can be values contained in variables. For example, suppose that we have set X to the value 5 and Y to the value 12. Then when we call hypotenuse(X,Y), it will compute √ 42+ 32 = 13.
The values that we plug into a parameter can also be the result of a function call. For example, what value would Var be set to by the following algorithm:
Set Var to hypotenuse(sqrt(9), sqrt(16))
Here is how this would look in App Inventor:
Another way of defining our hypotenuse function is to use a global variable and break the computation into several steps:
# Comment: A function to compute the hypotenuse # Notice that we put the parameters, a and b, in a list following the function's name. To hypotenuse(a, b): Set Hypotenuse to a * a Set Hypotenuse to Hypotenuse + (b * b) Set Hypotenuse to sqrt(Hypotenuse) Return: Hypotenuse
Here's a function that will perform this algorithm in App Inventor:
(NOTE: Unlike in most programming languages, in App Inventor, argument names have global scope, rather than local scope, which means we can't reuse the argument names a, and b, in this function definition. So we use a1 and b1.)
Before you use your function in your app, you should test it by calling it. To do this, you will need to pull out the call function block from the My Definitions drawer.
If you right-click on a call to the function, you can test it using App Inventor's Do-it option, as shown here:
A procedure call is a statement and it can go
anywhere that a statement can go in a program. For example, it can go
in a do slot. Recall this example from the FairCoin app,
where we Call InitializeTheExperiment to do some initialize
operations for us:
A function call produces a value, which cannot stand
alone the way a statement can. Therefore the value has to be put into
a statement or into another expression. For example, look how we put
the result of calculating the hypotenuse into the slot that takes a
text value.
![]() | ![]() |
When the CalculateHypotenuse button is clicked, the values in the aInput and bInput text boxes are passed to our hypotenuse function and its result is put in the Result text box.
Write Pseudocode functions to perform the following calculations. Post your solutions on your Portfolio.