about summary refs log tree commit diff stats
path: root/src/roster_list.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/roster_list.h')
0 files changed, 0 insertions, 0 deletions
='n8' href='#n8'>8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830





























































































































































































































































































































































































































































































































































































































































































































































































































































                                                                                                                                                                                
<HTML>
<HEAD>
<TITLE>Computer Science Logo Style vol 1 ch 4: Predicates</TITLE>
</HEAD>
<BODY>
<CITE>Computer Science Logo Style</CITE> volume 1:
<CITE>Symbolic Computing</CITE> 2/e Copyright (C) 1997 MIT
<H1>Predicates</H1>

<TABLE width="100%"><TR><TD>
<IMG SRC="../csls1.jpg" ALT="cover photo">
<TD><TABLE>
<TR><TD align="right"><CITE><A HREF="http://www.cs.berkeley.edu/~bh/">Brian
Harvey</A><BR>University of California, Berkeley</CITE>
<TR><TD align="right"><BR>
<TR><TD align="right"><A HREF="../pdf/v1ch04.pdf">Download PDF version</A>
<TR><TD align="right"><A HREF="../v1-toc2.html">Back to Table of Contents</A>
<TR><TD align="right"><A HREF="../v1ch3/v1ch3.html"><STRONG>BACK</STRONG></A>
chapter thread <A HREF="../v1ch5/v1ch5.html"><STRONG>NEXT</STRONG></A>
<TR><TD align="right"><A HREF="https://mitpress.mit.edu/books/computer-science-logo-style-second-edition-volume-1">MIT
Press web page for Computer Science Logo Style</A>
</TABLE></TABLE>

<HR>

<P>
By introducing variables in Chapter 3, we made it possible for a
procedure to operate on different data each time you invoke it.  But
the <EM>pattern</EM> of what the procedure does with the data remains
constant.  We can get even more variety out of our procedures if we
can vary the <EM>instructions</EM> that the procedure executes.  We
need a way to say, &quot;Sometimes do this; other times do that.&quot;

<P><H2>True or False</H2>

<P>One helpful metaphor is this:  When you invoke a command, you're giving
the computer an order.  &quot;Now hear this!  <CODE>Print</CODE> such-and-such!&quot;
But when you invoke an operation, you're asking the computer a <EM>
question.</EM>  &quot;What is the <CODE>first</CODE> member of such-and-such?&quot;

<P>In real life we single out as a special category <EM>
yes-or-no questions.</EM>
For example, these special questions form the basis of the
game Twenty Questions.  The corresponding
category in Logo is the <EM>predicate.</EM>
A predicate is an operation whose output is always either the word
<CODE>true</CODE> or the word <CODE>false</CODE>.

<P>For example, <CODE>listp</CODE> (pronounced &quot;list-pea&quot;) is a predicate
that takes one input.  The input can be any datum.  The output from
<CODE>listp</CODE> is <CODE>true</CODE> if the input is a list, <CODE>false</CODE> if the
input is a word.

<P><CODE>Wordp</CODE> is another predicate that takes one input.  The input can
be any datum.  The output from <CODE>wordp</CODE> is <CODE>true</CODE> if the input
is a word, <CODE>false</CODE> if the input is a list.  (This is the opposite
of the output from <CODE>listp</CODE>.)

<P><CODE>Emptyp</CODE> is also a predicate with one input.  The input can be any
datum. The output from <CODE>emptyp</CODE> is <CODE>true</CODE> if the input is
either the empty word or the empty list; if the input is anything
else, the output is <CODE>false</CODE>.

<P>You'll have noticed by now that predicates tend to have names ending
in the letter <CODE>p</CODE>.  This is not quite a universal rule, but almost.
It's a good idea to follow the same convention in naming your
own predicates.<SUP>*</SUP>

<P><SMALL><BLOCKQUOTE><SMALL><SUP>*</SUP>Many versions of Logo use a question mark at the end
of names of predicates, instead of a <CODE>p</CODE>.  For example, you may see <CODE>
list?</CODE> instead of <CODE>listp</CODE>.  Berkeley Logo accepts either form, but I
prefer the <CODE>p</CODE> version.</SMALL></BLOCKQUOTE></SMALL><P>

<P>As I'm describing primitive predicates, you might want to try them
out on the computer.  You can do experiments like this:

<P><PRE>? <U>print wordp &quot;hello</U>
true
? <U>print wordp [hello]</U>
false
? <U>print emptyp []</U>
true
? <U>print emptyp 0</U>
false
</PRE>

<P>Of course, most of the time you won't actually want to print
the output from a predicate.  You'll see in a few moments
how we can use a predicate to control the instructions carried out
in a procedure.

