Comp 210 Lab 8: Equality; From Scheme to C

Table of Contents

  • Miscellany
  • Equality
  • Scheme to C
  • Miscellany

  • The Law of local, that is how it should be treated in a hand-evaluation.
  • Recall from the lab about errors in floating-point numbers, that round-off error can occur, and can accumulate. For instance, are six one-sixths one? Not if you're using floating-point numbers:
    |- (define s (/ 1.0 6))
    |- (= 1 (+ s s s s s s))
    #f
    
    What if you had a function which whose argument started at 1.0, recursivly subtracted 1/6 from its argument, and stopped when the result is exactly zero? The never-ending program! Moral of the story: when using floating-point numbers, you should stop not be testing for equality with 0, but less-or-equals 0.

  • The Syntax-Check Button: another way to have Dr. Scheme locate problems for you.
    If you choose "Check Syntax" from the Tools menu, you'll get a new "Check Syntax" button. Clicking this button will look for any errors in your definition window. In particular, it will find any free (unbound) variables, and paint them red.

  • You remember how we used printf immediately after a lambda, to print out debugging information? Well, now that you know about begin, you can use printf where ever you like. Just be careful not to have printf be the last expression of a begin statement, or you won't be returning any value!

    (By the way, there is a function newline which takes zero arguments, prints a newline, and returns nothing.)

  • You have seen some of Dr. Scheme's types: symbols, integers, lists...and now, pictures! Yes, pictures can be used just like any other type. In the definition window, type (define hi , and then (before closing the parenthesis), select "Insert Image..." from the Edit menu. It brings up an open-file dialogue. Go to the directory ~comp210/Gifs/, and choose any file inside which ends in .gif. (This stands for ... graphical image format??) Choose an image, click "ok", and close off the final paren.

    You can now use hi however you please! Is it equal to 'pretty? While gifs don't work well with printf, you can use display instead.

    WARNING: when you save a file containing gif values, don't expect it to be readable or printable any more!

  • Equality

    Somebody broke into my apartment, stole all my furnishings, and replaced them with exact duplicates.
    -- Steven Wright
    In the computer, is there one copy of 3, or many copies? Is there one copy of (make-bike 5), or many copies? These questions were moot until we introduced set! and set-[structure]-[field]!; without these we have no way (or need) of distinguishing between extensional and intensional equality.

    The rules given in Monday's lecture show how to hand-evaluate set-bike-location!, and why it's different from set!. Here is the same explanation again.

    1. When you see any make-structure, the hand-evaluation rule is to re-write it at the top level as
      (define uniqueVar^ (make-bike 5))
      
      and replace the original with uniqueVar^.
    2. As always, when figuring out what (define z ...) means, we must evaluate the ... so it is a value (not placeholder). As of this week, we modify this rule: these special "hat" placeholders which correspond to structures will themselves count as values. (This is a hand-evaluation convention; Dr. Scheme itself does not treat ^ in any way special.) This new rule is the fundamental reason why structures have different properties than (say) numbers or symbols.
    3. Then, when hand-evaluating (set-bike-location! uniqueVar^ 7), change the "define" line of uniqueVar^ to be
      (define uniqueVar^ (make-bike 7))
      
    Using these rules, your hand-evaluation should now be able to show the difference between
    (define x (make-bike 5))
    (define y x)
    (set-bike-location! x 7)
    y
    
    and
    (define x 5)
    (define y x)
    (set! x 7)
    y
    

    Another way of thinking of this whole subtlety:
    set! changes a binding, nothing else; set-particle-x! doesn't change any binding (which is why uniqueVar^ is used), though it does reach inside a structure and changes the structure's innards (which is changing the make-bike in the above example).

    From Scheme to C

  • A Sample Program

  • The Process of Creating a C Program

  • Using emacs

  • A Sample Program

    Consider the following Scheme code:
    ;; (f n)
    ;; given an integer n,
    ;; return 3n^2 +4n + 2
    ;;
    (define f
      (lambda (n)
         (+ (* 3 n n)
            (* 4 n)
            2)))
    
    (f 7)	
    
    Here's the
    corresponding program written in C:
    #include <stdio.h>        /* include standard input/output library header */
    
    /* f( n )
     * return 3n^2 + 4n + 2
     */
    int f( int n ) {             /* A function which takes int n, returns an int. */
      int result = 3*n*n + 4*n + 2;
      return result;             /* You have to "return" explicitly. */
      }
    
    
    int main() {                 /* Every program needs one function named "main" */
      printf( "f at 7 is %d\n",
               f(7) );           /* Nothing prints by iteslf. */
    
      return 0;                  /* Return a value...to where?  Who called main?
                                    Always return 0 from main, to UNIX. */
      }
    
    (Yes, it is possible to shorten some of the above if you wanted.) The labby will go over what each of these lines do step-by-step. A few things to note:
  • The line int n creates a placeholder n (Cf. Scheme's define); its value is initially garbage. The word int can be viewed as a data definition, declaring that the value of n is always an integer.
  • The assignment operator = is like Scheme's set!. Do not confuse = with the comparison function ==, which is the analog of Scheme's eq?.
  • You must declare the types of all variables, and the return type of each function.
  • There is no begin in C; instead it is implicitly there in every function. On the other hand, there is an explicit return statement which you'll need in every function.
  • Here is another example, income.c:
    #include <stdio.h>
    
    bool biggern( int a, int b ) {      /* "bool" is C's Boolean type */
      return (a > b);
      }
    
    int main() {
      int income = 7;
      int outgo  = 9;
    
      if (biggern( income, outgo ))
        printf( "Woo-hoo!  Made a profit!\n" );
      else {
        printf( "Uh-oh, in the red.\n" );
        printf( "Must raise $%d quickly!\n", outgo-income );
        }
        
      return 0;
      }
    
    Exercise: Write a function which converts Fahrenheit to Celsius, and a main function which prints what -40 fahrenheit is. (Your function must subtract 32, then multiply by 5.0/9.0. In C, these decimal points are needed; dividing two integers 5/9 is truncated to the nearest integer -- zero!)

    For more introduction to the C language, see the Extended C Primer (html or ps)

    The Process of Creating a C Program

    Unlike Scheme, where program development is fairly interactive, writing C programs is a little more rigid. There are several steps:
    1. Type your program into a text file. The filename should end with .c, for example hello.c. You can use whatever text editor you like to create this file; we'll use emacs since it has some nice features for using C.

    2. Compile your file, that is translate it from a text file to a binary format the machine can understand directly.

      Translating your program to machine code would be tedious by hand, but fortunately there is a program which will do it automatically.

         owl%  g++ hello.c
      
      If you are using emacs, you can compile the file with M-c (meta-c), or select "compile" under the C menu. You'll see that emacs invokes g++ for you, but with some useful extra arguments. (If emacs doesn't invoke g++ when you type M-c, or there isn't a C menu, type "M-x c-mode" and everything should be set aright.)

    3. If your program had any syntax errors (i.e., it wasn't legal C), then g++ will inform you. You must go back to Step 1, and fix your source file.

    4. If you didn't have any syntax errors, g++ will create a new executable file, named hello if you compiled with those extra arguments, or a.out (booo) if you didn't.

      Run your program as if it were any other UNIX program: just type in the name of the executable file.

    5. Test your program on different inputs. If you have any mistakes...you guessed it: back to Step 1.

    6. Celebrate!

    Using emacs

    Okay, okay, but how to actually create the text file? You can use any editor you like (even the one built-in to Dr. Scheme), but we'll use emacs, since it has some special commands suited for C.

    To edit a file first.c, type emacs first.c & at the UNIX prompt.

    In the emacs window, you can start typing text as normal, except for the delete key. If you are running on X, you can also use commands from the menus. Finally, you can use the control and meta keys to invoke special emacs commands.

    Exercise 1: Copy the file ~comp210/Labs/lab08/income.c or ~comp210/Labs/lab08/prog.c to your own directory, and then start editing it from emacs. Compile the file and run it.
    Exercise 2: (due to Dan Grossman) Change one character of the program at random, and compile again. Discuss the various error messages with the TA.

    Here are some common keyboard commands.
    Notation: C-x means control-x; M-c means meta-c.

    C-x C-c     to quit
    C-x C-f     to open a file
    M-x info    to get help
    C-_         undo (can be repeated to undo several commands)
    
    M-c         to compile (only if the file you are editing ends in .c)
    C-x 1       to make the current emacs window the only one
                 (useful to get rid of the second window M-c opens)
    
    You can also use many of the same commands that you can use inside Dr. Scheme:
    C-p, C-n  for previous/next line
    C-f, C-b  for forward/back a character
    C-d       delete one character
    C-k       kill (delete) the line,
    C-y       to yank back the last killed text
    

    You can run an emacs tutorial from the "Help" menu. For further commands, see the emacs reference card.


    Back to Comp 210 Home