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 instruction

if 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