<P>But first here are a few more primitive predicates.  <CODE>Numberp</CODE> takes one
input, which can be any datum.  The output from <CODE>numberp</CODE> is <CODE>
true</CODE> if the input is a number, <CODE>false</CODE> otherwise.

<P><CODE>Equalp</CODE> takes two inputs, each of which can be any datum.  The output
from <CODE>equalp</CODE> is <CODE>true</CODE> if the two inputs are identical or if they're
both numbers and they're numerically equal.  That is, 3 and 3.0 are
numerically equal even though they're not identical words.  A list is
never equal to a word.

<P><PRE>? <U>print equalp 3 3.0</U>
true
? <U>print equalp &quot;hello [hello]</U>
false
? <U>print equalp &quot;hello first [hello]</U>
true
? <U>print equalp &quot; []</U>
false
? <U>print equalp [] butfirst [hello]</U>
true
</PRE>

<P>

<P>The equal sign (<CODE>=</CODE>) can
be used as an <EM>infix</EM> equivalent
of <CODE>equalp</CODE>:

<P><PRE>? <U>print &quot;hello = first [hello]</U>
true
? <U>print 2 = 3</U>
false
</PRE>

<P>As I mentioned in Chapter 2, if you use infix operations
you have to be careful about what is grouped with what.  It varies
between versions of Logo.  Here is an example I tried in Berkeley Logo:

<P><PRE>? <U>print first [hello] = &quot;hello</U>
f
</PRE>

<P>Among current commercial implementations, Object Logo and
Microworlds give the same answer <CODE>f</CODE>.  But here is the <EM>same</EM>
example in Logowriter:

<P><PRE>? <U>print first [hello] = &quot;hello</U>
true
</PRE>

<P>You can avoid confusion by using parentheses.  The following
instructions work reliably in any Logo:

<P><PRE>? <U>print (first [hello]) = &quot;hello</U>
true
? <U>print first ([hello] = &quot;hello)</U>
f
</PRE>

<P><CODE>Memberp</CODE> is a predicate with two inputs.  If the second input is a
list, then the first can be any datum.  If the second input is a word, then
the first must be a one-character word.  The output from <CODE>memberp</CODE>
is true if the first input is a member of the second input.

<P><PRE>? <U>print memberp &quot;rain [the rain in Spain]</U>
true
? <U>print memberp [the rain] [the rain in Spain]</U>
false
? <U>print memberp [the rain] [[the rain] in Spain]</U>
true
? <U>print memberp &quot;e &quot;please</U>
true
? <U>print memberp &quot;e &quot;plain</U>
false
</PRE>

<P><CODE>Lessp</CODE> and <CODE>greaterp</CODE> are predicates that take two inputs.
Both inputs must be numbers.  The output from <CODE>lessp</CODE> is <CODE>true</CODE> if
the first input is numerically less than the second; the output from <CODE>
greaterp</CODE> is true if the first is greater than the second.  Otherwise the
output is <CODE>false</CODE>.  (In particular, both <CODE>lessp</CODE> and <CODE>greaterp</CODE>
output <CODE>false</CODE> if the two inputs are equal.) The infix forms for <CODE>
lessp</CODE> (<CODE>&lt;</CODE>) and <CODE>greaterp</CODE> (<CODE>&gt;</CODE>) are also allowed.

<P><H2>Defining Your Own Predicates</H2>

<P>Here are two examples of how you can create new predicates:

<P><PRE>to vowelp :letter
output memberp :letter [a e i o u]
end

? <U>print vowelp &quot;e</U>
true
? <U>print vowelp &quot;g</U>
false

to oddp :number
output equalp (remainder :number 2) 1
end

? <U>print oddp 5</U>
true
? <U>print oddp 8</U>
false
</PRE>

<P><H2>Conditional Evaluation</H2>

<P> The main use of predicates is to
compute inputs to the primitive procedures <CODE>if</CODE> and <CODE>ifelse</CODE>.
We'll get to <CODE>ifelse</CODE> in a while, but first we'll explore <CODE>if</CODE>.

<P>
<CODE>If</CODE> is a command with two inputs.  The first input must
be either the word <CODE>true</CODE> or the word <CODE>false</CODE>.  The second input must
be a list containing Logo instructions.  If the first input is <CODE>true</CODE>,
the effect of <CODE>if</CODE> is to evaluate the instructions in the second input.
If the first input is <CODE>false</CODE>, <CODE>if</CODE> has no effect.

<P><PRE>? <U>if equalp 2 1+1 [print &quot;Yup.]</U>
Yup.
? <U>if equalp 3 2 [print &quot;Nope.]</U>
?
</PRE>

