Tests
Tests
only output "true or "false
In
order to use the if command to direct the flow of control
through alternative sets of instructions, you need to know how to formulate test
expresssions of the type which if requires as
its first input. LOGO tests are fortunately at heart very simple objects.
Earlier
we identified a test
as a LOGO expression which evaluates to "true
or "false. This definition
should be taken at face value. At the most basic level, it means that a test
can be literally the words "true or "false.
It is not, of course, easy to imagine a circumstance in which it
would be useful to provide "true or "false
directly as
the first of if's inputs. But you can. You can say:
if
"true [pr [this always works]]
Whenever
LOGO meets this instruction, the instruction list provided as the second
input to if will be carried out. Always, because inevitably if
receives "true as its first input every
time. Similarly if you try
if "false [pr [you will never
see this]]
then
you will never see the words YOU WILL NEVER SEE THIS displayed on
screen.
Flags
Although you are unlikely to
resort to the direct provision of "true or
"false, a variant of the idea turns out
to be very useful. If a test is any expression which evaluates to
"true or "false, then
as well as the words "true
or "false, a test can also be any procedure
which outputs "true or "false.
Now, you will recall that the procedure thing
when given an input "name will output whatever value has
been associated with "name . So, even though it is obviously
not necessarily so, thing "name
- or its shorthand equivalent
:name - could output "true
or "false, as long "name had
been previously set up with one of these words as its value.
To make this more concrete, let us consider a variable with the name
"flag? You can imagine this as something which functions
like a a starter's flag, or for that matter any two-state signal or switch.
You could decide that a raised
flag (or a red light) means Stop! and a lowered flag (or a green light)
means Go!, or a forward lever means that the points guide the train
to the left hand track, while a lever pulled back would direct the train to the
right. We chose the name "flag? simply
because flag happens to be a word often used by programmers for switches
of this type. We used a question mark as the last letter of the
variable name to suggest that
you can also think of the variable as something like a yes-no question.
Provided we guarantee that the value of "flag?
is set as either "true or "false, then
thing "flag? ( or :flag?) is like a
question with just two answers. And because the output of of :flag is only "true
or "false, Logo
is happy to accept this expression
as the first input to an if, i.e. as a test,
which can be used to select one or other of the lists of instructions
which follow. For example, you might write:if :flag? [fire]
[take.aim]
The procedure fire is
of course not a primitive, but however you might choose to define it, what it does
will happen if the value associated with "flag? is "true.
If, on the other hand,
the value associated with "flag? is "false,
then take.aim (whatever that does)
will be carried out.
With a variable called "test?,
we can even reproduce the movement through a flow chart by
writing:
if :test? [go.right] [go.left]
Take
care with flags
There is, of course, an
element of risk in using variables
within the first input to if.
A test is an expression which evaluates to "trueor "false
and only "true or "false. It is therefore extremely important to ensure that variables used in this
way never have any other values. For its own part, if is not at all
fussy where the "trues and "falses come
from. You could even use primitives like
word and butlast to construct the words out
of meaningless character sequences. The instructionif word bl
"fall bl "set [pr [that's true]]
works for that reason
perfectly well since the expression word bl "fall bl "set evaluates
to "false.
But beware! If will complain bitterly if
you try to give it anything other than a "true or "false
as its first input.
Predicates
While
a flag is a useful device to have in your programming
armoury, you will normally find yourself formulating tests using special
procedures which are restricted, by their definition, to outputting either the
word "true
or the word "false. Procedures, or more specifically operations,
of this type are called predicates. (Although
predicate is often used as interchangable with test.
it is useful to reserve the term to distinguish procedures specifically
designed for use in tests from other procedures like thing
which may be used sometimes, but are not necessarily used, to implement
tests.)Primitive predicates
To get you going, your LOGO implementation will
provide you with a range of primitive predicates. They are usually
distinguished from other procedures by having names which end in a question
mark or with the letter p (for predicate). As far as
Logo is concerned, this final labelling - like that of our variable flag?
- is of no significance. But although it is essentially cosmetic,
you will find it helpful in interpreting
procedure definitions and it is a good idea to maintain the convention
when you develop tests expressions of your own.Aside from the restrictions
on their output, predicates are just normal operations. For instance, member?
is an operation which takes two inputs and which will output
"true if the first input is a member of the second
input and "false if not. List? is another
which outputs "true
when its one input is a list and "false otherwise.
If you want to confirm that these are normal operations, you can
try typing:
pr first list? [cat dog]
Because
[cat dog] is a list, list? [cat dog] outputs
the word "true. Because first receives
literally the word "true as input, it outputs "t.
(And pr
is happy to display the word "t.)
A list
of the most common primitive predicates can be found in the appendix Primitives.
The next page provides information on compound tests.
Ron Brasington
Department of Linguistic Science
The University of Reading
Reading
UK
E-mail: ron.brasington@rdg.ac.uk