Index:
set-struct-field!
                     revew,
begin,
set-struct-field!
                     examples,
I/O 
Work through the many small exercises on your own, asking labbies at your leisure!
set-struct-field! reviewWhen we define a structure type, e.g.,
     (define-struct foo (bar baz))
we've previously seen that DrScheme defines a number of functions for us.
     make-foo : (type of bar) (type of baz) -> foo
     foo?     : any                         -> boolean
     foo-bar  : foo                         -> (type of bar)
     foo-baz  : foo                         -> (type of baz)
In addition, it also defines two other functions (called mutators)
     set-foo-bar! : foo (type of bar) -> void
     set-foo-baz! : foo (type of baz) -> void
Rather than creating a new foo, they change
the given one.  Changing an existing value is called a side-effect.
By convention, most Scheme functions with side-effects have names
ending with a "bang" (exclamation point).
This also introduces the type void, which indicates no
information.
begin
We can sequence operations with begin.
For example,
     ; An uninteresting use of begin.
     (begin (+ 2 3)
            (* 2 3)
            (- 2 3))
     ; An interesting use of begin.
     (define-struct cat (name age high? buddy))
     (define acat (make-cat 'furball 3 false '??dummy??))
     (begin (set-cat-age! acat (add1 (cat-age acat)))
            (set-cat-high?! acat true)
            acat)
evaluates each of its (three) expressions,
throws away the results of all but the last,
and returns the value of the last expression.
In the second case, nothing is thrown away, because the mutators don't return
anything.
Sequencing is not useful when the prior expressions mutate state, as
in the second case.
Syntax:
       (begin expression ... expression)
       
       There must be at least one expression.
       
  Semantics: Evaluate each expression in sequential order, and return the value of that last one.
set-struct-field! examples
In class we discussed how constructors (e.g., make-foo)
evaluate to a reference to a new structure, and
not to the new structure itself.
This allows us to share references to the same structure.
Also, we discussed how to mutate (change) structures.
This lets our program more closely match what we're modeling.
| 
 | 
Cons-cells are just predefined kinds of structures, using a naming
convention that doesn't quite correspond to user-defined structures.
For mutating these structures, Scheme provides the functions
set-first! and set-rest!.
(Remember that a list is not just a single structure, but 
 a bunch of cons-cells, or 
 empty
 (which is a flat value -- not a (reference to a) structure!)
| 
       (define mylist (list 1 3 5 7))
       (define yourlist (rest mylist))
       (set-first! yourlist 10)         ; The first should be a list element.
       ; what is mylist now?
       ; what is yourlist now?
       (set-rest! mylist (list 2 4))   ; The rest should be a list.
       ; what is mylist now?
       ; what is yourlist now?
       (set-rest! (rest mylist) mylist)
       ; what is mylist now?
       ; what is yourlist now?
        | 
Since Scheme automatically displays the result of whatever expression we give it, so far we haven't needed to know how to display something ourselves (aside from the drawing examples). Here are a few functions for getting information into and out of our programs. (Scheme has many others, too.) Try them out.
printf
     printf displays information to the screen.
     It takes at least one argument: a string giving the
     format of what to display.  printf may take more arguments,
     if so specified by the format.  E.g.,
     
     (printf "hello, world~n")
     
     displays the string hello, world, followed by a newline.
     The ~n means a newline.
     
     
     (printf "hello, ~v~n" 'world)
     
     displays the same thing.  The ~v indicates that the
     next argument's value should be printed in place of the ~v.
     (Mnemonic: "v" meaning any value.)
     
     
     (printf "~v ~v ~v~n" (+ 1 1) (list 'a 'b) true)
     
     displays three things separated by spaces and terminated by a
     newline. The three things displayed are the values of the
     remaining arguments.
     
error
     error causes an error to happen and displays an error
     message.  In this class, we haven't been concerned with writing
     functions that check for bad inputs.
     In real life and later classes, we'd want to check and report
     any errors, including bad inputs.
     
     (error 'myfunction "error message")
     
     causes an error. It also displays an error message using the
     symbol provided (typically the current function name), the string
     for the error message.  The format function can be
     used to format the error string before it is passed to
     error.
     
read
     read stops a program, waits for the user to type something
     in, and returns the value that the user just typed in.
     It takes no arguments.  Each time it is used, it could return a
     different value, since the user can type in something different each time.
     
| Execute the following code, typing in answers when prompted. 
     (printf "I will read, but immediately forget the next thing you type.~n")
     (read)
     (printf "What is your name? ")
     (define name (read))
     (printf "Howdy there, ~v.~n" name)
     Observe how words you type in are read as symbols.
     You can click on "eof" to type in an "end-of-file" signal.
     (Aside: you can use~ato format output suitable
        for non programmers -- that is, symbols aren't preceded by'and strings aren't surrounded by"s.) | 
So far, you have used two good techniques for debugging code:
Consider the following incorrect version of factorial.
     ;; buggy-fact: natnum --> number
     ;; Return n!.
     ;;   OOPS -- doesn't work -- always returns 0?!!
     ;;
     (define (buggy-fact n)
         (cond [(zero? n) 1]
               [else      (* (sub1 n) (buggy-fact (sub1 n)))]))
| DrScheme has a version of tracing built-in that is very easy to use. 
 | 
For the curious...
Some programming environments like DrScheme having tracing built-in.
But, some don't.  So, it can be valuable
to understand how to incorporate tracing into your own program.
The basic idea is simply to add printf's to print out the
input(s) and output(s) of the function.
(Thus the name "printf debugging", since the function is also called
 printf in the language C, where this technique is common.)
     (define debug? true)  ; Do I want to display debugging info?
     ;; buggy-fact: natnum --> number
     ;; Return n!.
     ;;   OOPS -- doesn't work -- always returns 0?!!
     ;;
     (define (buggy-fact n)
        (begin
           (when debug? (printf "buggy-fact input: ~v~n" n))
           (local [(define result
                       (cond [(zero? n) 1]
                             [else      (* (sub1 n)
                                           (buggy-fact (sub1 n)))]))]
               (begin
                  (when debug? (printf "buggy-fact output: ~v~n" result))
                  result))))
Here, we used a boolean flag debug? to indicate whether
or not to print out debugging info.
This makes turning on/off debugging very easy.
It can get very annoying to add and remove debugging repeatedly.
Also, we used a conditional called when:
     (when test-exp exp ... exp)
evaluates its test-exp,
and if true it returns
(begin exp ... exp)); 
if the 
test-exp
is false, then no useful value is returned (just as
set-struct-field!
and
printf don't return any useful value).
There are lots of variations on this idea to make it more useful. For example, we'd like to encapsulate the debugging aspect into a separate function. And we'd like finer control over what specific functions we want to trace.