<P>Here is an example of how <CODE>if</CODE> can be used in a procedure.
This is an extension of the <CODE>converse</CODE> example in Chapter 3:

<P><PRE>to talk
local &quot;name
print [Please type your full name.]
make &quot;name readlist
print sentence [Your first name is] first :name
if (count :name) &gt; 2 ~
   [print sentence [Your middle name is] first bf :name]
print sentence [Your last name is] last :name
end

? <U>talk</U>
Please type your full name.
<U>George Washington</U>
Your first name is George
Your last name is Washington
? <U>talk</U>
Please type your full name.
<U>John Paul Jones</U>
Your first name is John
Your middle name is Paul
Your last name is Jones
</PRE>

<P><CODE>Talk</CODE> asks you to type your name and reads what you type
into a list, which is remembered in the variable named <CODE>
name</CODE>.  Your first and last names are printed as in the earlier
version.  If the list <CODE>:name</CODE> contains more than two members,
however, <CODE>talk</CODE> also prints the second member as your middle
name.  If <CODE>:name</CODE> contains only two members, <CODE>talk</CODE> assumes
that you don't have a middle name.

<P>&raquo;Write a procedure of your own that asks a question and uses <CODE>if</CODE> to
find out something about the response.

<P>You can use <CODE>if</CODE> to help in writing more interesting predicates.

<P><PRE>to about.computersp :sentence
if memberp &quot;computer :sentence [output &quot;true]
if memberp &quot;computers :sentence [output &quot;true]
if memberp &quot;programming :sentence [output &quot;true]
output &quot;false
end

? <U>print about.computersp [This book is about programming]</U>
true
? <U>print about.computersp [I like ice cream]</U>
false
?
</PRE>

<P>This procedure illustrates something I didn't explain before about <CODE>
output</CODE>: An <CODE>output</CODE> command finishes the evaluation of the
procedure in which it occurs.  For example, in <CODE>about.computersp</CODE>,
if the input sentence contains the word <CODE>computer</CODE>, the first <CODE>
if</CODE> evaluates the <CODE>output</CODE> instruction that is its second input.
The procedure immediately outputs the word <CODE>true</CODE>.  The remaining
instructions are not evaluated at all.

<P>&raquo;Write <CODE>past.tensep</CODE>, which takes a word as input and
outputs <CODE>true</CODE> if the word ends in <CODE>ed</CODE> or if it's one of a list of
exceptions, like <CODE>saw</CODE> and <CODE>went</CODE>.

<P>&raquo;Write <CODE>integerp</CODE>, which takes any Logo datum as input and
outputs <CODE>true</CODE> if and only if the datum is an integer (a number without a
fraction part).  Hint: a number with a fraction part will contain a decimal
point.

<P><H2>Choosing Between Alternatives</H2>

<P><CODE>If</CODE> gives the choice between carrying out some instructions and doing
nothing at all.  More generally, we may want to carry out either of <EM>
two</EM> sets of instructions, depending on the output from a predicate.
The primitive procedure <CODE>ifelse</CODE> meets this need.<SUP>*</SUP>  <CODE>Ifelse</CODE> is
an unusual primitive because it can be used either as a command or as an
operation.  We'll start with examples in which <CODE>ifelse</CODE> is used as a
command.

<P><SMALL><BLOCKQUOTE><SMALL><SUP>*</SUP>In some
versions of Logo, the name <CODE>if</CODE> is used both for the two-input command
discussed earlier and for the three-input one presented here.</SMALL></BLOCKQUOTE></SMALL><P><CODE>Ifelse</CODE> requires three inputs.  The first input must be either the word
<CODE>true</CODE> or the word <CODE>false</CODE>.  The second and third inputs must be
lists containing Logo instructions.  If the first input is <CODE>true</CODE>, the
effect of <CODE>if</CODE> is to evaluate the instructions in the second input.  If
the first input is <CODE>false</CODE>, the effect is to evaluate the instructions
in the third input.

<P><PRE>? <U>ifelse 4 = 2+2 [print &quot;Yup.] [print &quot;Nope.]</U>
Yup.
? <U>ifelse 4 = 3+5 [print &quot;Yup.] [print &quot;Nope.]</U>
Nope.
?
</PRE>

<P>
Here is an example of a procedure using <CODE>ifelse</CODE>:

<P><PRE>to groupie
local &quot;name
print [Hi, who are you?]
make &quot;name readlist
ifelse :name = [Ray Davies] ~
     [print [May I have your autograph?]] ~
     [print sentence &quot;Hi, first :name]
end

