about summary refs log tree commit diff stats
path: root/js/games/nluqo.github.io/~bh/ssch20/io
diff options
context:
space:
mode:
Diffstat (limited to 'js/games/nluqo.github.io/~bh/ssch20/io')
-rw-r--r--js/games/nluqo.github.io/~bh/ssch20/io1333
1 files changed, 1333 insertions, 0 deletions
diff --git a/js/games/nluqo.github.io/~bh/ssch20/io b/js/games/nluqo.github.io/~bh/ssch20/io
new file mode 100644
index 0000000..c5e9623
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/ssch20/io
@@ -0,0 +1,1333 @@
+\input bkmacs
+\pagetag{\typing}
+\photo{}{\pspicture{4in}{io}{io}{}\vfill}
+\chapter{Input and Output}
+\chaptag{\io}
+
+
+In the tic-tac-toe project in Chapter \ttt, we didn't write a complete game
+program.  We wrote a {\it function\/} that took a board position and {\tt x}
+or {\tt o} as arguments, returning the next move.  We noted at the time that
+a complete game program would also need to carry on a {\it conversation\/}
+with the user.  Instead of computing and returning one single value, a
+\bkidx{conversational}{program} must carry out a sequence of events in time,
+reading information from the \idx{keyboard} and displaying other information
+on the \idx{screen}.
+
+Before we complete the tic-tac-toe project, we'll start by
+exploring Scheme's mechanisms for \bkidx{interactive}{programming}.
+
+\backskipsubhd{Printing}{5}
+\justidx{printing}
+
+Up until now, we've never told Scheme to print anything.  The programs we've
+written have computed values and returned them; we've relied on the
+\idx{read-eval-print loop} to print these values.\footnt{The only
+exception is that we've used {\tt trace}, which prints messages about
+the progress of a computation.}
+
+But let's say we want to write a program to print out all of the words to
+``99 Bottles of Beer on the Wall.'' We could implement a function to produce a
+humongous {\it list\/} of the lines of the song, like this:
+
+{\prgex%
+(define (bottles n)
+  (if (= n 0)
+      '()
+      (append (verse n)
+	      (bottles (- n 1)))))
+}
+
+{\medskipamount=4pt\prgexskipamount=9pt\prgexbaselineamount=10pt
+{\prgex%
+(define (verse n)
+  (list (cons n '(bottles of beer on the wall))
+	(cons n '(bottles of beer))
+	'(if one of those bottles should happen to fall)
+	(cons (- n 1) '(bottles of beer on the wall))
+	'()))
+
+> (bottles 3)
+((3 BOTTLES OF BEER ON THE WALL)
+ (3 BOTTLES OF BEER)
+ (IF ONE OF THOSE BOTTLES SHOULD HAPPEN TO FALL)
+ (2 BOTTLES OF BEER ON THE WALL)
+ ()
+ (2 BOTTLES OF BEER ON THE WALL)
+ (2 BOTTLES OF BEER)
+ (IF ONE OF THOSE BOTTLES SHOULD HAPPEN TO FALL)
+ (1 BOTTLES OF BEER ON THE WALL)
+ ()
+ (1 BOTTLES OF BEER ON THE WALL)
+ (1 BOTTLES OF BEER)
+ (IF ONE OF THOSE BOTTLES SHOULD HAPPEN TO FALL)
+ (0 BOTTLES OF BEER ON THE WALL)
+ ())
+}
+
+\noindent The problem is that we don't want a list.  All we
+want is to print out the lines of the song; storing them in a data structure
+is unnecessary and inefficient.  Also, some versions of Scheme would print
+the above list like this:
+
+{\prgex%
+((3 BOTTLES OF BEER ON THE WALL) (3 BOTTLES OF BEER) (IF ONE OF
+ THOSE BOTTLES SHOULD HAPPEN TO FALL) (2 BOTTLES OF BEER ON THE
+ WALL) () (2 BOTTLES OF BEER ON THE WALL) (2 BOTTLES OF BEER) (IF
+ ONE OF THOSE BOTTLES SHOULD HAPPEN TO FALL) (1 BOTTLES OF BEER ON
+ THE WALL) () (1 BOTTLES OF BEER ON THE WALL) (1 BOTTLES OF BEER)
+ (IF ONE OF THOSE BOTTLES SHOULD HAPPEN TO FALL) (0 BOTTLES OF BEER
+ ON THE WALL) ())
+}
+
+\noindent or even all on one line.  We can't rely on Scheme's mechanism for
+printing lists if we want to be sure of a particular arrangement on the
+screen.
+
+Instead we'll write a program to {\it print\/} a verse, rather
+than return it in a list:
+\justtt{show}
+
+{\prgex%
+(define (\ufun{bottles} n)
+  (if (= n 0)
+      'burp
+      (begin (verse n)
+	     (bottles (- n 1)))))
+
+(define (\ufun{verse} n)
+  (show (cons n '(bottles of beer on the wall)))
+  (show (cons n '(bottles of beer)))
+  (show '(if one of those bottles should happen to fall))
+  (show (cons (- n 1) '(bottles of beer on the wall)))
+  (show '()))
+
+> (bottles 3)
+(3 BOTTLES OF BEER ON THE WALL)
+(3 BOTTLES OF BEER)
+(IF ONE OF THOSE BOTTLES SHOULD HAPPEN TO FALL)
+(2 BOTTLES OF BEER ON THE WALL)
+()
+(2 BOTTLES OF BEER ON THE WALL)
+(2 BOTTLES OF BEER)
+(IF ONE OF THOSE BOTTLES SHOULD HAPPEN TO FALL)
+(1 BOTTLES OF BEER ON THE WALL)
+()
+(1 BOTTLES OF BEER ON THE WALL)
+(1 BOTTLES OF BEER)
+(IF ONE OF THOSE BOTTLES SHOULD HAPPEN TO FALL)
+(0 BOTTLES OF BEER ON THE WALL)
+()
+BURP
+}
+
+} % skip kludges
+
+\noindent Notice that Scheme doesn't print an outer set of parentheses.
+Each line was printed separately; there isn't one big list containing all of
+them.\footnt{We know that it's still not as beautiful as can be, because of
+the capital letters and parentheses, but we'll get to that later.}
+
+Why was ``burp''\ printed at the end?  Just because we're printing things
+explicitly doesn't mean that the read-eval-print loop stops functioning.  We
+typed the expression {\tt (bottles~3)}.  In the course of evaluating that
+expression, Scheme printed several lines for us.  But the {\it value\/} of
+the expression was the word {\tt burp}, because that's what {\tt bottles}
+returned.
+
+\subhd{Side Effects and Sequencing}
+
+How does our program work?  There are two new ideas here:\ {\it
+\bkidx{side}{effect}s\/} and {\it sequencing.}
+
+Until now, whenever we've invoked a procedure, our only goal has been to get
+a return value.  The procedures we've used compute and return a value, and do
+nothing else.  {\tt Show} is different.  Although every Scheme procedure
+returns a value, the Scheme language standard doesn't specify what
+value the printing procedures should return.\footnt{Suppose {\tt show}
+returns {\tt \#f} in your version of Scheme.  Then you might see
+
+{\prgex%
+> (show 7)
+7
+#F
+}
+
+\noindent But since the return value is unspecified, we try to write
+programs in such a way that we never use {\tt show}'s return value as the
+return value from our procedures.  That's why we return values like {\tt
+burp}.} Instead, we are interested in their side effects.  In other words,
+we invoke {\tt show} because we want it to {\it do\/} something, namely,
+print its argument on the screen.
+
+What exactly do we mean by ``side effect''?  The kinds of procedures that
+we've used before this chapter can compute values, invoke helper procedures,
+provide arguments to the helper procedures, and return a value.  There may be
+a lot of activity going on within the procedure, but the procedure
+affects the world outside of itself only by returning a value that some
+other procedure might use.  {\tt Show} affects the world outside of itself
+by putting something on the screen.  After {\tt show} has finished its
+work, someone who looks at the screen can tell that {\tt show} was
+used.\footnt{The term {\it side\/} effect is based on the idea that a
+procedure may have a useful return value as its main purpose and may also
+have an effect ``on the side.'' It's a misnomer to talk about the
+side effect of {\tt show}, since the effect is its main purpose.  But nobody
+ever says ``side return value''!}
+
+{\medskipamount=4pt\prgexskipamount=9pt\prgexbaselineamount=10pt
+\def\psate{\prgexskipamount=8pt}
+
+Here's an example to illustrate the difference between values and effects:
+
+{\prgex%
+(define (\ufun{effect} x)
+  (show x)
+  'done)
+
+(define (\ufun{value} x)
+  x)
+
+> (effect '(oh! darling))
+(OH! DARLING)
+DONE
+
+> (value '(oh! darling))
+(OH! DARLING)
+
+> (bf (effect '(oh! darling)))
+(OH! DARLING)
+ONE\psate
+
+> (bf (value '(oh! darling)))
+(DARLING)
+
+> (define (\ufun{lots-of-effect} x)
+    (effect x)
+    (effect x)
+    (effect x))
+
+> (define (\ufun{lots-of-value} x)
+    (value x)
+    (value x)
+    (value x))
+
+> (lots-of-effect '(oh! darling))
+(OH! DARLING)
+(OH! DARLING)
+(OH! DARLING)
+DONE
+
+> (lots-of-value '(oh! darling))
+(OH! DARLING)
+}
+
+} % skip kludge
+
+This example also demonstrates the second new idea,
+\idx{sequencing}:  Each of {\tt effect}, {\tt lots-of-effect},
+and {\tt lots-of-value} contains more than one expression in
+its body.  When you invoke such a procedure, Scheme evaluates all
+the expressions in the body, in order, and returns the value of the
+last one.\footnt{In Chapter \defining, we said that the body of a
+procedure was always one single expression.  We lied.  But as long
+as you don't use any procedures with side effects, it doesn't do you
+any good to evaluate more than one expression in a body.} This also
+works in the body of a {\tt let}, which is really the body of a
+procedure, and in each clause of a {\ttidx cond}.\footnt{For example:
+
+{\zfprgex%
+> (cond ((< 4 0)
+	 (show '(how interesting))
+	 (show '(4 is less than zero?))
+	 #f)
+	((> 4 0)
+	 (show '(more reasonable))
+	 (show '(4 really is more than zero))
+	 'value)
+	(else
+	 (show '(you mean 4=0?))
+	 #f))
+(MORE REASONABLE)
+(4 REALLY IS MORE THAN ZERO)
+VALUE}}
+
+When we invoked {\tt lots-of-value}, Scheme invoked {\tt value} three times;
+it discarded the values returned by the first two invocations, and returned
+the value from the third invocation.  Similarly, when we invoked {\tt
+lots-of-effect}, Scheme invoked {\tt effect} three times and returned the
+value from the third invocation.  But each invocation of {\tt effect} caused
+its argument to be printed by invoking {\tt show}.
+
+\subhd{The \ttpmb{Begin} Special Form}
+\pagetag{\beg}
+
+The {\tt lots-of-effect} procedure accomplished sequencing by having more
+than one expression in its body.  This works fine if the sequence of events
+that you want to perform is the entire body of a procedure.  But in {\tt
+bottles} we wanted to include a sequence as one of the alternatives in an
+{\tt if} construction.  We couldn't just say
+
+{\prgex%
+(define (bottles n)                          ;; wrong
+  (if (= n 0)
+      '()
+      (verse n)
+      (bottles (- n 1))))
+}
+
+\noindent because {\tt if} must have exactly three arguments.  Otherwise,
+how would {\tt if} know whether we meant {\tt (verse~n)} to be the second
+expression in the true case, or the first expression in the false case?
+
+Instead, to turn the sequence of expressions into a single expression, we
+use the \bkidx{special}{form} \ttidx{begin}.  It takes any number of
+arguments, evaluates them from left to right, and returns the value of the
+last one.
+
+{\prgex%
+(define bottles n)
+  (if (= n 0)
+      'burp
+      (begin (verse n)
+	     (bottles (- n 1)))))
+}
+
+\noindent (One way to think about sequences in procedure bodies is that
+every procedure body has an invisible {\tt begin} surrounding it.)
+
+\subhd{This Isn't Functional Programming}
+
+Sequencing and side effects are radical departures from the idea of
+\bkidx{functional}{programming}.  In fact, we'd like to reserve the name {\it
+function\/} for something that computes and returns one value, with no side
+effects.  ``Procedure'' is the general term for the thing that {\tt lambda}
+returns---an embodiment of an algorithm.  If the algorithm is the kind that
+computes and returns a single value without side effects, then we say that
+the procedure implements a function.\footnt{Sometimes people sloppily
+say that the procedure {\it is\/} a function.  In fact, you may hear people
+be {\it really\/} sloppy and call a non-functional procedure a function!}
+
+There is a certain kind of sequencing even in functional programming.  If
+you say
+
+{\prgex%
+(* (+ 3 4) (- 92 15))
+}
+
+\noindent it's clear that the addition has to happen before the
+multiplication, because the result of the addition provides one of the
+arguments to the multiplication.  What's new in the sequential programming
+style is the {\it emphasis\/} on sequence, and the fact that the expressions
+in the sequence are {\it independent\/} instead of contributing values to
+each other.  In this multiplication problem, for example, we don't care
+whether the addition happens before or after the subtraction.  If the
+addition and subtraction were in a sequence, we'd be using them for
+independent purposes:
+
+{\prgex%
+(begin
+ (show (+ 3 4))
+ (show (- 92 15)))
+}
+
+\noindent This is what we mean by being independent.  Neither expression
+helps in computing the other.  And the order matters because we can see
+the order in which the results are printed.
+
+\subhd{Not Moving to the Next Line}
+
+Each invocation of {\tt show} prints a separate line.  What if we
+want a program that prints several things on the same line, like this:
+
+{\prgex%
+> (begin (show-addition 3 4)
+	 (show-addition 6 8)
+	 'done)
+3+4=7
+6+8=14
+DONE
+}
+
+\noindent We use \ttidx{display}, which doesn't move to the next line after
+printing its argument:
+
+{\prgex%
+(define (\ufun{show-addition} x y)
+  (display x)
+  (display '+)
+  (display y)
+  (display '=)
+  (show (+ x y)))
+}
+
+\noindent (The last one is a {\tt show} because we {\it do\/} want to start
+a new line after it.)
+
+What if you just want to print a blank line?  You use \ttidx{newline}:
+
+{\prgex%
+(define (verse n)
+  (show (cons n '(bottles of beer on the wall)))
+  (show (cons n '(bottles of beer)))
+  (show '(if one of those bottles should happen to fall))
+  (show (cons (- n 1) '(bottles of beer on the wall)))
+  (newline))                                 ; replaces (show '())
+}
+
+In fact, {\tt show} isn't an official Scheme primitive; we wrote it
+in terms of {\tt display} and {\tt newline}.
+
+\subhd{Strings}
+
+Throughout the book we've occasionally used strings, that is, words enclosed in
+double-quote marks so that Scheme will permit the use of punctuation or other
+unusual characters.  Strings also preserve the case of letters, so they can
+be used to beautify our song even more.  Since {\it any\/} character can be
+in a \idx{string}, including spaces, the easiest thing to do in this case is
+to treat all the letters, spaces, and punctuation characters of each line of
+the song as one long word.  (If we wanted to be able to compute functions of
+the individual words in each line, that wouldn't be such a good idea.)
+
+{\prgex%
+(define (\ufun{verse} n)
+  (display n)
+  (show " bottles of beer on the wall,")
+  (display n)
+  (show " bottles of beer.")
+  (show "If one of those bottles should happen to fall,")
+  (display (- n 1))
+  (show " bottles of beer on the wall.")
+  (newline))
+}
+
+{\medskipamount=4pt\prgexskipamount=8pt\prgexbaselineamount=10pt
+{\prgex%
+> (verse 6)
+6 bottles of beer on the wall,
+6 bottles of beer.
+If one of those bottles should happen to fall,
+5 bottles of beer on the wall.
+
+#F                               ; or whatever is returned by (newline)
+}
+
+% \def\vb{\vispc\penalty 0{}}
+% \def\vb{\_}
+\def\vb{\ }
+\noindent It's strange to think of ``{\tt\vb bottles\vb of\vb
+beer\vb on\vb the\vb wall,}'' as a single word.  But the rule is that
+anything inside double quotes counts as a single word.  It doesn't have to
+be an English word.
+
+\backskipsubhd{A Higher-Order Procedure for Sequencing}{8}
+
+Sometimes we want to print each element of a list separately:
+
+{\prgex%
+(define (\ufun{show-list} lst)
+  (if (null? lst)
+      'done
+      (begin (show (car lst))
+	     (show-list (cdr lst)))))
+
+> (show-list '((dig a pony) (doctor robert) (for you blue)))
+(DIG A PONY)
+(DOCTOR ROBERT)
+(FOR YOU BLUE)
+DONE
+}
+
+Like other patterns of computation involving lists, this one can be
+abstracted into a higher-order procedure.  (We can't call it a
+``higher-order function'' because this one is for computations with side
+effects.)  The procedure {\tt \ttidx{for-each}} is part of standard Scheme:
+
+{\prgex%
+> (for-each show '((mean mr mustard) (no reply) (tell me why)))
+(MEAN MR MUSTARD)
+(NO REPLY)
+(TELL ME WHY)
+}
+
+\noindent The value returned by {\tt for-each} is unspecified.
+
+Why couldn't we just use {\tt map} for this purpose?  There are two reasons.
+One is just an efficiency issue:  {\tt Map} constructs a list containing the
+values returned by each of its sub-computations; in this example, it would
+be a list of three instances of the unspecified value returned by {\tt
+show}. But we aren't going to use that list for anything, so there's no
+point in constructing it.  The second reason is more serious.  In functional
+programming, the order of evaluation of subexpressions is unspecified.  For
+example, when we evaluate the expression
+
+{\prgex%
+(- (+ 4 5) (* 6 7))
+}
+
+\noindent we don't know whether the addition or the multiplication happens
+first.  Similarly, the order in which {\tt map} computes the results for
+each element is unspecified.  That's okay as long as the ultimately returned
+list of results is in the right order.  But when we are using side effects,
+we {\it do\/} care about the order of evaluation.  In this case, we want
+to make sure that the elements of the argument list are printed from left to
+right.  {\tt For-each} guarantees this ordering.
+
+\backskipsubhd{Tic-Tac-Toe Revisited}{8}
+
+We're working up toward playing a game of tic-tac-toe against the computer.
+But as a first step, let's have the computer play against itself.  What we
+already have is {\tt ttt}, a {\it strategy\/} function:\ one that takes a
+board position as argument (and also a letter {\tt x} or {\tt o}) and
+returns the chosen next move.  In order to play a game of tic-tac-toe, we
+need two players; to make it more interesting, each should have its own
+strategy.  So we'll write another one, quickly, that just moves in the first
+empty square it sees:
+
+{\prgex%
+(define (\ufun{stupid-ttt} position letter)
+  (location '_ position))
+
+(define (\ufun{location} letter word)
+  (if (equal? letter (first word))
+      1
+      (+ 1 (location letter (bf word)))))
+}
+
+Now we can write a program that takes two strategies as arguments and
+actually plays a game between them.
+
+{\prgex%
+(define (\ufun{play-ttt} x-strat o-strat)
+  (play-ttt-helper x-strat o-strat '_________ 'x))
+
+(define (\ufun{play-ttt-helper} x-strat o-strat position whose-turn)
+  (cond ((already-won? position (opponent whose-turn))
+	 (list (opponent whose-turn) 'wins!))
+	((tie-game? position) '(tie game))
+	(else (let ((square (if (equal? whose-turn 'x)
+				(x-strat position 'x)
+				(o-strat position 'o))))
+		(play-ttt-helper x-strat
+				 o-strat
+				 (add-move square whose-turn position)
+				 (opponent whose-turn))))))
+}
+} % skip kludge
+
+\noindent We use a helper procedure because we need to keep track of two
+pieces of information besides the strategy procedures:\ the current board
+position and whose turn it is ({\tt x} or {\tt o}).  The helper procedure
+is invoked recursively for each move.  First it checks whether the game
+is already over (won or tied).\footnt{You wrote the procedures {\tt
+already-won?}\ and {\tt tie-game?}\ in Exercises \tttwon\ and \ttttied:
+
+{\prgex%
+(define (\ufun{already-won?} position who)
+  (member? (word who who who)  (find-triples position)))
+
+(define (\ufun{tie-game?} position)
+  (not (member? '_ position)))
+}}
+If not, the helper procedure invokes the current player's strategy procedure,
+which returns the square number for the next move.  For the recursive call,
+the arguments are the same two strategies, the new position after the move,
+and the letter for the other player.
+
+We still need {\tt add-move}, the procedure that takes a square and an old
+position as arguments and returns the new position.
+
+{\prgex%
+(define (\ufun{add-move} square letter position)
+  (if (= square 1)
+      (word letter (bf position))
+      (word (first position)
+	    (add-move (- square 1) letter (bf position)))))
+
+> (play-ttt ttt stupid-ttt)
+(X WINS!)
+
+> (play-ttt stupid-ttt ttt)
+(O WINS!)
+}
+
+\subhd{Accepting User Input}
+
+The work we did in the last section was purely functional.  We didn't print
+anything (except the ultimate return value, as always) and we didn't
+have to read information from a human player, because there wasn't one.
+
+You might expect that the structure of an {\it interactive\/} game program
+would be very different, with a top-level procedure full of sequential
+operations.  But the fact is that we hardly have to change anything to turn
+this into an interactive game.  All we need is a new ``strategy'' procedure
+that asks the user where to move, instead of computing a move based on
+built-in rules.
+
+{\prgex%
+(define (\ufun{ask-user} position letter)
+  (print-position position)
+  (display letter)
+  (display "'s move: ")
+  (read))
+
+(define (print-position position)            ;; first version
+  (show position))
+}
+
+\noindent (Ultimately we're going to want a beautiful two-dimensional
+display of the current position, but we don't want to get distracted by that
+just now.  That's why we've written a trivial temporary version.)
+
+{\prgex%
+> (play-ttt ttt ask-user)
+____X____
+O'S MOVE: \pmb{1}
+O___XX___
+O'S MOVE: \pmb{4}
+O__OXXX__
+O'S MOVE: \pmb{3}
+OXOOXXX__
+O'S MOVE: \pmb{8}
+(TIE GAME)
+}
+
+\noindent What the user typed is just the single digits shown in boldface at
+the ends of the lines.
+
+What's new here is that we invoke the procedure \ttidx{read}.  It waits for
+you to type a Scheme expression, and returns that expression.  Don't
+be confused:  {\tt Read} does {\it not\/} evaluate what you type.  It
+returns exactly the same expression that you type:
+
+{\prgex%
+(define (\ufun{echo})
+  (display "What? ")
+  (let ((expr (read)))
+    (if (equal? expr 'stop)
+	'okay
+	(begin
+	 (show expr)
+	 (echo)))))
+}
+
+{\medskipamount=2pt\prgexskipamount=7.5pt\prgexbaselineamount=10pt
+{\prgex%
+> (echo)
+What? \pmb{hello}
+HELLO
+What? \pmb{(+ 2 3)}
+(+ 2 3)
+What? \pmb{(first (glass onion))}
+(FIRST (GLASS ONION))
+What? \pmb{stop}
+OKAY
+}
+
+\backskipsubhd{Aesthetic Board Display}{9}
+
+Here's our beautiful position printer:
+
+{%\setbox2=\hbox{{\ninett +}}\catcode`+=\active\def+{\lower1pt\copy2}
+
+{\prgex%
+(define (\ufun{print-position} position)
+  (print-row (subword position 1 3))
+  (show "-+-+-")
+  (print-row (subword position 4 6))
+  (show "-+-+-")
+  (print-row (subword position 7 9))
+  (newline))
+
+(define (\ufun{print-row} row)
+  (maybe-display (first row))
+  (display "|")
+  (maybe-display (first (bf row)))
+  (display "|")
+  (maybe-display (last row))
+  (newline))
+
+(define (\ufun{maybe-display} letter)
+  (if (not (equal? letter '_))
+      (display letter)
+      (display " ")))
+
+(define (\ufun{subword} wd start end)
+  ((repeated bf (- start 1))
+   ((repeated bl (- (count wd) end))
+    wd)))\pgfoot
+\nobreak}
+\nobreak\vfootnt{Alternate version:
+\def\fpskip{\vskip 5pt\relax}
+{\prgex\fprgexbaselineamount=9.5pt%
+(define (subword wd start end)
+  (cond ((> start 1) (subword (bf wd) (- start 1) (- end 1)))
+	((< end (count wd)) (subword (bl wd) start end))
+	(else wd)))
+}
+
+\noindent You can take your choice, depending on which you think is easier,
+recursion or higher-order functions.
+}
+} % skip kludge
+
+Here's how it works:
+
+{\prgex%
+> (print-position '_x_oo__xx)
+ |X| 
+-+-+-
+O|O| 
+-+-+-
+ |X|X
+}
+} %%%%%%%%% active + kludge %%%%%%%%%%%%%
+
+\subhd{Reading and Writing Normal Text}
+
+The {\tt read} procedure works fine as long as what you type looks like a
+Lisp program.  That is, it reads one expression at a time.  In the
+tic-tac-toe program the user types a single number, which is a Scheme
+expression, so {\tt read} works fine.  But what if we want to read more than
+one word?
+
+{\prgex%
+(define (music-critic)                       ;; first version
+  (show "What's your favorite Beatles song?")
+  (let ((song (read)))
+    (show (se "I like" song "too."))))
+
+> (music-critic)
+What's your favorite Beatles song?
+\pmb{She Loves You}
+(I like SHE too.)
+}
+
+\noindent If the user had typed the song title in parentheses, then it would
+have been a single Scheme expression and {\tt read} would have accepted it.
+But we don't want the users of our program to have to be typing parentheses
+all the time.
+
+Scheme also lets you read one character at a time.  This allows you to read
+any text, with no constraints on its format.  The disadvantage is that you
+find yourself putting a lot of effort into minor details.  We've provided a
+procedure {\tt \ttidx{read-line}} that reads one line of input and returns a
+sentence.  The words in that sentence will contain any punctuation
+characters that appear on the line, including parentheses, which are not
+interpreted as sublist delimiters by {\tt read-line}.  {\tt Read-line} also
+preserves the case of letters.
+
+{\prgex%
+(define (music-critic)                       ;; second version
+  (read-line)   ; See explanation on next page.
+  (show "What's your favorite Beatles song?")
+  (let ((song (read-line)))
+    (show (se "I like" song "too."))))
+
+> (music-critic)
+What's your favorite Beatles song?
+\pmb{She Loves You}
+(I like She Loves You too.)
+}
+
+\noindent Why do we call {\tt read-line} and ignore its result at the
+beginning of {\tt music-critic}?  It has to do with the interaction between
+{\tt read-line} and {\tt read}.  {\tt Read} treats what you type as a
+sequence of Scheme expressions; each invocation of {\tt read} reads one of
+them.  {\tt Read} pays no attention to formatting details, such as several
+consecutive spaces or line breaks.  If, for example, you type several
+expressions on the same line, it will take several invocations of {\tt read}
+to read them all.
+
+By contrast, {\tt read-line} treats what you type as a sequence of lines,
+reading one line per invocation, so it does pay attention to line breaks.
+
+Either of these ways to read input is sensible in itself, but if you mix
+the two, by invoking {\tt read} sometimes and {\tt read-line} sometimes in
+the same program, the results can be confusing.  Suppose you type a line
+containing an expression and your program invokes {\tt read} to read it.
+Since there might have been another expression on the line, {\tt read}
+doesn't advance to the next line until you ask for the next
+expression.  So if you now invoke {\tt read-line}, thinking that it will
+read another line from the keyboard, it will instead return an empty list,
+because what it sees is an empty line---what's left after {\tt read} uses up
+the expression you typed.
+
+You may be thinking, ``But {\tt music-critic} doesn't call {\tt read}!''
+That's true, but Scheme itself used {\tt read} to read the expression that
+you used to invoke {\tt music-critic}.  So the first invocation of {\tt
+read-line} is needed to skip over the spurious empty line.
+
+Our solution works only if {\tt music-critic} is invoked directly at a
+Scheme prompt.  If {\tt music-critic} were a subprocedure of some larger
+program that has already called {\tt read-line} before calling {\tt
+music-critic}, the extra {\tt read-line} in {\tt music-critic} would really
+read and ignore a useful line of text.
+
+If you write a procedure using {\tt read-line} that will sometimes be called
+directly and sometimes be used as a subprocedure, you can't include an extra
+{\tt read-line} call in it.  Instead, when you call your procedure directly
+from the Scheme prompt, you must say
+
+{\prgex%
+> (begin (read-line) (my-procedure))
+}
+
+Another technical detail about {\tt read-line} is that since
+it preserves the capitalization of words, its result may
+include strings, which will be shown in quotation marks if you return the
+value rather than {\tt show}ing it:
+
+{\prgex%
+(define (music-critic-return)
+  (read-line)
+  (show "What's your favorite Beatles song?")
+  (let ((song (read-line)))
+    (se "I like" song "too.")))
+
+> (music-critic-return)
+What's your favorite Beatles song?
+\pmb{She Loves You}
+("I like" "She" "Loves" "You" "too.")
+}
+
+We have also provided {\tt \ttidx{show-line},} which takes a sentence
+as argument.  It prints the sentence without surrounding parentheses,
+followed by a newline.  (Actually, it takes any list as argument; it prints
+all the parentheses except for the outer ones.)
+
+{\prgex%
+(define (\ufun{music-critic})
+  (read-line)
+  (show "What's your favorite Beatles song?")
+  (let ((song (read-line)))
+    (show-line (se "I like" song "too."))))
+
+> (music-critic)
+What's your favorite Beatles song?
+\pmb{She Loves You}
+I like She Loves You too.
+}
+
+The difference between {\tt show} and {\tt show-line} isn't
+crucial.  It's just a matter of a pair of parentheses.  The point is that
+{\tt read-line} and {\tt show-line} go together.  {\tt Read-line} reads a
+bunch of disconnected words and combines them into a sentence.  {\tt
+Show-line} takes a sentence and prints it as if it were a bunch of
+disconnected words.  Later, when we read and write files in Chapter
+\files, this ability to print in the same form in which we read will be
+important.
+
+\subhd{Formatted Text}
+
+We've been concentrating on the use of sequential programming with explicit
+\pagetag{\spformat}
+printing instructions for the sake of conversational programs.  Another
+common application of sequential printing is to display tabular information,
+such as columns of numbers.  The difficulty is to get the numbers to line up
+so that corresponding digits are in the same position, even when the numbers
+have very widely separated values.  The
+\ttidx{align} function can be used to convert a number to a printable word
+with a fixed number of positions before and after the decimal point:
+
+{\prgex%
+(define (square-root-table nums)
+  (if (null? nums)
+      'done
+      (begin (display (align (car nums) 7 1))
+	     (show (align (sqrt (car nums)) 10 5))
+	     (square-root-table (cdr nums)))))
+
+> (square-root-table '(7 8 9 10 20 98 99 100 101 1234 56789))
+    7.0   2.64575
+    8.0   2.82843
+    9.0   3.00000
+   10.0   3.16228
+   20.0   4.47214
+   98.0   9.89949
+   99.0   9.94987
+  100.0  10.00000
+  101.0  10.04988
+ 1234.0  35.12834
+56789.0 238.30443
+DONE
+}
+
+\noindent {\tt Align} takes three arguments.  The first is the value to be
+displayed.  The second is the width of the column in which it will be
+displayed; the returned value will be a word with that many characters in it.
+The third argument is the number of digits that should be displayed to the
+right of the decimal point.  (If this number is zero, then no decimal point
+will be displayed.)  The width must be great enough to include all the
+digits, as well as the decimal point and minus sign, if any.
+
+As the program example above indicates, {\tt align} does not print
+anything.  It's a function that returns a value suitable for printing with
+{\tt display} or {\tt show}.
+
+What if the number is too big to fit in the available space?
+
+{\prgex%
+> (align 12345679 4 0)
+"123+"
+}
+
+\noindent {\tt Align} returns a word containing the first few digits,
+as many as fit, ending with a plus sign to indicate that part of the value
+is missing.
+
+{\tt Align} can also be used to include non-numeric text in columns.  If
+the first argument is not a number, then only two arguments are needed; the
+second is the column width.  In this case {\tt align} returns a word with
+extra spaces at the right, if necessary, so that the argument word will
+appear at the left in its column:
+
+{\prgex%
+(define (\ufun{name-table} names)
+  (if (null? names)
+      'done
+      (begin (display (align (cadar names) 11))
+	     (show (caar names))
+	     (name-table (cdr names)))))
+
+> (name-table '((john lennon) (paul mccartney)
+		(george harrison) (ringo starr)))
+LENNON     JOHN
+MCCARTNEY  PAUL
+HARRISON   GEORGE
+STARR      RINGO
+DONE
+}
+
+\noindent As with numbers, if a non-numeric word won't fit in the allowed
+space, {\tt align} returns a partial word ending with a plus sign.
+
+This {\tt align} function is not part of standard Scheme.  Most programming
+languages, including some versions of Scheme, offer much more elaborate
+formatting capabilities with many alternate ways to represent both numbers
+and general text.  Our version is a minimal capability to show the flavor
+and to meet the needs of projects in this book.
+
+\subhd{Sequential Programming and Order of Evaluation}
+
+Our expanded tic-tac-toe program includes both functional and sequential
+parts.  The program computes its strategy functionally but uses sequences
+of commands to control the {\it \bkidx{user}{interface}\/} by alternately
+printing information to the screen and reading information from the keyboard.
+
+By adding sequential programming to our toolkit, we've increased our ability
+to write interactive programs.  But there is a cost that goes along with
+this benefit:  We now have to pay more attention to the order of events than
+we did in purely functional programs.
+
+The obvious concern about order of events is that sequences of {\tt show}
+expressions must come in the order in which we want them to appear, and {\tt
+read} expressions must fit into the sequence properly so that the user is
+asked for the right information at the right time.
+
+But there is another, less obvious issue about order of events.  When the
+evaluation of expressions can have side effects in addition to returning
+values, the order of evaluation of argument subexpressions becomes important.
+Here's an example to show what we mean.  Suppose we type the expression
+
+{\prgex%
+(list (+ 3 4) (- 10 2))
+}
+
+\noindent The answer, of course, is {\tt (7~8)}.  It doesn't matter whether
+Scheme computes the seven first (left to right) or the eight first (right to
+left).  But here's a similar example in which it {\it does\/} matter:
+
+{\prgex%
+(define (\ufun{show-and-return} x)
+  (show x)
+  x)
+
+> (list (show-and-return (+ 3 4)) (show-and-return (- 10 2)))
+8
+7
+(7 8)
+}
+
+\noindent The value that's ultimately returned, in this example, is the same
+as before.  But the two numeric values that go into the list are also
+printed separately, so we can see which is computed first.  (We've shown
+the case of right-to-left computation; your Scheme might be different.)
+
+Suppose you want to make sure that the seven prints first, regardless of
+which order your Scheme uses.  You could do this:
+
+{\prgex%
+> (let ((left (show-and-return (+ 3 4))))
+    (list left (show-and-return (- 10 2))))
+7
+8
+(7 8)
+}
+
+\noindent The expression in the body of a {\tt let} can't be evaluated until
+the {\tt let} variables (such as {\tt left}) have had their values computed.
+
+It's hard to imagine a practical use for the artificial {\tt
+show-and-return} procedure, but a similar situation arises whenever we use
+{\tt read}.  Suppose we want to write a procedure to ask a person for his or
+her full name, returning a two-element list containing the first and last
+name.  A natural mistake to make would be to write this procedure:
+
+{\prgex%
+(define (ask-for-name)                       ;; wrong
+  (show "Please type your first name, then your last name:")
+  (list (read) (read)))
+
+> (ask-for-name)
+Please type your first name, then your last name:
+\pmb{John
+Lennon}
+(LENNON JOHN)
+}
+
+\noindent What went wrong?  We happen to be using a version of Scheme that
+evaluates argument subexpressions from right to left.  Therefore, the word
+{\tt John} was read by the rightmost call to {\tt read}, which provided the
+second argument to {\tt list}.  The best solution is to use {\tt let} as we
+did above:
+
+{\prgex%
+(define (\ufun{ask-for-name})
+  (show "Please type your first name, then your last name:")
+  (let ((first-name (read)))
+    (list first-name (read))))
+}
+
+Even this example looks artificially simple, because of the two invocations
+of {\tt read} that are visibly right next to each other in the erroneous
+version.  But look at {\tt play-ttt-helper}.  The word {\tt read} doesn't
+appear in its body at all.  But when we invoke it using {\tt ask-user} as
+the strategy procedure for {\tt x}, the expression
+
+{\prgex%
+(x-strat position 'x)
+}
+
+\noindent hides an invocation of {\tt read}.  The structure of {\tt
+play-ttt-helper} includes a {\tt let} that controls the timing of that {\tt
+read}.  (As it turns out, in this particular case we could have gotten away
+with writing the program without {\tt let}.  The hidden invocation of {\tt
+read} is the only subexpression with a side effect, so there aren't two
+effects that might get out of order.  But we had to think carefully about
+the program to be sure of that.)
+
+\subhd{Pitfalls}
+
+\pit It's easy to get confused about what is printed explicitly by your
+\justidx{printing}
+program and what is printed by Scheme's read-eval-print loop.  Until now,
+{\it all\/} printing was of the second kind.  Here's an example that doesn't
+do anything very interesting but will help make the point clear:
+
+{\prgex%
+(define (name)
+  (display "MATT ")
+  'wright)
+
+> (name)
+MATT WRIGHT
+}
+
+\noindent At first glance it looks as if putting the word ``Matt'' inside a
+call to {\tt display} is unnecessary.  After all, the word {\tt wright} is
+printed even without using {\tt display}.  But watch this:
+
+{\prgex%
+> (bf (name))
+MATT RIGHT
+}
+
+\noindent Every time you invoke {\tt name}, whether or not as the entire
+expression used at a Scheme prompt, the word {\tt MATT} is printed.  But
+the word {\tt wright} is {\it returned,\/} and may or may not be printed
+depending on the context in which {\tt name} is invoked.
+
+\pit A sequence of expressions returns the value of the {\it last\/}
+expression.  If that isn't what you want, you must remember the value you
+want to return using {\tt let}:
+
+{\prgex%
+(let ((result (compute-this-first)))
+  (begin
+   (compute-this-second)
+   (compute-this-third)
+   result))
+}
+
+\pit Don't forget that the first call to {\tt read-line}, or any call to
+{\tt read-line} after a call to {\tt read}, will probably read the empty
+line that {\tt read} left behind.
+
+\pit Sometimes you want to use what the user typed more than once in your
+program.  But don't forget that {\tt read} has an effect as well as a return
+value.  Don't try to read the same expression twice:
+
+{\prgex%
+(define (ask-question question)              ;; wrong
+  (show question)
+  (cond ((equal? (read) 'yes) #t)
+	((equal? (read) 'no) #f)
+	(else (show "Please answer yes or no.")
+	      (ask-question question))))
+}
+
+\noindent If the answer is {\tt yes}, this procedure will work fine.  But if
+not, the second invocation of {\tt read} will read a second expression, not
+test the same expression again as intended.  To avoid this problem, invoke
+{\tt read} only once for each expression you want to read, and use {\tt let}
+to remember the result:
+
+{\prgex%
+(define (\ufun{ask-question} question)
+  (show question)
+  (let ((answer (read)))
+    (cond ((equal? answer 'yes) #t)
+	  ((equal? answer 'no) #f)
+	  (else (show "Please answer yes or no.")
+		(ask-question question)))))
+}
+
+\esubhd{Boring Exercises}
+
+{\exercise
+What happens when we evaluate the following expression?  What is printed,
+and what is the return value?  Try to figure it out in your head before you
+try it on the computer.
+
+{\prgex%
+(cond ((= 2 3) (show '(lady madonna)) '(i call your name))
+      ((< 2 3) (show '(the night before)) '(hello little girl))
+      (else '(p.s. i love you)))
+}}
+
+\solution
+{\tt (THE NIGHT BEFORE)} is printed.
+
+{\tt (HELLO LITTLE GIRL)} is returned.
+
+@
+
+{\exercise
+What does {\tt newline} return in your version of Scheme?
+}
+
+{\exercise
+Define {\tt show} in terms of {\tt newline} and {\tt display}.
+}
+
+\solution
+{\prgex%
+(define (show stuff)
+  (display stuff)
+  (newline))
+}
+@
+
+\esubhd{Real Exercises}
+
+{\exercise
+Write a program that carries on a conversation like the following example.
+What the user types is in boldface.
+
+{\prgex%
+> \pmb{(\ufun{converse})}
+Hello, I'm the computer.  What's your name? \pmb{Brian Harvey}
+Hi, Brian.  How are you? \pmb{I'm fine.}
+Glad to hear it.
+}}
+
+\solution
+
+Here's a boring version that's glad to hear anything about how you're
+doing.  Naturally you could make it do a lot more if you were so inclined.
+
+{\prgex%
+(define (converse)
+  (read-line)
+  (display "Hello, I'm the computer.  What's your name? ")
+  (let ((name (read-line)))
+    (display (word "Hi, " (first name) ".  How are you? "))
+    (read-line)
+    (show "Glad to hear it.")))
+}
+@
+
+{\exercise
+Our {\tt name-table} procedure uses a fixed width for the column containing
+the last names of the people in the argument list.  Suppose that instead of
+liking British-invasion music you are into late romantic Russian composers:
+
+{\prgex%
+> (name-table '((piotr tchaikovsky) (nicolay rimsky-korsakov)
+		(sergei rachmaninov) (modest musorgsky)))
+}
+
+\noindent Alternatively, perhaps you like jazz:
+
+{\prgex%
+> (name-table '((bill evans) (paul motian) (scott lefaro)))
+}
+
+\noindent Modify {\tt name-table} so that it figures out the longest last
+name in its argument list, adds two for spaces, and uses that number as the
+width of the first column.
+}
+
+\solution
+{\prgex%
+(define (name-table names)
+  (if (null? names)
+      'done
+      (nt-help names
+	       (+ 2 (reduce max (map (lambda (nm) (count (last nm)))
+				     names))))))
+
+(define (nt-help names width)
+  (if (null? names)
+      'done
+      (begin (display (align (cadar names) width))
+	     (show (caar names))
+	     (nt-help (cdr names) width))))
+}
+
+The {\tt null?} test in {\tt name-table} is needed only for the case
+in which the user gives an empty argument; the {\tt null?} test that
+serves as the base case for the recursion is the one in {\tt nt-help}.
+
+@
+
+{\exercise
+The procedure {\tt ask-user} isn't robust.  What happens if you type
+something that isn't a number, or isn't between 1 and 9?  Modify it to check
+that what the user types is a number between 1 and 9.  If not, it should
+print a message and ask the user to try again.
+}
+
+\solution
+The changed parts of the procedure are shown here in boldface.
+
+{\prgex%
+(define (ask-user position letter)
+  (print-position position)
+  (display letter)
+  (display "'s move: ")
+  \pmb{(let ((answer (read)))}
+    \pmb{(if (and (integer? answer) (>= answer 1) (<= answer 9))}
+	\pmb{answer}
+	\pmb{(begin (show "That's not a move, silly!")}
+	       \pmb{(ask-user position letter)))))}
+}
+@
+
+{\exercise
+Another problem with {\tt ask-user} is that it allows a user to request a
+square that isn't free.  If the user does this, what happens?  Fix {\tt
+ask-user} to ensure that this can't happen.
+}
+
+\solution
+If the user asks for a square that's already taken, the square will
+be reassigned to the user.  The following solution assumes that the
+previous exercise is also included.
+The changed parts of the procedure are shown here in boldface.
+
+
+{\prgex%
+(define (ask-user position letter)
+  (print-position position)
+  (display letter)
+  (display "'s move: ")
+  (let ((answer (read)))
+    \pmb{(cond ((not} (and (integer? answer) (>= answer 1) (<= answer 9)))
+	   (show "That's not a move, silly!")
+	   (ask-user position letter))
+	  \pmb{((not (equal? '_ (item answer position)))}
+	   \pmb{(show "That square is occupied.")}
+	   \pmb{(ask-user position letter))}
+	  \pmb{(else} answer))))
+}
+@
+
+{\exercise
+At the end of the game, if the computer wins or ties, you never find out
+which square it chose for its final move.  Modify the program to correct
+this.  (Notice that this exercise requires you to make {\tt play-ttt-helper}
+non-functional.)
+}
+
+\solution
+The changed parts of the procedure are shown here in boldface.
+
+{\prgex%
+(define (play-ttt-helper x-strat o-strat position whose-turn)
+  (cond ((already-won? position (opponent whose-turn))
+	 \pmb{(print-position position)}
+	 (list (opponent whose-turn) 'wins!))
+	((tie-game? position)
+	 \pmb{(print-position position)}
+	 '(tie game))
+	(else (let ((square (if (equal? whose-turn 'x)
+				(x-strat position 'x)
+				(o-strat position 'o))))
+		(play-ttt-helper x-strat
+				 o-strat
+				 (add-move square whose-turn position)
+				 (opponent whose-turn))))))
+}
+@
+
+{\exercise
+The way we invoke the game program isn't very user-friendly.  Write a
+procedure {\tt game} that asks you whether you wish to play {\tt x} or {\tt
+o}, then starts a game.  (By definition, {\tt x} plays first.)  Then write a
+procedure {\tt games} that allows you to keep playing repeatedly.  It
+can ask ``do you want to play again?''\ after each game.  (Make sure that
+the outcome of each game is still reported, and that the user can choose
+whether to play {\tt x} or {\tt o} before each game.)
+}
+
+\solution
+{\prgex%
+(define (game)
+  (display "Do you want to play X or O? ")
+  (let ((letter (read)))
+    (cond ((equal? letter 'x)
+	   (play-ttt ask-user ttt))
+	  ((equal? letter 'o)
+	   (play-ttt ttt ask-user))
+	  (else (show "Please type X or O!")
+		(game)))))
+
+(define (games)
+  (show (game))
+  (display "Do you want to play again (Y or N)? ")
+  (if (another?)
+      (games)
+      "Thank you for playing, have a day."))
+
+(define (another?)
+  (let ((letter (read)))
+    (cond ((equal? letter 'y) #t)
+	  ((equal? letter 'n) #f)
+	  (else (show "C'mon, Y or N!")
+		(another?)))))
+}
+
+{\tt Game} and {\tt games} both ask a question, and both include a
+check for invalid answers.  But {\tt game} is able to repeat the
+question itself, if the answer was invalid, whereas {\tt games}
+uses a helper procedure {\tt another?} to ask the question.  The
+reason for this difference is that {\tt games} plays a game before
+asking its question, whereas the question is the first thing in
+{\tt game}.  If {\tt games} were written as a single procedure,
+an invalid answer would result in playing another game before
+asking again.
+
+@
+
+\bye