Free Book Chapter 21 - Procedures
(Copied from http://www.appinventor.org/book2 chapter 21 to allow translation)
- These blocks are shown with Inline inputs, which reduces the width of the blocks. You can right-click blocks
to toggle between “Inline” and “External” inputs.
Defining Procedures and Reusing Blocks
Programming languages such as App Inventor
provide a base set of built-in functionality—in App
Inventor’s case, a base set of blocks. Programming
languages also provide a way to extend that
functionality by adding new functions (blocks) to
the language. In App Inventor, you do this by
defining procedures—named sequences of blocks
—that your app can call just as it calls App
Inventor’s predefined blocks. As you’ll see in this
chapter, being able to create such abstractions is
very important for solving complex problems,
which is the cornerstone of building truly
When parents tell their child, “Go brush your
teeth before bed,” they really mean, “Take your
toothbrush and toothpaste from the cabinet,
squeeze out some toothpaste onto the brush,
swivel the brush on each tooth for 10 seconds (ha!),” and so on. “Brush your teeth” is
an abstraction: a recognizable name for a sequence of lower-level instructions. In this
case, the parents are asking the child to perform the instructions that they’ve all
agreed mean “brush your teeth.”
In programming, you can create such named sequences of instructions. Some
programming languages call them functions or subprograms. In App Inventor, they’re
called procedures. A procedure is a named sequence of blocks that you can call from
any place in an app.
Figure 21-1 is an example of a procedure that estimates the distance, in miles,
between two GPS coordinates you send to it.
Figure 21-1. Procedure for computing the distance between points
Don’t worry too much about the internals of this procedure just yet; all you need to
realize at the moment is that procedures like this let you extend the language by
which you design and build programs. If every parent had to explain the steps of
“brush your teeth” to his or her child each night, that kid might not make it to the fifth
grade. It’s much more efficient to just say, “Brush your teeth,” and everyone can move
on with getting to bed at a reasonable hour.
Similarly, after you define the procedure distanceBetweenPoints, you can ignore
the details of how it works and simply refer to (call) the procedure’s name when
designing or coding a larger app. This type of abstraction is key to solving large
problems and lets us break down a large software project into more manageable
chunks of code.
Procedures also help reduce errors because they eliminate redundancy in your
code. With procedures, you can put a chunk of code in one place and then call it from
various places throughout your app. So, if you’re building an app that needs to know
the minimum distance between your current location and 10 other spots, you don’t
need to have 10 copies of the blocks shown in Figure 21-2. Instead, you just define the
distanceBetweenPoints procedure and then call it whenever you need it. The
alternative—copying and pasting blocks—is much more code-dependent (recall the
discussion from Chapter 19) and, consequently, error-prone because when you make
a change, you have to find all the other copies of those blocks and change each one
in the same way. Imagine trying to find the 5 to 10 places where you pasted a
particular chunk of code in an app with 1,000 lines or blocks! A procedure lets you
instead encapsulate blocks in one place, and then call it many times.
Procedures also help you build up a library of code that can be reused in many
apps. Even when building an app for a very specific purpose, experienced
programmers are always thinking of ways to create the code in such a way that you
can reuse it in other apps. Some programmers never even create apps, but instead
focus solely on building reusable code libraries for other programmers to use in their
The blocks in Figure 21-2 are from a Note Taker app. Take a look at the blocks and see
if you can you identify the redundant ones.
Figure 21-2. A Note Taker app with redundant code
The redundant blocks are the ones involving a for each block (actually the for
each and its nested blocks and the set NotesLabel.Text to above it). In all three for
each instances, the block’s job is to display the list of notes. In this app, this behavior
needs to take place in three event handlers: when a new item is added, when an item
is removed, and when the list is loaded from the database upon application launch.
When experienced programmers see such redundancy, a bell goes of in their
heads, probably even before they’ve copied and pasted the blocks in the first place.
They know that it’s best to encapsulate such redundancy into a procedure, both to
make the program more understandable and so that changes will be much easier to
Accordingly, an experienced programmer would create a procedure, move a copy
of the redundant blocks into it, and then call the procedure from the three places
containing the redundant blocks. The app will not behave any differently, but it will
be easier to maintain and easier for other programmers to work with. Such code
(block) reorganization is called refactoring.
Defining a Procedure
Let’s build a procedure to do the job of the redundant code blocks from Figure 21-2. In
App Inventor, you define a procedure in a manner similar to how you define variables.
From the Procedures drawer, drag out either a to procedure block or a to procedure
result block. Use the latter if your procedure should calculate some value and return
it (we’ll discuss this approach a bit later in the chapter).
After dragging out a to procedure block, you can change its default name by
clicking the word “procedure” and typing a new name. The redundant blocks that you
want to refactor carry out the job of displaying a list, so we’ll name the procedure
displayList, shown in Figure 21-4.
Figure 21-4. Click “procedure” to name your procedure
The next step is to add the blocks within the procedure. In this case, we’re using
blocks that already exist, so we’ll drag one of the original redundant blocks out of its
event handler and place it within the to displayList block, as shown in Figure 21-5.
Figure 21-5. The displayList procedure encapsulates the redundant code
Calling a Procedure
Procedures, like displayList and “brush your teeth,” are entities with the potential to
perform a task. However, they’ll only perform that task if they are called upon to do
so. Thus far, we’ve created a procedure but haven’t called it. To call a procedure means
to invoke it, or to make it happen.
In App Inventor, when you define a procedure, a call block is automatically added
to the Procedures drawer as shown in Figure 21-6.
Figure 21-6. A call block appears in the Procedures drawer when you define a
You’ve been using call blocks already to call App Inventor’s predefined functions,
such as Ball.MoveTo and Texting.SendMessage. When you define a procedure, you
have in essence created your own block; you’ve extended the App Inventor language.
Using the new call block, you can invoke your creation.
For the Note Taker app example, you’d drag out three call displayList blocks and
use them to replace the redundant code in the three event handlers. For instance, the
ListPicker1.AfterPicking event handler (for deleting a note) should be modified as
illustrated in Figure 21-7.
Figure 21-7. Using the displayList call to invoke the blocks now in the procedure
The Program Counter
To understand how the call block works, think of an app as having a pointer that
steps through the blocks that are performing functions. In computer science, this
pointer is called the program counter.
When the program counter is performing the blocks within an event handler and it
reaches a call block, it jumps over to the procedure and executes the blocks in it.
When the procedure completes, the program counter jumps back to its previous
location (the call block) and proceeds from there. So, for the Note Taker example, the
remove list item block is executed; then the program counter jumps to the
displayList procedure and performs the blocks in that procedure (setting the
NotesLabel.Text to the empty text, and the for each); and finally the program
counter returns to perform the TinyDB1.StoreValue block.
Adding Parameters to Your Procedure
The displayList procedure allows redundant code to be refactored into a single
place. The app is easier to understand because you can read the event handlers at a
high level and generally ignore the details of how a list is displayed. It is also helpful
because you might decide to modify how you display the list, and the procedure
makes it possible for you to make such a modification in a single place (instead of
The displayList procedure has limits in terms of its general usefulness, however.
The procedure only works for a specific list (notes) and displays that list in a specific
label (NotesLabel). You couldn’t use it to display a different data list—for example, a
list of the app’s users—because it is defined too specifically.
App Inventor and other languages provide a mechanism called parameters for
making procedures more general-purpose. Parameters comprise the information a
procedure needs to do its job. They provide the specifics of how the procedure should
be performed. In our bedtime tooth-brushing example, you might define “toothpaste
type” and “brushing time” as parameters of the procedure “brush your teeth.”
You define parameters for a procedure by clicking the blue icon at the upper-left of
the procedure definition. For the displayList procedure, we would define a
parameter named “list,” as shown in Figure 21-8.
Figure 21-8. The procedure now accepts a list as a parameter
Even with the parameter defined, the blocks still refer directly to the specific list
notes (it’s plugged into the “in list” slot of the for each). Because we want the
procedure to use the list we send in as a parameter, we replace the reference to
global notes with a reference to get list, as demonstrated in Figure 21-9.
Figure 21-9. Now the for each will use the list sent in
The new version of the procedure is more generic: calls to displayList can now
send it any list, and displayList will display it. When you add a parameter to a
procedure, App Inventor automatically puts a corresponding socket in the call block.
So, when the parameter list is added to displayList, the call blocks to displayList
look like Figure 21-10.
Figure 21-10. Calling displayList now requires you to specify which list to display
The parameter list within the procedure definition is called a formal parameter.
The corresponding socket within the call block is called an actual parameter. When
you call a procedure from somewhere in the app, you must supply an actual
parameter for each formal parameter of the procedure. You do this by filling in all the
sockets in the call.
For the Note Taker app, you add a reference get global notes as the actual
parameter. Figure 21-11 shows how ListPicker.AfterSelection should be modifed.
Figure 21-11. Calling the displayList with notes sent as the actual parameter
Now, when displayList is called, the list notes is sent over to the procedure and
placed in the parameter list. The program counter proceeds to execute the blocks in
the procedure, referring to the parameter list but really working with the variable
Because of the parameter, you can now use the procedure displayList with any
list, not just notes. For example, if the Note Taker app were shared among a list of
users and you wanted to display the list of users, you could call displayList and send
it the userList, as demonstrated in Figure 21-12.
Figure 21-12. The displayList procedure can now be used to display any list, not just
Returning Values from a Procedure
There is still one issue with the displayList procedure in terms of its general
usefulness—can you figure out what it is? As it’s currently written, it can display any
list of data, but it will always display that data in the label NotesLabel. What if you
wanted the list to be displayed in a different user interface object (e.g., you had a
different label for displaying the userList)?
One solution is to reconceptualize the procedure and change its job from
displaying a list in a particular label to simply returning a text object that you can
display anywhere. To do this, you use a procedure result block, depicted in
Figure 21-13, instead of the procedure block.
Figure 21-13. The procedure result block
You’ll notice that, when compared to the procedure block, the procedure result
block has an extra socket at the bottom. You place a variable in this slot and it’s
returned to the caller. So, just as the caller can send data to a procedure with a
parameter, a procedure can send data back with a return value.
Figure 21-14 shows the reworked version of the preceding procedure, this time
using a procedure result block. Observe that because the procedure is now doing a
different job, its name is changed from displayList to listToText.
Figure 21-14. listToText returns a text object that the caller can place in any label
In the blocks shown in Figure 21-14, a local variable text is defined to hold the data
as the procedure iterates through each item on the list. text is initialized as a local
variable, instead of a global one, because it is used only in this procedure.
This text variable replaces the overly specific NotesLabel component that was
being used in the displayList version of this procedure. When the for each
completes, the variable text contains the list items, with each item separated by a
newline character, \n (e.g., “item1\nitem2\item3”). This text variable is then plugged
into the return value socket.
When a procedure result is defined, its corresponding call blocks look different
than those for a procedure. Compare the call to listToText with the call to the
displayList in Figure 21-15.
Figure 21-15. The call on the right returns a value and so must be plugged into
The difference is that the call listToText has a plug on its left side. This is
because when the call is executed, the procedure will run through its task and then
return a value to the call block. That return value must be plugged into something.
In this case, the callers to displayList can plug that return value into any label
they want. For the Note Taker example, the three event handlers that need to display
a list will call the procedure, as shown in Figure 21-16.
Figure 21-16. Converting the list notes into text and displaying it in NotesLabel
The important point here is that because the procedure is completely generic and
doesn’t refer to any lists or labels specifically, another part of the app could use it to
display any list in any label, as exemplified in Figure 21-17.
Figure 21-17. The procedure is no longer tied to a particular Label component
Reusing Blocks Among Apps
Reusing code blocks through procedures need not be restricted to a single app. There
are many procedures, such as listToText, that you could use in just about any app
you create. In practice, organizations and programming communities build up code
libraries of procedures for their domains of interest.
Typically, programming languages provide an import utility through which you can
include library code in any app. App Inventor doesn’t yet have such a utility. The only
way to share procedures is to create a special library app and begin new app
development by saving a new copy of that app and working from it.
The distanceBetweenPoints Procedure
With the displayList (listToText) example, we characterized procedure definition as
a way to eliminate redundant code: you start writing code, find redundancies as you
go along, and refactor your code to eliminate them. Generally, however, a software
developer or team will design an app from the beginning with procedures and
reusable parts in mind. This sort of planning can save you significant time as the
Consider an app to determine the closest local hospital to the user’s current
location—something that would come in very handy in case of an emergency. Here’s
a high-level design description of the app:
When the app launches, find the distance, in miles, between the current location and the
first hospital. Then find it for the second hospital, and so on. When you have the distances,
determine the minimum distance and display the address (and/or a map) to that location.
From this description, can you determine the procedures this app needs?
Often, the verbs in such a description hint at the procedures you’ll need. Repetition
in your description, as indicated with the “so on,” is another clue. In this case, finding
the distance between two points and determining the minimum of some distances are
two necessary procedures.
Let’s think about the design of the procedure for finding the distance between two
points, which we’ll name distanceBetweenPoints (fine, so originality is not my strong
suit). When designing a procedure, you need to determine its inputs and outputs: the
parameters the caller will send to the procedure for it to do its job, and the result
value the procedure will send back to the caller. In this case, the caller needs to send
the latitude and longitude of both points to the procedure, as shown in Figure 21-18.
The procedure’s job is to return the distance, in miles.
Figure 21-18. The caller sends four input parameters and receives a distance
Figure 21-19 shows the procedure we encountered at the beginning of the chapter,
using a formula for approximating the mileage between two GPS coordinates.
Figure 21-19. distanceBetweenPoints procedure
Figure 21-20 shows blocks that make two calls to the procedure, each of which
finds the distance from the current location to a particular hospital.
For the first call, the actual parameters for the first point are the the current
readings from the LocationSensor, whereas the second point is defined by the GPS
coordinates for St. Mary’s Hospital. The resulting value is placed in the variable
distanceStMarys. The second call is similar but instead uses the data for CPMC
Hospital for the second point.
The app goes on to compare the two distances returned to determine which
hospital is closest. But, if there were more hospitals involved, you’d really need to
compare a list of distances to find the shortest. From what you’ve learned, can you
create a procedure called findMinimum that accepts a list of numbers as a parameter
and returns the index of the minimum?
Figure 21-20. Two calls to the distanceBetweenPoints procedure
Programming languages such as App Inventor provide a base set of built-in
functionality. Through the use of procedures, app inventors can extend that language
with new abstractions. App Inventor doesn’t provide a block for displaying a list, so
you build one. Need a block for computing the distance between GPS coordinates?
You can create your own.
The ability to define higher-level procedure blocks is the key to engineering large,
maintainable software and solving complex problems without being constantly
overwhelmed by all of the details. Procedures let you encapsulate code blocks and
give those blocks a name. While you program the procedure, you focus solely on the
details of those blocks. However, in programming the rest of the app, you now have
an abstraction—a name—that you can refer to at a high level.
from http://www.appinventor.org/bookChapters/chapter19.pdf for translation
(picture of hands holding paper with printed list)
As you’ve already seen, apps handle events and
make decisions; such processing is fundamental to
computing. But, the other fundamental part of an
app is its data—the information it processes. An
app’s data is rarely restricted to single memory slots
such as the score of a game. More often, it consists
of lists of information and complex, interrelated
items that must be organized just as carefully as
the app’s functionality.
In this chapter, we’ll examine the way App Inventor handles data. You’ll learn the
fundamentals of programming both static information, in which the data doesn’t change,
and dynamic information, in which data is entered by the end user. You’ll learn how to
work with lists, and then you’ll explore a more complex data structure involving lists of
lists and a multiple-choice quiz app.
Many apps process lists of data. For example, Facebook processes your list of
friends and lists of status reports. A quiz app works with a list of questions and
answers. A game might have a list of characters or all-time high scores.
You specify list data in App Inventor with a variable, but instead of naming a single
memory cell with the variable, you name a set of related memory cells. You specify
that a variable is multi-item by using either the make a list or create empty list
blocks. For instance, the variable phoneNumbers in Figure 19-2 defines a list of three
Figure 19-2. phoneNumbers names three memory cells initialized with the numbers
Creating a List Variable
You create a list variable in the Blocks Editor by using an initialize global variable
block and then plugging in a make a list block. You can fnd the make a list block
in the Lists drawer, and it has only two sockets. But you can specify the number of
sockets you want in the list by clicking on the blue icon and adding items, as depicted
in Figure 19-3.
Figure 19-3. Click the blue icon on make a list to change the number of items
You can plug any type of data into the “item” sockets of make a list. For the
phoneNumbers example, the items should be text objects, not numbers, because
phone numbers have dashes and other formatting symbols that you can’t put in a
number object, and you won’t be performing any calculations on the numbers (in
which case, you would want number objects, instead).
As your app runs, you’ll need to select items from the list; for example, a particular
question as the user traverses a quiz or a particular phone number chosen from a list.
You access items within a list by using an index; that is, by specifying a position in the
list. If a list has three items, you can access the items by using indices 1, 2, and 3. You
can use the select list item block to grab a particular item, as shown in Figure 19-5.
Figure 19-5. Selecting the second item of a list
With select list item, you plug in the list you want in the frst socket, and the
index you want in the second socket. For this phoneNumber sample, the result of
selecting the second item is “333–4444.”
In many apps, you’ll define a list of data and then allow the user to step through (or
traverse) it. The Presidents Quiz in Chapter 8 provides a good example of this: in that
app, when the user clicks a Next button, the next item is selected from a list of
questions and displayed.
The previous section showed how to select the second item of a list, but how do
you select the next item? When you traverse a list, the item number you’re selecting
changes each time; it’s your current position in the list. Therefore, you need to define a
variable to represent that current position. “index” is the common name for such a
variable, and it is usually initialized to 1 (the frst position in the list), as demonstrated
in Figure 19-6.
Figure 19-6. Initializing the variable index to 1
When the user does something to move to the next item, you increment the index
variable by adding a value of 1 to it, and then select from the list by using that
incremented value. Figure 19-6 shows the blocks for doing this.
Figure 19-6. Incrementing the index value and using the incremented value to select
the next list item
Let’s consider an example app with which the user can peruse each potential paint
color for his house by tapping a “ColorButton.” Each time the user taps, the button’s
color changes. When the user makes it through all of the possible colors, the app goes
back to the frst one.
For this example, we’ll use some basic colors. However, you could customize the
code blocks to iterate through any set of colors.
Your first step is to define a list variable for the colors list and initialize it with some
paint colors as items, as depicted in Figure 19-7.
Figure 19-7. Initializing the list colors with a list of paint colors
Next, define an index variable that tracks the current position in the list. It should
start at 1. You could give the variable a descriptive name such as currentColorIndex,
but if you aren’t dealing with multiple indexes in your app, you can just name it
“index”, as in Figure 19-6.
The user traverses to the next color in the list by clicking the ColorButton. Upon
each tap, the index should be incremented and the BackgroundColor of the button
should change to the currently selected item, as shown in Figure 19-8.
Figure 19-8. Each tap of the button changes its color
Let’s assume the button’s background is initially set to Red in the Component
Designer. The frst time the user taps the button, index changes from its initial value
of 1 to 2, and the button’s background color changes to the second item in the list,
green. The second time the user taps it, the index changes from 2 to 3, and the
background color switches to Blue.
But what do you think will happen the next time the user taps it?
If you said there would be an error, you’re right! index will become 4 and the app
will try to select the fourth item in the list, but the list only has three items. The app
will force close, or quit, and the user will see an error message like the one in
Figure 19-9. The error message displayed when the app tries to select a fourth item
from a three-item list
Obviously, that message is not something you want your app’s users to see. To
avoid that problem, add an if block to check whether the last color in the list has
been reached. If it has, the index can be changed back to 1 so that the first color is
again displayed, as illustrated in Figure 19-10.
Figure 19-10. Using an if to check whether the index value is larger than the length of
When the user taps the button, the index is incremented and then checked to see
if its value is too large. The index is compared to length of list, not 3; this way your
app will work even if you add items to the list. By checking if the index is greater than
your list length (versus checking if it is greater than the specifc number 3), you’ve
eliminated a code dependency in your app. A code dependency is a programming
term that describes code that is defined too specifically and lacks flexibility. Thus, if
you change something in one place—in our example here, you add items to your list
—you’ll need to search for every instance where you use that list and change it
As you can imagine, these kinds of dependencies can get messy very quickly, and
they generally lead to many more bugs for you to chase down, as well. In fact, the
design for our Color app contains another code dependency as it is currently
programmed. Can you fgure out what it is?
If you changed the first color in your list from red to some other color, the app
won’t work correctly unless you also remembered to change the initial
Button.BackgroundColor you set in the Component Designer. The way to eliminate
this code dependency is to set the initial ColorButton.BackgroundColor to the first
color in the list rather than to a specific color. Because this change involves behavior
that happens when your app first opens, you do this in the Screen.Initialize event
handler that is invoked when an app is launched, as illustrated in Figure 19-11.
Figure 19-11. Setting the BackgroundColor of the button to the first color in the list
when the app launches
The previous Color app involved a static list: one whose elements are defined by the
programmer (you) and whose items don’t change unless you change the blocks
themselves. More often, however, apps deal with dynamic data: information that
changes based on the end user entering new items, or new items being loaded in
from a database or web information source. In this section, we discuss an example
Note Taker app, in which the user enters notes in a form and can view all of her
Apps such as a Note Taker begin with an empty list. When you want a list that begins
empty, you defne it with the create empty list block, as depicted in Figure 19-12.
Figure 19-12. The blocks to defne a dynamic list don’t contain any predefined items
The first time someone launches the app, the notes list is empty. But when the user
types some data in a form and taps Submit, new notes will be added to the list. The
form might be as simple as the one shown in Figure 19-13.
Figure 19-13. Using a form to add new items to the notes list
When the user types a note and taps the Submit button, the app calls the add
items to list function to append the new item to the list, as illustrated in
Figure 19-14. Calling add items to list to add the new note when the user taps the
You can fnd the add items to list block in the List drawer. Be careful: there is
also an append to list block, but that one is a fairly rare block used to append one
entire list to another.
The contents of list variables, like all variables, are not visible to the user. The blocks in
Figure 19-13 add items to the list each time SubmitButton.Click is invoked, but the
user will not receive feedback that the list is growing until you program more blocks
to actually display the content of the list.
The simplest way to display a list in your app’s user interface is to use the same
method you use for displaying numbers and text: put the list in the Text property of a
Label component, as illustrated in Figure 19-15.
Figure 19-15. Displaying the list to the user by placing it in a label.
Unfortunately, this simple method of displaying a list isn’t very elegant; it puts the
list within parentheses, with each item separated by a space and not necessarily on
the same line. For instance, if the user were to type, “Will I ever finish this book?” as
the first note, and “I forget what my son looks like!” as the second, the app would
display the notes list similar to what we see in Figure 19-16.
Figure 19-16. These entries are listed using default formatting
In Chapter 20, you can see a more sophisticated way to display a list.
You can remove an item from a list by using the remove list item block, as shown in
Figure 19-17. Removing an item from a list
The blocks in Figure 19-17 remove the second item from the list named notes.
Generally, however, you won’t want to remove a fixed item (e.g., 2), but instead will
provide a mechanism for the user to choose the item to remove.
You can use the ListPicker component to provide the user with a way to select an
item. ListPicker comes with an associated button. When the button is tapped, the
ListPicker displays the items of a list from which the user can choose one. When the
user chooses an item, the app can remove it.
ListPicker is easy to program if you understand its key events, BeforePicking and
AfterPicking, and its key properties, Elements, Selection, and SelectionIndex (see
|BeforePicking: Triggered when button is clicked.
|Elements: The list of choices.
|AfterPicking: Triggered when user makes a choice.
|Selection: The user’s choice.
|SelectionIndex: Position of choice.
Table 19-1. The key events and properties of the ListPicker component
BeforePicking: Triggered when button is clicked. Elements: The list of choices.
AfterPicking: Triggered when user makes a choice. Selection: The user’s choice.
SelectionIndex: Position of choice.
The user triggers the ListPicker.BeforePicking event by tapping the ListPicker’s
associated button. In the ListPicker.BeforePicking event handler, you’ll set the
ListPicker.Elements property to a list variable so that the data in the list displays. For
the Note Taker app, you’d set Elements to the notes variable that contains your list of
notes, as shown in Figure 19-18.
Figure 19-18. The Elements property of ListPicker1 is set to the notes list
With these blocks, the items of the list notes will appear in the ListPicker. If there
were two notes, it would appear as shown in Figure 19-19.
Figure 19-19. The list of notes appears in the ListPicker
When the user chooses an item in the list, it triggers the ListPicker.AfterPicking
event. In this event handler, you can access the user’s selection in the
However, your goal in this example is to remove an item from the list, and the
remove item from list block expects an index, not an item. The Selection property
of the ListPicker is the actual data (the note), not the index. Therefore, you need to
use the SelectionIndex property instead because it provides you with the index of
the chosen item. It should be set as the index of the remove list item block, as
demonstrated in Figure 19-20.
Figure 19-20. Removing an item by using ListPicker.SelectionIndex
The items of a list can be of any type, including numbers, text, colors, or Boolean
values (true/false). But, the items of a list can also, themselves, be lists. Such complex
data structures are common. For example, a list of lists could be used to convert the
Presidents Quiz (Chapter 8) into a multiple-choice quiz. Let’s look again at the basic
structure of the Presidents Quiz, which is a list of questions and a list of answers, as
shown in Figure 19-21.
Figure 19-21. A list of questions and a list of answers
Each time the user answers a question, the app checks to see if it is correct by
comparing the answer to the current item in the AnswerList.
To make the quiz multiple choice, you need to keep an additional list, one which
stores the choices for each answer to each question. You specify such data by placing
three make a list blocks within an inner make a list block, as demonstrated in
Figure 19-22. A list of lists is formed by inserting make a list blocks as items within an
inner make a list block
Each item in the variable answerChoices is itself a list containing three items. If you
select an item from answerChoices, the result is a list. Now that you’ve populated your
multiple-choice answers, how would you display that to the user?
As with the Note Taker app, you could use a ListPicker to present the choices to
the user. If the index were named currentQuestionIndex, the
ListPicker.BeforePicking event would appear as shown in Figure 19-23.
Figure 19-23. Using the List Picker to present one of the list of answer choices to the
These blocks would take the current sublist of answerChoices and let the user
choose from it. So, if currentQuestionIndex were 1, the ListPicker would show a list
like the one in Figure 19-24.
Figure 19-24. The answer choices presented to the user for the first question
When the user chooses, you check the answer with the blocks shown in
Figure 19-25. Checking whether the user chose the correct answer
In these blocks, the user’s selection from the ListPicker is compared to the correct
answer, which is stored in a different list, AnswerList (because answerChoices provides
only the choices and does not denote the correct answer).
Lists are used in almost every app you can think of. Understanding how they work is
fundamental to programming. In this chapter, we explored one of the most common
programming patterns: using an index variable that starts at the beginning of the list
and is incremented until each list item is processed. If you can understand and
customize this pattern, you are indeed a programmer!
We then covered some of the other mechanisms for list manipulation, including
typical forms for letting the user add and remove items. Such programming requires
yet another level of abstraction, as you have to envision the dynamic data before it
really exists. After all, your lists are empty until the user puts something in them. If you
can understand this, you might even think of quitting your day job.
We concluded the chapter by introducing a complex data structure, a list of lists.
This is defnitely a difficult concept, but we explored it by using fixed data: the answer
choices for a multiple-choice quiz. If you mastered that and the rest of the chapter,
your final test is this: create an app that uses a list of lists but with dynamic data. One
example would be an app with which people can create their own multiple-choice
quizzes, extending even further the MakeQuiz app in Chapter 10. Good luck!
While you think about how you’ll tackle that, understand that our exploration of
lists isn’t done. In the next chapter, we continue the discussion and focus on list
iteration with a twist: applying functions to each item in a list.