? <U>groupie</U>
Hi, who are you?
<U>Frank Sinatra</U>
Hi, Frank
? <U>groupie</U>
Hi, who are you?
<U>Ray Davies</U>
May I have your autograph?
</PRE>

<P>&raquo;Write an operation <CODE>color</CODE> that takes as input a word
representing a card, such as <CODE>10h</CODE> for the ten of hearts.  Its output
should be the word <CODE>red</CODE> if the card is a heart or a diamond, or <CODE>
black</CODE> if it's a spade or a club.

<P>&raquo;Write a conversational program that asks the user's name and figures
out how to address him or her.  For example:

<P><PRE>? <U>converse</U>
Hi, what's your name?
<U>Chris White</U>
Pleased to meet you, Chris.

? <U>converse</U>
Hi, what's your name?
<U>Ms. Grace Slick</U>
Pleased to meet you, Ms. Slick.

? <U>converse</U>
Hi, what's your name?
<U>J. Paul Getty</U>
Pleased to meet you, Paul.

? <U>converse</U>
Hi, what's your name?
<U>Sigmund Freud, M.D.</U>
Pleased to meet you, Dr. Freud.

? <U>converse</U>
Hi, what's your name?
<U>Mr. Lon Chaney, Jr.</U>
Pleased to meet you, Mr. Chaney.
</PRE>

<P>What should the program say if it meets Queen Elizabeth II?


<P><H2>Conditional Evaluation Another Way</H2>

<P>The use of <CODE>ifelse</CODE> in the <CODE>groupie</CODE> example above makes for
a rather long instruction line.  If you wanted to do several instructions
in each case, rather than just one <CODE>print</CODE>, the <CODE>if</CODE> line would become
impossible to read.  Logo provides another mechanism that is equivalent
to the <CODE>ifelse</CODE> command but may be easier to read.

<P><CODE>Test</CODE> is a command that takes one input.  The input must be
either the word <CODE>true</CODE> or the word <CODE>false</CODE>.  The effect of
<CODE>test</CODE> is just to remember what its input was in a special place.
You can think of this place as a variable without a name.  This
special variable is automatically local to the procedure from which
<CODE>test</CODE> is invoked.

<P><CODE>Iftrue</CODE> (abbreviation <CODE>ift</CODE>) is a command with one
input.  The input must be a list of Logo instructions.  The effect of
<CODE>iftrue</CODE> is to evaluate the instructions in its input only if the
unnamed variable set by the most recent <CODE>test</CODE> command in the same
procedure is <CODE>true</CODE>.  It is an error to use <CODE>iftrue</CODE> without
first using <CODE>test</CODE>.

<P><CODE>Iffalse</CODE> (abbreviation <CODE>iff</CODE>) is a command with one input, which
must be an instruction list.  The effect of <CODE>iffalse</CODE> is to evaluate
the instructions only if the remembered result of the most recent <CODE>test</CODE>
command is <CODE>false</CODE>.

<P><CODE>Iftrue</CODE> and <CODE>iffalse</CODE> can be invoked as many times as you like after
a <CODE>test</CODE>.  This allows you to break up a long sequence of conditionally evaluated
instructions into several instruction lines:

<P><PRE>to better.groupie
local &quot;name
print [Hi, who are you?]
make &quot;name readlist
test equalp :name [Ray Davies]
iftrue [print [Wow, can I have your autograph?]]
iftrue [print [And can I borrow a thousand dollars?]]
iffalse [print sentence [Oh, hello,] first :name]
end
</PRE>

<P><H2>About Those Brackets</H2>

<P>I hope that the problem I'm about to mention won't even have occurred
to you because you are so familiar with the idea of evaluation that
you understood right away.  But you'll probably have to explain it
to someone else, so I thought I'd bring it up here:

<P>

Some people get confused about why the second
input to <CODE>if</CODE> (and the second and third inputs to <CODE>ifelse</CODE>)
is surrounded by brackets but the first isn't.  That
is, they wonder, why don't we say

<P><PRE>if [equalp 2 3] [print &quot;really??]          ; (wrong!)
</PRE>

<P>They have this problem because someone lazily told them
to put brackets around the conditionally evaluated instructions without
ever explaining about brackets and quotation.

