Functions

Abstraction is a key concept in programming and in life.

Abstraction uses a strategy of simplification, wherein formerly concrete details are left ambiguous, vague, or undefined
from wikipedia


In computer science, the mechanism and practice of abstraction reduce and factor out details so that one can focus on a few concepts at a time. en.wikipedia.org/wiki/Abstraction_(computer_science).

Programmers create an abstraction by defining a procedure: a named sequence of operations. Once you name a bunch of operations, you can ignore the details. Procedures are sometimes called sub-procedures or functions.

Here's an example: When you brush your teeth in the morning, you


1) open the cabinet,
2) grab your brush and paste,
3) put some paste on your brush,
4) open your mouth,
5) push the brush across your teeth.

Now when a dad tells a kid to brush his teeth, he doesn’t want to explain all these steps each time. When the dad says, “brush your teeth”, he is making a procedure call.

‘Brush your teeth’ is an abstraction for all the many steps involved.

The top software engineers don't usually write a lot of code directly. They just design giant pieces of software, working at the structure chart level. They don't think in terms of single lines of code (single blocks in App Inventor), they think in terms of high-level procedures. Once they figure it out, they give specs of the procedures to 'grunt' programmers who then implement them.

Their goal is to divide and conquer, to break a problem down into parts small enough that it easy to program.

Creating a Procedure with App Inventor

In the lesson on timer events and animation, we learned that you can move an image (or a ball) right with the following blocks:


As a first example for creating a procedure, let's turn the five blocks that move the ball into a procedure named "MoveRight". In the Blocks Editor, we'll open the Definition drawer within the built-in palette, and drag the block labeled "procedure" into the application:


We specify the procedure name by clicking on the "procedure name" text and typing "moveRight", as in the above sample.

To build our procedure, we just grab the blocks that were directly part of the Timer event-handler and stick them into the moveRight procedure block:

We now have a procedure which moves a ball to the right a small amount. We can call that procedure from anywhere in our program. In essence, we've created a new block that we can use, a new abstraction.

When you define a procedure, a new call block is automatically placed into the My Program drawer of My Blocks. If we click My Program, we'll see it:


This block represents a procedure call, something like the dad telling the kid to "brush your teeth". In this case, moveRight tells the application to move the sprite to a new destination as defined by the five blocks defined within the procedure.

We can now simplify the Timer.Timer event handler by having it just call moveRight:

We say that the Timer1.Timer event-handler is the caller, and we say it calls the procedure moveRight.

Generalizing the Procedure with Arguments

Some procedures just do their job and don't require any input data from the caller. For instance, the dad just says "Brush your teeth" and the kid does it (or doesn't).

Sometimes, however, it is beneficial to make a procedure more general by allowing the caller to provide arguments (also known as parameters) to the procedure. For instance, a "Brush your teeth" procedure might have an argument which is the type of toothpaste to use.

We can generalize our MoveRight example by defining an argument for "how far right" to move the image (in the original we moved it a fixed amount, 10 pixels). Each procedure (to) block has slots for arguments (labeled "arg"). Here, we want to set up a placeholder, a name, to catch the value that the caller will send us. We do this by going to the Built-In palette and the drawer for Definitions and selecting the name block. In this case, we drag the name block into the arg slot of the moveRight procedure and give it the name "distance":


What we've specified so far is that when some other piece of code calls moveRight, it should also send an argument for the distance. Of course moveRight needs to make use of that argument instead of always moving 10. We do this by first dragging the number 10 block into the left panel to delete it. We then go to the My Program drawer within My Blocks and see that App Inventor has created a value block for the new distance argument we created. We drag this value block and hook it into the + block:

Walla! Our procedure moveRight is now more general. Other code can call it and specify the distance each time it is called.

But defining this procedure only sets up an abstraction for us. Our program doesn't yet make use of it. We need to change the caller-- the Timer event-handler-- so that it calls moveRight and supplies a distance for the argument. Just for fun, we'll send in 15 so that MoveRight, on timer events, will move the object 15 pixels:


Note that we can also use the MoveRight in our other event-handlers. For instance, if we want the ball to move back 100 pixles when it hits the edge, we can call MoveRight with a negative number:

In a full-fledged programming language, we could further generalize the procedure by making the ball or image that is moved an argument as well. This would allow MoveRight to be applied to any image. However, the current App Inventor environment doesn't allow this.

Procedures with Return Values

Some procedures, like moveRight, just perform some operations. Others procedures are also are responsible for computing and returning a result to the caller. For instance, the + built-in block is a procedure that returns the sum of two things:


Unlike the moveRight procedure, + has a slot-peg coming out of the left-hand side. This slot peg can go into another block that expects a number, e.g., into the Ball.MoveTo block:

In later lessons, we'll write procedures that return values.

Key Concepts

Procedures make programs simpler through abstraction-- they allow a set of potentially many code blocks to be given a name, and that name be used to invoke those blocks.

Programmers don't like to re-program code they've already written. Programming languages allow them to create procedures that can be used over and over. The more general problem the procedure solves, the more it can be reused. With App Inventor:
  • You can create procedures of arbitrary complexity, then call them by name.
  • You can generalize procedures by adding arguments to their definition. The more general a procedure, the more often it can be reused.

Your Turn

Modify your BallAnimation project from your last tutorial by defining a procedure MoveHoriz that moves the ball an amount specified by an argument "distance".
  • If you haven't done so, complete the last tutorial.
  • Open your old app from the last tutorial and SaveAs into a new project "BallProc".
  • Create the MoveHoriz procedure.You'll grab some of the existing blocks and put them into that procedure.
  • Change the timer event so that it calls your procedure.
Document this application on your portfolio.