about summary refs log tree commit diff stats
path: root/js/games/nluqo.github.io/~bh/v1ch2/okparens.gif
blob: d014eb306f66cdaf7d5c80b65be64702906cd279 (plain)
ofshex dumpascii
0000 47 49 46 38 37 61 c9 00 a1 00 f0 00 00 00 00 00 ff ff ff 2c 00 00 00 00 c9 00 a1 00 00 02 fe 84 GIF87a.............,............
0020 8f a9 cb ed 0f a3 9c b4 da 8b b3 de bc fb 0f 86 e2 48 96 e6 89 a6 ea ca b6 ee 0b c7 f2 4c d7 f6 .................H...........L..
0040 8d e7 fa ce f7 fe 0f 0c 0a 87 c4 a2 f1 88 44 06 96 01 03 b3 09 78 3a 99 d3 65 15 2a 8d 52 b5 56 ..............D......x:..e.*.R.V
0060 2e 76 9b 0d 83 c7 5d f2 b7 6c be aa bd 6b 31 fa 7d 8e b7 b7 08 68 f2 ae b3 47 f1 7c 9c be 0f 58 .v....]..l...k1.}....h...G.|...X
0080 f3 17 48 08 a3 37 58 98 b8 82 a8 d8 68 c2 e8 18 c9 71 28 59 09 02 69 79 d0 95 19 81 99 49 c7 f9 ..H..7X.....h....q(Y..iy.....I..
00a0 40 19 aa e9 49 aa 60 da b8 79 da e9 f2 94 4a 62 05 3a 33 ab 32 ba 68 b7 ca 42 a7 eb fa e5 7a d3 @...I.`..y....Jb.:3.2.h..B....z.
00c0 6b fb 27 3c 4c 2b 58 6b 5c 07 3b 52 bc 58 e7 3b 65 48 cc 2c e2 fc 52 dd b1 79 fd 48 1d c3 dd 92 k.'<L+Xk\.;R.X.;eH.,..R..y.H....
00e0 3d 99 2b ee a1 0b 5e 82 fe 08 bd 7b 36 4d 4e 9b 0b 2c 33 86 dd 94 fc 8e cd ba 5f 71 cb ff ef a0 =.+...^....{6MN..,3......._q....
0100 1c c0 4f 03 0b 3a 61 a7 cf 86 c0 58 86 14 06 f3 d3 50 d0 c3 89 f3 0e 46 94 48 91 de b4 fe 8c 34 ..O..:a....X.....P.....F.H.....4
0120 16 5e f2 f5 ea db 2b 8f e3 42 ee 42 88 cb a4 3d 95 2b b3 3c a3 c7 b2 25 49 6d 31 51 cc 2c a9 2e .^....+..B.B...=.+.<...%Im1Q.,..
0140 9d 4b 91 f8 d6 69 b2 06 61 27 03 92 9e 6a 26 20 1a 54 e8 82 9b 0d 98 1e 15 d5 d3 e2 86 a2 dc 6e .K...i..a'...j&..T.............n
0160 9a 8a 2a 95 61 33 a8 98 9c 76 bd e6 95 ab a8 ad 3f b5 0e ed 1a 02 6d d3 b4 50 03 9a b5 e9 76 28 ..*.a3...v......?.....m..P....v(
0180 d9 a5 6b 81 d6 95 fb 16 6e bf 74 7b f3 4a 70 4a b7 ac cf bf 27 98 01 0e 3c e1 f0 58 bd 41 49 19 ..k.....n.t{.JpJ....'...<..X.AI.
01a0 0e 97 78 a4 e4 c9 b0 28 5b be 3c 39 32 e6 cd 97 35 73 36 8a 37 eb 62 83 43 1e 5f 50 4c 7a 70 e3 ..x....([.<92...5s6.7.b.C._PLzp.
01c0 d3 a9 4b 27 46 39 ba f5 0f 81 a6 65 cf c6 50 db 76 8f dc b9 75 ef e8 fd da f7 ee e0 16 50 0b 37 ..K'F9.....e..P.v...u........P.7
01e0 47 7c 0f e1 e3 bf 71 27 67 ce f1 79 5c 3f a0 56 f1 52 9a b9 94 e4 e1 cb 45 4f a7 7e 94 98 b4 65 G|....q'g..y\?.V.R......EO.~...e
0200 a8 e0 91 3f 9f 03 78 77 f0 e8 0f 0a 3b 77 28 7e f9 3c d2 d7 07 f3 06 ed 3d fe f1 fc fe 4b d1 5f ...?..xw....;w(~.<......=....K._
0220 af 1e 32 3f 6d a3 45 53 f2 f9 87 60 78 e9 39 67 df 7d 03 ca e3 8c 75 e6 25 d8 1e 46 c5 d5 27 a0 ..2?m.ES...`x.9g.}....u.%..F..'.
0240 7b 10 42 22 61 32 fa 2d 08 20 86 02 c2 f3 cb 59 e4 d5 f2 21 44 0d ae a8 d0 3d fe 95 b8 d4 81 b3 {.B"a2.-.......Y...!D....=......
0260 a4 18 dd 5d 7d fd e6 a2 34 13 56 b8 cd 7e 14 3a 14 22 8b 2d 2a f8 63 7f 05 56 51 e1 91 2a 5e 28 ...]}...4.V..~.:.".-*.c..VQ..*^(
0280 64 86 3f c2 37 9f 76 4f 1a 37 15 83 ad ec e6 a3 76 bd 8c a4 65 76 cd 05 79 25 74 4b ae c6 a4 98 d.?.7.vO.7......v...ev..y%tK....
02a0 35 86 76 a3 99 16 92 a9 5c 98 6a 76 64 25 9b 6f 6a c4 5a 93 73 be e4 66 80 77 9e 64 a7 8d 7b 26 5.v.....\.jvd%.oj.Z.s..f.w.d..{&
02c0 e4 26 05 54 fe 19 e8 77 7a 12 ca 58 9a b1 21 ca 67 99 72 32 6a 4b 72 87 42 ea 97 9f 22 52 5a 29 .&.T...wz..X..!.g.r2jKr.B..."RZ)
02e0 9a 82 7e c6 69 a7 9e 7a c9 d5 a7 a2 8e ba 99 a4 8e f5 29 c9 a0 5f 3e 7a 6a 28 95 9d e2 8f 25 af ..~.i..z..........).._>zj(....%.
0300 b6 ba cf ac ae fe 63 2b 27 b1 56 92 2b 2b aa fe c7 ea ad c2 06 1b c9 ae a9 a2 5a fe c8 af 98 42 ......c+'.V.++............Z....B
0320 b6 6c 20 f1 c1 31 07 b4 6c 4c eb 86 1c d4 a6 71 ad b4 d8 56 1b ad b5 dc 66 eb ed b6 e2 e6 d4 6c .l...1..lL.....q...V....f......l
0340 b9 e6 16 04 98 b2 e7 22 56 e5 ba 17 65 a0 ae bb 9a 2a 2a 6f 45 f4 d6 6b 2f b2 f8 16 26 e8 be 40 ......."V...e....**oE..k/...&..@
0360 12 7b 27 a9 02 77 fa d7 c0 06 73 7a 9b bf b0 01 ab 70 9b 3c c4 db 1a c4 75 36 ec f0 aa 0d 4b ec .{'..w....sz.....p.<....u6....K.
0380 a8 c2 18 df 8b ef c6 fd 52 5c 31 c3 1a 27 4c b1 c7 97 ba 6b b2 be 97 6c e7 c5 4e 5c ce 88 70 be ........R\1..'L....k...l..N\..p.
03a0 22 b7 93 60 8f 44 16 89 45 7b 1b a7 5c 28 2e e7 49 c8 e3 39 59 59 07 e8 c3 22 fd 7c a0 91 2e c7 "..`.D..E{..\(..I..9YY...".|....
03c0 08 a7 0f 26 03 ad 64 d4 42 13 1d 25 9d dc d9 53 f3 8e 51 2b 47 60 d5 df 90 0c 12 7c 1e 8a c7 85 ...&..d.B..%...S..Q+G`.....|....
03e0 77 5b 17 6d 71 38 8c c8 b2 25 d9 47 22 42 6e a6 67 a6 50 cc 1b 37 0f 9d e3 dd ef a6 4d 33 d3 4a w[.mq8...%.G"Bn.g.P..7......M3.J
0400 bb 3d ad de 68 cf ec b3 df 65 3f 19 1e dc 3c 87 0c 22 d6 86 1f be f5 20 34 7e 43 ed b4 4c cf 5e .=..h....e?...<.."......4~C..L.^
0420 b7 5d 4c d4 28 d5 a8 d1 20 2f be a8 bf a0 7f 37 72 e5 9f 83 5d fa d5 17 a3 2e 3a eb fb 8e 6e e9 .]L.(..../.....7r...].....:...n.
0440 eb ae 77 3c 7b bd b0 cf 2b bb e9 25 cf 76 70 ef be ff 0e fc ed 20 0f 4f 7c f1 c6 13 52 00 00 3b ..w<{...+..%.vp........O|...R..;
235'>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 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892
<P>
<A NAME="dumdee"></A>
<P><CENTER><IMG SRC="../ss-pics/tweedle.jpg" ALT="figure: tweedle"></CENTER><P><CENTER>&quot;Contrariwise,&quot; continued Tweedledee, &quot;if it was so,
it might be; and if it were so, it would be; but as it isn't, it ain't.
That's logic.&quot;
</CENTER><P>

<HTML>
<HEAD>
<TITLE>Simply Scheme: Introducing Computer Science ch 6: True and False</TITLE>
</HEAD>
<BODY>
<HR>
<CITE>Simply Scheme:</CITE>
<CITE>Introducing Computer Science</CITE> 2/e Copyright (C) 1999 MIT
<H2>Chapter 6</H2>
<H1>True and False</H1>

<TABLE width="100%"><TR><TD>
<IMG SRC="../simply.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"><CITE><A HREF="http://ccrma.stanford.edu/~matt">Matthew
Wright</A><BR>University of California, Santa Barbara</CITE>
<TR><TD align="right"><BR>
<TR><TD align="right"><A HREF="../pdf/ssch06.pdf">Download PDF version</A>
<TR><TD align="right"><A HREF="../ss-toc2.html">Back to Table of Contents</A>
<TR><TD align="right"><A HREF="../ssch5/words.html"><STRONG>BACK</STRONG></A>
chapter thread <A HREF="../ssch7/variables.html"><STRONG>NEXT</STRONG></A>
<TR><TD align="right"><A HREF="http://mitpress.mit.edu/0262082810">MIT
Press web page for <CITE>Simply Scheme</CITE></A>
</TABLE></TABLE>

<HR>


<P>We still need one more thing before we can write more interesting programs: 
the ability to make decisions.  Scheme has a way to say &quot;if this is true,
then do this thing, otherwise do something else.&quot;

<P>Here's a procedure that greets a person:

<P><PRE>(define (<A NAME="g63"></A>greet name)
  (if (equal? (first name) 'professor)
      (se '(i hope i am not bothering you) 'professor (last name))
      (se '(good to see you) (first name))))

&gt; (greet '(matt wright))
(GOOD TO SEE YOU MATT)

&gt; (greet '(professor harold abelson))
(I HOPE I AM NOT BOTHERING YOU PROFESSOR ABELSON)
</PRE>

<P>The program greets a person by checking to see if that person is a
professor.  If so, it says, &quot;I hope I am not bothering you&quot; and then the
professor's name.  But if it's a regular person, the program just says,
&quot;Good to see you,&quot; and then the person's first name.

<P><CODE>If</CODE> takes three arguments.  The first has to be either true or
false.
<A NAME="spif"></A>
<A NAME="g64"></A>
(We'll talk in a moment about exactly what true and false look like to
Scheme.)  In the above example, the first word of the person's name might or
might not be equal to the word &quot;Professor.&quot; The second and third arguments
are expressions; one or the other of them is evaluated depending on the
first argument.  The value of the entire <CODE>if</CODE> expression is the value of
either the second or the third argument.

<P>
You learned in Chapter 2 that Scheme includes a special data type
called <EM>Booleans</EM> to represent true or false
values.  There are just two of them: <A NAME="g65"></A><CODE>#t</CODE> for &quot;true&quot; and
<A NAME="g66"></A><CODE>#f</CODE> for &quot;false.&quot;<A NAME="dumbfalse"></A><A NAME="text1" HREF="true.html#ft1">[1]</A>

<P>We said that the first argument to <CODE>if</CODE> has to be true or false.  Of
course, it would be silly to say

<P>

<P><PRE>&gt; (if #t (+ 4 5) (* 2 7))
9
</PRE>

<P>
because what's the point of using <CODE>if</CODE> if we already know
which branch will be followed?  Instead, as in the <CODE>greet</CODE> example, we call
some procedure whose return value will be either true or false, depending on
the particular arguments we give it.

<P><H2>Predicates</H2>

<P>A function that returns either <CODE>#t</CODE> or <CODE>#f</CODE> is called a <EM>predicate.</EM><A NAME="text2" HREF="true.html#ft2">[2]</A> You've
already seen the <A NAME="g69"></A><CODE>equal?</CODE> predicate.  It takes two arguments, which
can be of any type, and returns <CODE>#t</CODE> if the two arguments are the same
value, or <CODE>#f</CODE> if they're different.  It's a convention in Scheme that
the names of predicates end with a question mark, but that's just a
convention.  Here are some other useful predicates:

<P>
<PRE>&gt; (member? 'mick '(dave dee dozy beaky mick and tich))
#T
&gt; (member? 'mick '(john paul george ringo))
#F
&gt; (member? 'e 'truly)
#F
</PRE>

<P>
<PRE>&gt; (member? 'y 'truly)
#T
&gt; (= 3 4)
#F
&gt; (= 67 67)
#T
&gt; (&gt; 98 97)
#T
&gt; (before? 'zorn 'coleman)
#F
&gt; (before? 'pete 'ringo)
#T
&gt; (empty? '(abbey road))
#F
&gt; (empty? '())
#T
&gt; (empty? 'hi)
#F
&gt; (empty? (bf (bf 'hi)))
#T
&gt; (empty? &quot;&quot;)
#T
</PRE>

<P>

<P><CODE>Member?</CODE> takes two arguments; it checks to see if the first
<A NAME="memq"></A>
<A NAME="g70"></A>
one is a member of the second.  The <A NAME="g71"></A><CODE>=</CODE>, <A NAME="g72"></A><CODE>&gt;</CODE>, <A NAME="g73"></A><CODE>&lt;</CODE>,
<A NAME="g74"></A><CODE>&gt;=</CODE>, and <A NAME="g75"></A><CODE>&lt;=</CODE> functions take two numbers as arguments and do the
obvious comparisons.  (By the way, these are exceptions to the convention about
question marks.)  <CODE>Before?</CODE> is like <CODE>&lt;</CODE>, but it compares two words
<A NAME="g76"></A>
alphabetically.  <CODE>Empty?</CODE> checks to see if its argument
<A NAME="g77"></A>
is either the empty word or the empty sentence.

<P>

<P>Why do we have both <CODE>equal?</CODE> and <CODE>=</CODE> in Scheme?  The first of these
works on any kind of Scheme data, while the second is defined only for
numbers.  You could get away with always using <CODE>equal?</CODE>, but the more
specific form makes your program more self-explanatory; people reading the
program know right away that you're comparing numbers.

<P>

<P>There are also several predicates that can be used to test the type of their
argument:

<P>

<P><PRE>&gt; (<A NAME="g78"></A>number? 'three)
#F
&gt; (number? 74)
#T
&gt; (<A NAME="g79"></A>boolean? #f)
#T
&gt; (boolean? '(the beatles))
#F
</PRE>

<P>
<PRE>&gt; (boolean? 234)
#F
&gt; (boolean? #t)
#T
&gt; (<A NAME="g80"></A>word? 'flying)
#T
&gt; (word? '(dig it))
#F
&gt; (word? 87)
#T
&gt; (<A NAME="g81"></A>sentence? 'wait)
#F
&gt; (sentence? '(what goes on))
#T
</PRE>

<P>Of course, we can also define new predicates:

<P>

<P><PRE>(define (vowel? letter)
  (member? letter 'aeiou))

(define (positive? number)
  (&gt; number 0))
</PRE>

<P><H2>Using Predicates</H2>

<P>Here's a procedure that returns the absolute value of a number:

<P>

<P><PRE>(define (<A NAME="g82"></A>abs num)
  (if (&lt; num 0)
      (- num)
      num))
</PRE>

<P>

<P>(If you call <A NAME="g83"></A><CODE>-</CODE> with just one argument, it returns the
negative of that argument.)  Scheme actually provides <A NAME="g84"></A><CODE>abs</CODE> as a
primitive procedure, but we can redefine it.

<P>Do you remember how to play buzz?  You're all sitting around the campfire
and you go around the circle counting up from one.  Each person says a
number.  If your number is divisible by seven or if one of its digits is a
seven, then instead of calling out your number, you say &quot;buzz.&quot;

<P><PRE>(define (<A NAME="g85"></A>buzz num)
  (if (or (divisible? num 7) (member? 7 num))
      'buzz
      num))

(define (<A NAME="g86"></A>divisible? big little)
  (= (remainder big little) 0))
</PRE>

<P><CODE>Or</CODE> can take any number of arguments, each of which must be
true or false.  It returns true if any of its arguments are true, that is, if
the first argument is true <EM>or</EM> the second argument is true <EM>or</EM>&hellip  (<CODE>Remainder</CODE>, as you know, takes two integers and tells
you what the remainder is when you divide the first by the second.  If the
remainder is zero, the first number is divisible by the second.)

<P><CODE>Or</CODE> is one of three functions in Scheme that combine true or false
values to produce another true or false value.  <CODE>And</CODE> returns true if
<A NAME="g87"></A> all of its arguments are true, that is, the first <EM>and</EM>
second <EM>and</EM>&hellip  Finally, there's a function <A NAME="g88"></A><CODE>not</CODE> that
takes exactly one argument, returning true if that argument is false and
vice versa.

<P>In the last example, the procedure we really wanted to write was <CODE>buzz</CODE>,
but we found it useful to define <CODE>divisible?</CODE> also.  It's quite common
that the easiest way to solve some problem is to write a <EM>helper
procedure</EM> to do part of the work.  In this case the helper procedure
computes a function that's meaningful in itself, but sometimes you'll want
to write procedures with names like <CODE>buzz-helper</CODE> that are useful only
in the context of one particular problem.

<P>Let's write a program that takes a word as its argument and returns the
plural of that word.  Our first version will just put an &quot;s&quot; on the end:

<P><PRE>(define (plural wd)
  (word wd 's))

&gt; (plural 'beatle)
BEATLES

&gt; (plural 'computer)
COMPUTERS

&gt; (plural 'fly)
FLYS
</PRE>

<P>This works for most words, but not those that end in &quot;y.&quot; Here's
version two:

<P><PRE>(define (<A NAME="g89"></A>plural wd)
  (if (equal? (last wd) 'y)
      (word (bl wd) 'ies)
      (word wd 's)))
</PRE>

<P>This isn't exactly right either; it thinks that the plural of
&quot;boy&quot; is &quot;boies.&quot; We'll ask you to add some more rules in Exercise
<A HREF="true.html#plurex">6.12</A>.

<P><H2><CODE>If</CODE> Is a Special Form</H2>

<P>There are a few subtleties that we haven't told you about yet.  First of
all, <A NAME="g90"></A><CODE>if</CODE> is a <A NAME="g91"></A><A NAME="g92"></A>special form.  Remember that we're going to
need the value of only one of its last two arguments.  It would be wasteful
for Scheme to evaluate the other one.  So if you say

<P><PRE>(if (= 3 3)
    'sure
    (factorial 1000))
</PRE>

<P><CODE>if</CODE> won't compute the factorial of 1000 before returning
<CODE>sure</CODE>.

<P>The rule is that <CODE>if</CODE> always evaluates its first argument.  If the value
of that argument is true, then <CODE>if</CODE> evaluates its second argument and
returns its value.  If the value of the first argument is false, then <CODE>if</CODE> evaluates its third argument and returns that value.

<P><H2>So Are <CODE>And</CODE> and <CODE>Or</CODE></H2>

<P><CODE>And</CODE> and <A NAME="g93"></A><CODE>or</CODE> are also <A NAME="g94"></A><A NAME="g95"></A>special forms.  They evaluate
<A NAME="g96"></A> their arguments in order from left to right<A NAME="text3" HREF="true.html#ft3">[3]</A> and stop as soon as they can.  For <CODE>or</CODE>, this means
returning true as soon as any of the arguments is true.  <CODE>And</CODE> returns
false as soon as any argument is false.  This turns out to be useful in
cases like the following:

<P><PRE>(define (divisible? big small)
  (= (remainder big small) 0))

(define (<A NAME="g97"></A>num-divisible-by-4? x)
  (and (number? x) (divisible? x 4)))

&gt; (num-divisible-by-4? 16)
#T

&gt; (num-divisible-by-4? 6)
#F

&gt; (num-divisible-by-4? 'aardvark)
#F

&gt; (divisible? 'aardvark 4)
ERROR: AARDVARK IS NOT A NUMBER
</PRE>

<P>We want to see if <CODE>x</CODE> is a number, and, if so, if it's
divisible by <CODE>4</CODE>.  It would be an error to apply <CODE>divisible?</CODE> to a
nonnumber.  If <CODE>and</CODE> were an ordinary procedure, the two tests (<CODE>number?</CODE> and <CODE>divisible?</CODE>) would both be evaluated before we would
have a chance to pay attention to the result of the first one.  Instead, if
<CODE>x</CODE> turns out not to be a number, our procedure will return <CODE>#f</CODE>
without trying to divide it by <CODE>4</CODE>.

<P><H2>Everything That Isn't False Is True</H2>

<P><CODE>#T</CODE> isn't the only true value.  In fact, <EM>every</EM> value is
considered true except for <CODE>#f</CODE>.

<P><PRE>&gt; (if (+ 3 4) 'yes 'no)
YES
</PRE>

<P>This allows us to have <EM>semipredicates</EM> that give
slightly more information than just true or false.  For example, we can
write an integer quotient procedure.  That is to say, our procedure will
divide its first argument by the second, but only if the first is evenly
divisible by the second.  If not, our procedure will return <CODE>#f</CODE>.

<P><PRE>(define (<A NAME="g98"></A>integer-quotient big little)
  (if (divisible? big little)
      (/ big little)
      #f))

&gt; (integer-quotient 27 3)
9

&gt; (integer-quotient 12 5)
#F
</PRE>

<P><CODE>And</CODE> and <CODE>or</CODE> are also semipredicates.  We've already explained
that <CODE>or</CODE> returns a true result as soon as it evaluates a true
argument.  The particular true value that <CODE>or</CODE> returns is the value of
that first true argument:

<P><PRE>&gt; (or #f 3 #f 4)
3
</PRE>

<P><CODE>And</CODE> returns a true value only if all of its arguments are
true.  In that case, it returns the value of the last argument:

<P><PRE>&gt; (and 1 2 3 4 5)
5
</PRE>

<P>As an example in which this behavior is useful, we can rewrite
<CODE>integer-quotient</CODE> more tersely:

<P><PRE>(define (integer-quotient big little)        ;; alternate version
  (and (divisible? big little)
       (/ big little)))
</PRE>

<P><H2>Decisions, Decisions, Decisions</H2>

<P><CODE>If</CODE> is great for an either-or choice.  But sometimes there are several
possibilities to consider:

<P><PRE>(define (roman-value letter)
  (if (equal? letter 'i)
      1
      (if (equal? letter 'v)
          5
          (if (equal? letter 'x)
              10
              (if (equal? letter 'l)
                  50
                  (if (equal? letter 'c)
                      100
                      (if (equal? letter 'd)
                          500
                          (if (equal? letter 'm)
                              1000
                              'huh?))))))))
</PRE>

<P>That's pretty hideous.  Scheme provides a shorthand notation for
situations like this in which you have to choose from among several
possibilities: the <A NAME="g99"></A><A NAME="g100"></A>special form <A NAME="g101"></A><CODE>cond</CODE>.
<A NAME="cond"></A>

<P><PRE>(define (<A NAME="g102"></A>roman-value letter)
  (cond ((equal? letter 'i) 1)
        ((equal? letter 'v) 5)
        ((equal? letter 'x) 10)
        ((equal? letter 'l) 50)
        ((equal? letter 'c) 100)
        ((equal? letter 'd) 500)
        ((equal? letter 'm) 1000)
        (else 'huh?)))
</PRE>

<P>The tricky thing about <CODE>cond</CODE> is that it doesn't use parentheses in quite
<A NAME="g103"></A> the same way as the rest
of Scheme.  Ordinarily, parentheses mean procedure invocation.  In <CODE>cond</CODE>, <EM>most</EM> of the parentheses still mean that, but <EM>some</EM> of
them are used to group pairs of tests and results.  We've reproduced the
same <CODE>cond</CODE> expression below, indicating the funny ones in boldface.

<P><PRE>(define (roman-value letter)
  (cond <STRONG><BIG>(</BIG></STRONG>(equal? letter 'i) 1<STRONG><BIG>)</BIG></STRONG>
        <STRONG><BIG>(</BIG></STRONG>(equal? letter 'v) 5<STRONG><BIG>)</BIG></STRONG>
        <STRONG><BIG>(</BIG></STRONG>(equal? letter 'x) 10<STRONG><BIG>)</BIG></STRONG>
        <STRONG><BIG>(</BIG></STRONG>(equal? letter 'l) 50<STRONG><BIG>)</BIG></STRONG>
        <STRONG><BIG>(</BIG></STRONG>(equal? letter 'c) 100<STRONG><BIG>)</BIG></STRONG>
        <STRONG><BIG>(</BIG></STRONG>(equal? letter 'd) 500<STRONG><BIG>)</BIG></STRONG>
        <STRONG><BIG>(</BIG></STRONG>(equal? letter 'm) 1000<STRONG><BIG>)</BIG></STRONG>
        <STRONG><BIG>(</BIG></STRONG>else 'huh?<STRONG><BIG>)</BIG></STRONG> ))
</PRE>

<P><CODE>Cond</CODE> takes any number of arguments, each of which is <EM>two
expressions</EM> inside a pair of parentheses.  Each argument is called a <EM><A NAME="g104"></A><A NAME="g105"></A>cond clause.</EM> In the example above, one typical clause is

<P><PRE><STRONG><BIG>(</BIG></STRONG>(equal? letter 'l) 50<STRONG><BIG>)</BIG></STRONG>
</PRE>

<P>The outermost parentheses on that line enclose two expressions.
The first of the two expressions (the <EM>condition</EM>) is taken as
true or false, just like the first argument to <CODE>if</CODE>.  The second
expression of each pair (the <EM>consequent</EM>) is a candidate for
the return value of the entire <CODE>cond</CODE> invocation.

<P><CODE>Cond</CODE> examines its arguments from left to right.  Remember that since
<CODE>cond</CODE> is a special form, its arguments are not evaluated ahead of time.
For each argument, <CODE>cond</CODE> evaluates the first of the two expressions
within the argument.  If that value turns out to be true, then <CODE>cond</CODE>
evaluates the second expression in the same argument, and returns that value
without examining any further arguments.  But if the value is false, then
<CODE>cond</CODE> does <EM>not</EM> evaluate the second expression; instead, it goes
on to the next argument.

<P>By convention, the last argument always starts with the word <A NAME="g106"></A><CODE>else</CODE>
instead of an expression.  You can think of this as representing a true
value, but <CODE>else</CODE> doesn't mean true in any other context; you're only
allowed to use it as the condition of the last clause of a <CODE>cond</CODE>.<A NAME="text4" HREF="true.html#ft4">[4]</A>

<P>Don't get into bad habits of thinking about the appearance of
<CODE>cond</CODE> clauses in terms of &quot;two parentheses in a row.&quot;
That's often the case, but not always.  For example, here is a procedure that
translates Scheme true or false values (<CODE>#t</CODE> and <CODE>#f</CODE>)
into more human-readable words <CODE>true</CODE> and <CODE>false</CODE>.

<P><PRE>(define (<A NAME="g107"></A>truefalse value)
  (cond (value 'true)
	(else 'false)))

&gt; (truefalse (= 2 (+ 1 1)))
TRUE

&gt; (truefalse (= 5 (+ 2 2)))
FALSE
</PRE>

<P>When a <CODE>cond</CODE> tests several possible conditions, they might not
be <A NAME="g108"></A><A NAME="g109"></A>mutually exclusive.<A NAME="text5"
HREF="true.html#ft5">[5]</A> This can be either a source of error or an advantage in
writing efficient programs.  The trick is to make the <EM>most
restrictive</EM> test first.  For example, it would be an error to say

<P><PRE>(cond ((number? (first sent)) &hellip)           ;; wrong
      ((empty? sent) &hellip)
      &hellip)
</PRE>

<P>because the first test only makes sense once you've already
established that there <EM>is</EM> a first word of the sentence.
On the other hand, you don't have to say

<P><PRE>(cond ((empty? sent) &hellip)
      ((and (not (empty? sent)) (number? (first sent))) &hellip)
      &hellip)
</PRE>

<P>because you've already established that the sentence is nonempty
if you get as far as the second clause.

<P><H2><CODE>If</CODE> Is Composable</H2>

<P>Suppose we want to write a <CODE>greet</CODE> procedure that works like this:

<P><PRE>&gt; (greet '(brian epstein))
(PLEASED TO MEET YOU BRIAN - HOW ARE YOU?)

&gt; (greet '(professor donald knuth))
(PLEASED TO MEET YOU PROFESSOR KNUTH - HOW ARE YOU?)
</PRE>

<P>The response of the program in these two cases is almost the same;
the only difference is in the form of the person's name.

<P>This procedure could be written in two ways:

<P><PRE>(define (greet name)
  (if (equal? (first name) 'professor)
      (se '(pleased to meet you)
	  'professor
	  (last name)
	  '(- how are you?))
      (se '(pleased to meet you)
	  (first name)
	  '(- how are you?))))

(define (greet name)
  (se '(pleased to meet you)
      (if (equal? (first name) 'professor)
	  (se 'professor (last name))
	  (first name))
      '(- how are you?)))
</PRE>

<P>The second version avoids repeating the common parts of the
response by using <CODE>if</CODE> within a larger expression.

<P>Some people find it counterintuitive to use <CODE>if</CODE> as we did in the second
version.  Perhaps the reason is that in some other programming languages,
<CODE>if</CODE> is a &quot;command&quot; instead of a function like any other.  A mechanism
that selects one part of a program to run, and leaves out another part, may
seem too important to be a mere argument subexpression.  But in Scheme, the
value returned by <EM>every</EM> function can be used as part of a larger
expression.<A NAME="text6" HREF="true.html#ft6">[6]</A>

<P>We aren't saying anything new here.  We've already explained the idea of
composition of functions, and we're just making the same point again about
<CODE>if</CODE>.  But we've learned that many students expect <CODE>if</CODE> to be an
exception, so we're taking the opportunity to emphasize the point: There are
no exceptions to this rule.

<P><H2>Pitfalls</H2>

<P>The biggest pitfall in this chapter is the unusual notation of <CODE>cond</CODE>.  Keeping track of the parentheses that mean function invocation, as
usual, and the parentheses that just group the parts of a <CODE>cond</CODE> clause
is tricky until you get accustomed to it.

<P>Many people also have trouble with the asymmetry of the <A NAME="g110"></A><CODE>member?</CODE>
predicate.  The first argument is something small; the second is something
big.  (The order of arguments is the same as the order of a typical English
sentence about membership:  &quot;Is Mick a member of the Beatles?&quot;)
It seems pretty obvious when you look at an example in which both
arguments are quoted constant values, but you can get in trouble when you
define a procedure and use its parameters as the arguments to <CODE>member?</CODE>.
Compare writing a procedure that says, &quot;does the letter E appear in this
word?&quot; with one that says, &quot;is this letter a vowel?&quot;

<P>Many people try to use <CODE>and</CODE> and <CODE>or</CODE> with the full flexibility
of the corresponding English words.  Alas, Scheme is not English.  For
example, suppose you want to know whether the argument to a procedure is
either the word <CODE>yes</CODE> or the word <CODE>no</CODE>.  You can't say

<P>
<PRE>(equal? argument (or 'yes 'no))              ; wrong!
</PRE>

<P>This sounds promising:  &quot;Is the <CODE>argument</CODE> <CODE>equal</CODE> to
the word <CODE>yes</CODE> <CODE>or</CODE> the word <CODE>no</CODE>?&quot; But the arguments to <CODE>or</CODE> must be true-or-false values, not things you want to check for equality
with something else.  You have to make two separate equality tests:

<P><PRE>(or (equal? argument 'yes) (equal? argument 'no))
</PRE>

<P>In this particular case, you could also solve the problem by saying

<P><PRE>(member? argument '(yes no))
</PRE>

<P>but the question of trying to use <CODE>or</CODE> as if it were English
comes up in other cases for which <CODE>member?</CODE> won't help.

<P>This isn't exactly a pitfall, because it won't stop your program from
working, but programs like

<P><PRE>(define (odd? n)
  (if (not (even? n)) #t #f))
</PRE>

<P>are redundant.  Instead, you could just say

<P><PRE>(define (odd? n)
  (not (even? n)))
</PRE>

<P>since the value of <CODE>(not (even? n))</CODE> is already <CODE>#t</CODE> or
<CODE>#f</CODE>.

<P><H2>Boring Exercises</H2>

<P><B>6.1</B>&nbsp;&nbsp;What values are printed when you type these expressions to Scheme?  (Figure
it out in your head before you try it on the computer.)

<P><PRE>(cond ((= 3 4) '(this boy))
      ((&lt; 2 5) '(nowhere man))
      (else '(two of us)))

(cond (empty? 3)
      (square 7)
      (else 9))

(define (<A NAME="g111"></A>third-person-singular verb)
  (cond ((equal? verb 'be) 'is)
        ((equal? (last verb) 'o) (word verb 'es))
        (else (word verb 's))))

(third-person-singular 'go)
</PRE>


<P> 

<B>6.2</B>&nbsp;&nbsp;What values are printed when you type these expressions to Scheme?  (Figure
it out in your head before you try it on the computer.)

<P><PRE>(or #f #f #f #t)

(and #f #f #f #t)

(or (= 2 3) (= 4 3))

(not #f)

(or (not (= 2 3)) (= 4 3))

(or (and (= 2 3) (= 3 3)) (and (&lt; 2 3) (&lt; 3 4)))
</PRE>

<P><B>6.3</B>&nbsp;&nbsp;Rewrite the following procedure using a <CODE>cond</CODE> instead of the <CODE>if</CODE>s:

<P><PRE>(define (<A NAME="g112"></A>sign number)
  (if (&lt; number 0)
      'negative
      (if (= number 0)
	  'zero
	  'positive)))
</PRE>

<P>
<B>6.4</B>&nbsp;&nbsp;Rewrite the following procedure using an <CODE>if</CODE> instead of the <CODE>cond</CODE>:

<P><PRE>(define (<A NAME="g113"></A>utensil meal)
  (cond ((equal? meal 'chinese) 'chopsticks)
	(else 'fork)))
</PRE>

<P>
<P>
<H2>Real Exercises</H2>
<P>
Note: Writing helper procedures may be useful in solving some of these
problems.

<P><B>6.5</B>&nbsp;&nbsp;Write a procedure <A NAME="g114"></A><CODE>european-time</CODE> to convert a time from American
AM/PM notation into European 24-hour notation.  Also
write <A NAME="g115"></A><CODE>american-time</CODE>, which does the opposite:

<P><PRE>&gt; (european-time '(8 am))
8

&gt; (european-time '(4 pm))
16

&gt; (american-time 21)
(9 PM)

&gt; (american-time 12)
(12 PM)

&gt; (european-time '(12 am))
24
</PRE>

<P>Getting noon and midnight right is tricky.


<P>
<B>6.6</B>&nbsp;&nbsp;Write a predicate <A NAME="g116"></A><CODE>teen?</CODE> that returns true if its argument is between
13 and 19.


<P>
<B>6.7</B>&nbsp;&nbsp;Write a procedure <A NAME="g117"></A><CODE>type-of</CODE> that takes anything as its argument and
returns one of the words <CODE>word</CODE>, <CODE>sentence</CODE>, <CODE>number</CODE>, or
<CODE>boolean</CODE>:

<P><PRE>&gt; (type-of '(getting better))
SENTENCE

&gt; (type-of 'revolution)
WORD

&gt; (type-of (= 3 3))
BOOLEAN
</PRE>

<P>(Even though numbers are words, your procedure should return <CODE>number</CODE> if its argument is a number.)

<P>Feel free to check for more specific types, such as &quot;positive integer,&quot;
if you are so inclined.


<P>
<B>6.8</B>&nbsp;&nbsp;Write a procedure <A NAME="g118"></A><CODE>indef-article</CODE> that works like this:
<PRE>&gt; (indef-article 'beatle)
(A BEATLE)

&gt; (indef-article 'album)
(AN ALBUM)
</PRE>

<P>Don't worry about silent initial consonants like the <CODE>h</CODE> in <CODE>hour</CODE>.


<P>
<B>6.9</B>&nbsp;&nbsp;Sometimes you must choose the singular or the plural of a word:  <CODE>1 book</CODE> but <CODE>2 books</CODE>.  Write a procedure <A NAME="g119"></A><CODE>thismany</CODE> that takes
two arguments, a number and a singular noun, and combines them appropriately:

<P><PRE>&gt; (thismany 1 'partridge)
(1 PARTRIDGE)

&gt; (thismany 3 'french-hen)
(3 FRENCH-HENS)
</PRE>


<P>
<P>
<B>6.10</B>&nbsp;&nbsp;Write a procedure <A NAME="g120"></A><CODE>sort2</CODE> that takes as its argument a sentence
containing two numbers.  It should return a sentence containing the same two
numbers, but in ascending order:

<P><PRE>&gt; (sort2 '(5 7))
(5 7)

&gt; (sort2 '(7 5))
(5 7)
</PRE>

<P>
<B>6.11</B>&nbsp;&nbsp;Write a predicate <A NAME="g121"></A><CODE>valid-date?</CODE> that takes three numbers as arguments,
representing a month, a day of the month, and a year.  Your procedure should
return <CODE>#t</CODE> if the numbers represent a valid date (e.g., it isn't the
31st of September).  February has 29 days if the year is divisible by 4,
except that if the year is divisible by 100 it must also be divisible by 400.

<P><PRE>&gt; (valid-date? 10 4 1949)
#T

&gt; (valid-date? 20 4 1776)
#F

&gt; (valid-date? 5 0 1992)
#F

&gt; (valid-date? 2 29 1900)
#F

&gt; (valid-date? 2 29 2000)
#T
</PRE>

<P>
<B>6.12</B>&nbsp;&nbsp;Make <A NAME="g122"></A><CODE>plural</CODE> handle correctly words that end in <CODE>y</CODE> but have a
vowel before the <CODE>y</CODE>, such as <CODE>boy</CODE>.  Then teach it about words that
end in <CODE>x</CODE> (box).  What other special cases can you find?

<P><A NAME="plurex"></A>


<P>
<B>6.13</B>&nbsp;&nbsp;Write a better <A NAME="g123"></A><CODE>greet</CODE> procedure that understands as many different
kinds of names as you can think of:

<P><PRE>&gt; (greet '(john lennon))
(HELLO JOHN)

&gt; (greet '(dr marie curie))
(HELLO DR CURIE)

&gt; (greet '(dr martin luther king jr))
(HELLO DR KING)

&gt; (greet '(queen elizabeth))
(HELLO YOUR MAJESTY)

&gt; (greet '(david livingstone))
(DR LIVINGSTONE I PRESUME?)
</PRE>


<P>
<B>6.14</B>&nbsp;&nbsp;Write a procedure <A NAME="g124"></A><CODE>describe-time</CODE> that takes a number of seconds as its
argument and returns a more useful description of that amount of time:
<A NAME="desctime"></A>

<P><PRE>&gt; (describe-time 45)
(45 SECONDS)

&gt; (describe-time 930)
(15.5 MINUTES)

&gt; (describe-time 30000000000)
(9.506426344208686 CENTURIES)
</PRE>

<P>

<HR>
<A NAME="ft1" HREF="true.html#text1">[1]</A> In <EM>some</EM>
versions of Scheme, the <A NAME="g67"></A><A NAME="g68"></A>empty sentence is considered false.  That
is, <CODE>()</CODE> and <CODE>#f</CODE> may be the same thing.  The reason that we can't
be definite about this point is that older versions of Scheme follow the
traditional Lisp usage, in which the empty sentence is false, but since then
a standardization committee has come along and insisted that the two values
should be different.  In this book we'll consider them as different, but
we'll try to avoid examples in which it matters.  The main point is that you
shouldn't be surprised if you see something like this:

<P><PRE>&gt; (= 3 4)
()
</PRE>

<P>in the particular implementation of Scheme that you're using.
<P>
<A NAME="ft2" HREF="true.html#text2">[2]</A> Why is it called that?  Think about an English
sentence, such as &quot;Ringo is a drummer.&quot; As you may remember from elementary
school, &quot;Ringo&quot; is the <EM>subject</EM> of that sentence, and &quot;is a
drummer&quot; is the <EM>predicate.</EM> That predicate could be truthfully
attached to some subjects but not others.  For example, it's true of &quot;Neil
Peart&quot; but not of &quot;George Harrison.&quot; So the predicate &quot;is a drummer&quot;
can be thought of as a function whose value is true or false.<P>
<A NAME="ft3" HREF="true.html#text3">[3]</A> Since you
can start a new line in the middle of an expression, in some cases the
arguments will be &quot;top to bottom&quot; rather than &quot;left to right,&quot; but don't
forget that Scheme doesn't care about line breaks.  That's why Lisp
programmers always talk as if their programs were written on one enormously
long line.<P>
<A NAME="ft4" HREF="true.html#text4">[4]</A> What if you don't use an <CODE>else</CODE>
clause at all?  If none of the clauses has a true condition, then the return
value is unspecified.  In other words, always use <CODE>else</CODE>.<P>
<A NAME="ft5" HREF="true.html#text5">[5]</A> Conditions are mutually
exclusive if only one of them can be true at a time.<P>
<A NAME="ft6" HREF="true.html#text6">[6]</A> Strictly speaking, since the argument expressions to a
special form aren't evaluated, <CODE>if</CODE> is a function whose domain is
expressions, not their values.  But many special forms, including <CODE>if</CODE>,
<CODE>and</CODE>, and <CODE>or</CODE>, are designed to act as if they were ordinary
functions, the kind whose arguments Scheme evaluates in advance.  The only
difference is that it is sometimes possible for Scheme to figure out the
correct return value after evaluating only some of the arguments.  Most of
the time we'll just talk about the domains and ranges of these special forms
as if they were ordinary functions.<P>
<P><A HREF="../ss-toc2.html">(back to Table of Contents)</A><P>
<A HREF="../ssch5/words.html"><STRONG>BACK</STRONG></A>
chapter thread <A HREF="../ssch7/variables.html"><STRONG>NEXT</STRONG></A>

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