<P>I trust <EM>you</EM> aren't confused that way.  You understand that, as usual,
Logo evaluates the inputs to a procedure before invoking the procedure.  The
first input to <CODE>if</CODE> has to be either the word <CODE>true</CODE> or the word
<CODE>false</CODE>.  <EM>Before</EM> invoking <CODE>if</CODE>, Logo has to evaluate an
expression like <CODE>equalp 2 3</CODE> to compute the input.  (In this case, the
result output by <CODE>equalp</CODE> will be <CODE>false</CODE>.)  But if the <CODE>print</CODE>
instruction weren't quoted, Logo would evaluate it, too, <EM>before</EM>
invoking <CODE>if</CODE>.  That's not what we want.  We want the instruction list
<EM>itself</EM> to be the second input, so that <CODE>if</CODE> can decide whether
or not to carry out the instructions in the list.  So, as usual, we use
brackets to tell Logo to quote the list.

<P><CENTER><TABLE rules="groups" frame="void" border="2">
<THEAD>
<TR><TH>actual argument expression<TH>--&gt;<TH>actual argument value
<TBODY>
<TR><TD><CODE>equalp 2 3</CODE><TD>--&gt;<TD><CODE>false</CODE>
<TR><TD><CODE>[print &quot;really??]</CODE><TD>--&gt;<TD><CODE>[print &quot;really??]</CODE>
</TABLE></CENTER>

<P><H2>Logical Connectives</H2>

<P>Sometimes the condition under which you want to evaluate an instruction
is complicated.  You want to do it if <EM>both</EM> this <EM>and</EM> that
are true, or if <EM>either</EM> this <EM>or</EM> that is true.  Logo provides
operations for this purpose.

<P><CODE>And</CODE> is a predicate with two inputs.  Each input must be either the
word <CODE>true</CODE> or the word <CODE>false</CODE>.  The output from <CODE>and</CODE> is
<CODE>true</CODE> if both inputs are <CODE>true</CODE>; the output is <CODE>false</CODE> if
either input is <CODE>false</CODE>.  (<CODE>And</CODE> can take more than two inputs if
the entire expression is enclosed in parentheses.  In that case the output
from <CODE>and</CODE> will be <CODE>true</CODE> only if all of its inputs are <CODE>true</CODE>.)

<P><CODE>Or</CODE> is a predicate with two inputs.  Each input must be either the
word <CODE>true</CODE> or the word <CODE>false</CODE>.  The output from <CODE>or</CODE> is
<CODE>true</CODE> if either input is <CODE>true</CODE> (or both inputs are).  The
output is <CODE>false</CODE> if both inputs are <CODE>false</CODE>.  (Extra-input
<CODE>or</CODE> outputs <CODE>true</CODE> if any of its inputs are <CODE>true</CODE>, <CODE>
false</CODE> if all inputs are <CODE>false</CODE>.)

<P><CODE>Not</CODE> is a predicate with one input.  The input must be either the
word <CODE>true</CODE> or the word <CODE>false</CODE>.  The output from <CODE>not</CODE> is
the opposite of its input: <CODE>true</CODE> if the input is <CODE>false</CODE>, or
<CODE>false</CODE> if the input is <CODE>true</CODE>.

<P>

These three procedures are called <EM>logical connectives</EM> because
they connect logical expressions together into bigger ones.  (A <EM>
logical</EM> expression is one whose value is <CODE>true</CODE> or <CODE>
false</CODE>.) They can be useful in defining new predicates:

<P><PRE>to fullp :datum
output not emptyp :datum
end

to realwordp :datum
output and wordp :datum not numberp :datum
end

to digitp :datum
output and numberp :datum equalp count :datum 1
end
</PRE>

<P><H2><CODE>Ifelse</CODE> as an Operation</H2>

<P>So far, we have applied the idea of conditional evaluation only to
complete instructions.  It is also possible to choose between two
expressions to evaluate, by using <CODE>ifelse</CODE> as an
operation.

<P>When used as an operation, <CODE>ifelse</CODE> requires three inputs.  The first input
must be either the word <CODE>true</CODE> or the word <CODE>false</CODE>.  The second and third
inputs must be lists containing Logo expressions.  The output from
<CODE>ifelse</CODE> is the result of evaluating the second input, if the first input
is <CODE>true</CODE>, or the result of evaluating the third input, if the first
input is <CODE>false</CODE>.

<P><PRE>? <U>print sentence &quot;It's ifelse 2=3 [&quot;correct] [&quot;incorrect]</U>
It's incorrect
? <U>print ifelse emptyp [] [sum 2 3] [product 6 7]</U>
5
</PRE>

<P>Here is one of the classic examples of a procedure in which <CODE>ifelse</CODE> is
used as an operation.  This procedure is an operation that takes
a number as its input; it outputs the <EM>absolute value</EM> of the
number:

<P><PRE>to abs :number
output ifelse :number&lt;0 [-:number] [:number]
end
</PRE>

<P><H2>Expression Lists and Plumbing Diagrams</H2>

<P><CODE>If</CODE> and <CODE>ifelse</CODE> require <EM>instruction lists</EM> or <EM>
expression lists</EM> as inputs.  This requirement is part of their semantics,
not part of the syntax of an instruction.  Just as the arithmetic operators
require numbers as inputs (semantics), but those numeric values can be
provided either as explicit numbers in the instruction or as the result of
an arbitrarily complicated subexpression (syntax), the procedures that
require instruction or expression lists as input don't interpret those
inputs until after Logo has set up the plumbing for the instructions that
invoke them.

<P>What does that mean?  Consider the instruction

<P><PRE>ifelse &quot;false [&quot;stupid &quot;list] [print 23]
</PRE>

<P>Even though the second input to <CODE>ifelse</CODE>--that is, the first
of the two literal lists--makes no sense as an instruction list, this
instruction will work correctly without printing an error message.  The Logo
interpreter knows that <CODE>ifelse</CODE> accepts three inputs, and it sees that
the three input expressions provided are a literal (quoted) word and two
literal lists.  It sets up the plumbing without paying any attention to the
semantics of <CODE>ifelse</CODE>; in particular, Logo doesn't care whether the
given inputs are meaningful for use with <CODE>ifelse</CODE>.  Then, once <CODE>
ifelse</CODE> starts running, it examines its first input value.  Since that input
is the word <CODE>false</CODE>, the <CODE>ifelse</CODE> procedure ignores its second input
completely and executes the instruction in its third input.

<P>The use of quotation marks and square brackets to indicate literal inputs is
part of the plumbing syntax, not part of the procedure semantics.  Don't say,
&quot;<CODE>Ifelse</CODE> requires one predicate input and two inputs in square
brackets.&quot;  The instruction

<P><PRE>ifelse last [true false] list &quot;&quot;stupid &quot;&quot;list list bf &quot;sprint 23
</PRE>

<P>has a very different plumbing diagram (syntax) from that of the
earlier example, but provides exactly the same input values to <CODE>ifelse</CODE>.

<P>Consider these two instructions:

<P><CENTER><IMG SRC="https://people.eecs.berkeley.edu/~bh/v1ch4/printfirst.gif" ALT="figure: printfirst"></CENTER>

<P>Since the effect of <CODE>print</CODE> is easy to observe, it's not hard
to see the relationship among the instructions, the plumbing diagrams, and
the effects when these instructions are run.  Why are brackets used around
the <CODE>first</CODE> expression in one case but not in the other?  Because in one
case the expression is how we tell Logo to set up the plumbing diagram,
while in the second case we are giving <CODE>print</CODE> as input a literal list
that just happens to look like an expression.  When the context is something
like <CODE>ifelse</CODE> instead of <CODE>print</CODE>, the syntactic situation is really
quite similar, but may be harder to see.  Consider this instruction:

<P><PRE>print ifelse emptyp :a [emptyp :b] [emptyp :c]
</PRE>

<P>Why do we put brackets around two <CODE>emptyp</CODE> expressions but not
around another similar-looking one?  &raquo; Draw a plumbing diagram
for this instruction, paying no attention to your mental model of the
meaning of the <CODE>ifelse</CODE> procedure, treating it as if it were the
nonsense procedure <CODE>zot3</CODE>.  You will see that the first input to <CODE>
ifelse</CODE> is an expression whose value will be the word <CODE>true</CODE> or the word
<CODE>false</CODE>, because Logo will carry out that first <CODE>emptyp</CODE> computation
before invoking <CODE>ifelse</CODE>.  The remaining two inputs, however, are
literal lists that happen to contain the word <CODE>emptyp</CODE> but do not
involve an invocation of <CODE>emptyp</CODE> in the plumbing diagram.  Once <CODE>
ifelse</CODE> is actually invoked, precisely one of those two list inputs will be
interpreted as a Logo expression, for which a <EM>new</EM> plumbing diagram
is (in effect) drawn by Logo.  The other input list is ignored.

<P><H2>Stopping a Procedure</H2>

<P>I'd like to examine more closely one of the examples from the first
chapter:

<P><PRE>to music.quiz
print [Who is the greatest musician of all time?]
if equalp readlist [John Lennon] [print [That's right!] stop]
print [No, silly, it's John Lennon.]
end
</PRE>

<P>You now know about almost all of the primitive procedures
used in this example.  The only one we haven't discussed is the <CODE>stop</CODE>
command in the second instruction line.

<P><CODE>Stop</CODE> is a command that takes no inputs.  It is only allowed inside
a procedure; you can't type <CODE>stop</CODE> to a top-level prompt.  The effect
of <CODE>stop</CODE> is to finish the evaluation of the procedure in which it is
used.  Later instructions in the same procedure are skipped.

<P>Notice that <CODE>stop</CODE> does not stop <EM>all</EM> active procedures.  If procedure
A invokes procedure B, and there is a <CODE>stop</CODE> command in procedure B,
then procedure A continues after the point where it invoked B.

<P>Recall that the <CODE>output</CODE> command also stops the procedure that invokes
it.  The difference is that if you're writing an operation, which
should have an output, you use <CODE>output</CODE>; if you're writing a command,
which doesn't have an output, you use <CODE>stop</CODE>.

<P>In <CODE>music.quiz</CODE>, the effect of the <CODE>stop</CODE> is that if you get the right
answer, the final <CODE>print</CODE> instruction isn't evaluated.  The same effect
could have been written this way:

<P><PRE>ifelse equalp readlist [John Lennon] ~
    [print [That's right!]] ~
    [print [No, silly, it's John Lennon.]]
</PRE>

<P>The alternative form uses the three-input <CODE>ifelse</CODE> command.  One
advantage of using <CODE>stop</CODE> is precisely that it allows the use of
shorter lines.  But in this example, where there is only one
instruction after the <CODE>if</CODE>, it doesn't matter much.  <CODE>Stop</CODE> is
really useful when you want to stop only in an unusual situation and
otherwise you have a lot of work still to do:

<P><PRE>to quadratic :a :b :c
local &quot;discriminant
make &quot;discriminant (:b * :b)-(4 * :a * :c)
<U>if :discriminant &lt; 0 [print [No solution.] stop]</U>
make &quot;discriminant sqrt :discriminant
local &quot;x1
local &quot;x2
make &quot;x1 (-:b + :discriminant)/(2 * :a)
make &quot;x2 (-:b - :discriminant)/(2 * :a)
print (sentence [x =] :x1 [or] :x2)
end
</PRE>

<P>This procedure applies the quadratic formula to solve the
equation

<P><CENTER><EM>ax</EM>&#178;+<EM>bx</EM>+<EM>c</EM>=0</CENTER>

<P>The only interesting thing about this example for our present purpose
is the fact that sometimes there is no solution.  In that case the
procedure <CODE>stop</CODE>s as soon as it finds out.

<P>Don't forget that you need <CODE>stop</CODE> only if you want to stop a
procedure before its last instruction line.  A common mistake made by
beginners who've just learned about <CODE>stop</CODE> is to use it in every
procedure.  If you look back at the examples so far you'll see that
many procedures get along fine without invoking <CODE>stop</CODE>.

<P><H2>Improving the Quiz Program</H2>

<P>When I first introduced the <CODE>music.quiz</CODE> example in Chapter 1, we
hadn't discussed things like user procedures with inputs.  We are now in a
position to generalize the quiz program:

<P><PRE>to qa :question :answer
print :question
if equalp readlist :answer [print [That's right!] stop]
print sentence [Sorry, it's] :answer
end

to quiz
qa [Who is the best musician of all time?] [John Lennon]
qa [Who wrote &quot;Compulsory Miseducation&quot;?] [Paul Goodman]
qa [What color was George Washington's white horse?] [white]
qa [how much is 2+2?] [5]
end
</PRE>

Procedure <CODE>qa</CODE> is our old friend <CODE>music.quiz</CODE>, with variable
inputs instead of a fixed question and answer.  <CODE>Quiz</CODE> uses <CODE>qa</CODE> several
times to ask different questions.

<P>&raquo;Here are a couple of suggestions for further improvements you should
be able to make to <CODE>quiz</CODE> and <CODE>qa</CODE>:

<P>1.  <CODE>Qa</CODE> is very fussy about getting one particular answer to a
question. If you answer <CODE>Lennon</CODE> instead of <CODE>John Lennon</CODE>,
it'll tell you you're wrong.  There are a couple of ways you might fix
this.  One is to look for a single-word answer <EM>anywhere within</EM>
what the user types.  So if <CODE>:answer</CODE> is the word <CODE>Lennon</CODE>,
the program will accept &quot;<CODE>Lennon</CODE>,&quot; &quot;<CODE>John Lennon</CODE>,&quot; or &quot;<CODE>the
Lennon Sisters</CODE>.&quot;  The second approach would be for <CODE>qa</CODE> to take a
<EM>list</EM> of possible answers as its second input:

<P><PRE>qa [Who is the best musician of all time?] ~
   [[John Lennon] [Lennon] [the Beatles]]
</PRE>

<P><CODE>Qa</CODE> then has to use a different predicate, to see if what
the user types is any of the answers in the list.

<P>2.  By giving <CODE>quiz</CODE> a local variable named <CODE>score</CODE>, you could
have <CODE>quiz</CODE> and <CODE>qa</CODE> cooperate to keep track of how many
questions the user gets right.  At the end the score could be printed.
(This is an opportunity to think about the stylistic virtues and vices
of letting a subprocedure modify a variable that belongs to its
superprocedure.  If you say

<P><PRE>make &quot;score :score+1
</PRE>

<P>inside <CODE>qa</CODE>, doesn't that make <CODE>quiz</CODE> somewhat mysterious
to read?  For an alternative, read the next section.)

<P><H2>Reporting Success to a Superprocedure</H2>

<P>Suppose we want the quiz program to give the user three tries before
revealing the right answer.  There are several ways this could be
programmed.  Here is a way that uses the tools you already know about.

<P>The general idea is that the procedure that asks the question is
written as an <EM>operation,</EM> not as a command.  To be exact, it's a
predicate; it outputs <CODE>true</CODE> if the user gets the right answer.
This asking procedure, <CODE>ask.once</CODE>, is invoked as a subprocedure of
<CODE>ask.thrice</CODE>, which is in charge of allowing three tries.  <CODE>
ask.thrice</CODE> invokes <CODE>ask.once</CODE> up to three times, but stops if
<CODE>ask.once</CODE> reports success.

<P><PRE>to ask.thrice :question :answer
repeat 3 [if ask.once :question :answer [stop]]
print sentence [The answer is] :answer
end

to ask.once :question :answer
print :question
if equalp readlist :answer [print [Right!] output &quot;true]
print [Sorry, that's wrong.]
output &quot;false
end
</PRE>

<P>
You've seen <CODE>repeat</CODE> in the first chapter, but you haven't been formally
introduced.  <CODE>Repeat</CODE> is a command with two inputs.  The first input
must be a non-negative whole number.  The second input must be a list
of Logo instructions.  The effect of <CODE>repeat</CODE> is to evaluate its second
input, the instruction list, the number of times given as the first
input.

<P>The programming style used in this example is a little controversial.
In general, it's considered a good idea not to mix effect and output
in one procedure.  But in this example, <CODE>ask.once</CODE> has an effect (it
prints the question, reads an answer, and comments on its correctness)
and also an output (<CODE>true</CODE> or <CODE>false</CODE>).

<P>I think the general rule I've just cited is a good rule, but there
are exceptions to it.  Using an output of <CODE>true</CODE> or <CODE>false</CODE> to report
the success or failure of some process is one of the situations that
I consider acceptable style.  The real point of the rule, I think,
is to separate <EM>calculating</EM> something from <EM>
printing</EM> it.  For example, it's a mistake to write procedures like this
one:

<P><PRE>to <A NAME="prsecond">prsecond :datum
print first butfirst :datum
end
</PRE>

<P>
A more powerful technique is to write the <CODE>second</CODE> operation
from Chapter 2; instead of

<P><PRE>prsecond [something or other]
</PRE>

<P>you can then say

<P><PRE>print second [something or other]
</PRE>

<P>It may not be obvious from this example why I call <CODE>second</CODE>
more powerful than <CODE>prsecond</CODE>.  But remember that an operation can be
combined with other operations, as in the plumbing diagrams we used
earlier.  For example, the operation <CODE>second</CODE> can extract the word <CODE>
or</CODE> from the list as shown here.  But you can <EM>also</EM> use it as part of
a more complex instruction to extract the letter <CODE>o</CODE>:

<P><PRE>print first second [something or other]
</PRE>

<P>If you'd written the command <CODE>prsecond</CODE> to solve the
first problem, you'd have to start all over again to solve this new
one.  (Of course, both of these examples must seem pretty silly; why
bother extracting a word or a letter from this list?  But I'm trying
to use examples that are simple enough not to obscure this issue with
the kinds of complications we'll see in more interesting programs.)

<P>&raquo;If you made the improvements to <CODE>quiz</CODE> and <CODE>qa</CODE> that I
suggested earlier, you might like to see if they can fit easily with a new
version of <CODE>quiz</CODE> using <CODE>ask.thrice</CODE>.

<P><A HREF="../v1-toc2.html">(back to Table of Contents)</A>
<P><A HREF="../v1ch3/v1ch3.html"><STRONG>BACK</STRONG></A>
chapter thread <A HREF="../v1ch5/v1ch5.html"><STRONG>NEXT</STRONG></A>

<P>
<ADDRESS>
<A HREF="../index.html">Brian Harvey</A>, 
<CODE>bh@cs.berkeley.edu</CODE>
</ADDRESS>
</BODY>
</HTML>