The Department of Computer Science & Engineering
cse@buffalo

CSE202: Programming in Lisp

Course
Grades
Email

Welcome

Policies
    Grades
    Inc
    Intgrty

Preface
Part I
  Chap 1
  Chap 2
  Chap 3
  XEmacs
  Chap 4
  Chap 5
  Chap 6
  Chap 7
  Chap 8
  Chap 9
Part II
  Chap 10
  Chap 11
  Chap 12
  Chap 13
  Chap 14
  Chap 15
  Chap 16
  Chap 17
  Chap 18
  Chap 19
  Chap 20
  Chap 21
  Chap 22
  Chap 23
Part III
  Chap 24
  Chap 25
  Chap 26
  Chap 27
  Chap 28
  Chap 29
  Chap 30
  Chap 31
  Chap 32
CHAPTER 29: INPUT/OUTPUT
Corrections
  1. Page 217, line 4: Change interaction to interactions.

  2. Page 217, line 13: Change evaluate form to evaluate a form.

  3. Page 225, line -10: Change (format t " &I heard you say    A " sentence) to (format t "~&I heard you say ~{~A~}" sentence).

  4. Page 227, line -3 - page 228, line 3: Instead of using provide and require, put (unless (find-package 'match) (load match) as the first form in your eliza file, even before the defpackage form.

Notes
  1. Read Chapter 29.

  2. On the last line of page 218 and the first line of page 219, I say "A common mistake is forgetting that these functions take only one argument." For example, (print 'Hello 'Frank) will produce an error. However, it won't be the error you might expect. Actually, the print functions take a second, optional argument, which must be a stream. A stream is a generalized file, and includes the standard output file. So the error message will tell you that FRANK is not a stream. A nickname for the standard output stream, which is the default value of the optional argument, is the symbol T, so (print 'Hello t) will do exactly the same thing as (print 'Hello).

  3. On page 221, I say that the first argument of format, which I call destination, is either t or nil, and in the footnote, I say that there are other possibilities. Actually destination must evaluate to a stream, and as I said above, the symbol t is a nickname for the standard output stream. nil is a special case as a destination for format. The other possibilities are other streams, but we will still not discuss streams any more in this course.

  4. Do Exercises 29.1 - 29.7. These exercises are valuable for learning how the Common Lisp we are using behaves when reading input.

  5. Do Exercise 29.8 to learn about two valuable functions for output.

  6. Do Exercises 29.9 - 29.16. These are valuable for learning how to write an interactive program that prompts its user for input.

  7. Exercise 29.13 introduces the function values. I mentioned in the footnote on page 169 that "Common Lisp provides a facility that can be used to have a function return more than one value". This facility is the values function, which can be given zero or more arguments, and returns them all. To see it work, evaluate the following:
    	(values)
    	(values 'a)
    	(values 'a (+ 2 5))
    	(values 'a (+ 2 5) (second '(a b c))) 
    
    We will still not discuss this feature any more in this course.

  8. Exercises 29.14 - 29.16 are to learn more about the printing functions.

  9. Exercises 29.17 - 29.22 are valuable for learning about the format function. This is the most flexible and useful Common Lisp printing function, and is similar to C's writef.

  10. Exercises 29.23 - 29.31 are valuable for learning to write Lisp interactive programs. In particular, Exercises 29.29 - 29.31 discuss versions of the "echo" program.

  11. In your match file, define a function
    (apply-rules-fully tree rule-list)
    This should apply the first rule on rule-list to tree, then apply it again to the result, etc., until it doesn't apply any more. Then it should apply the second rule to the result until it doesn't apply any more, etc. for all the rules on rule-list. For example, the following rules
    ((($x you $y) ($x origyou $y))
     (($x I $y) ($x you $y))
     (($x me $y) ($x you $y))
     (($x origyou $y) ($x me $y)))
    
    will change all occurrences of I and me to you, and all occurrences of you to me.

  12. In your match file, define a function
    (apply-one-rule tree rule-list)
    This should try the rules on rule-list in order, and when the first applies to tree, apply the rule and return the result.

  13. Make apply-rules-fully and apply-one-rule external symbols in the match package.

  14. Create a file named eliza.cl. The first form in this file should be
    (unless (find-package 'match) (load "match"))
    
    Next put the defpackage and in-package forms so that the rest of the file will be in the eliza package. Put a (:use common-lisp match) subform in the defpackage form, so that you can use exported symbols from the match package without qualification in the eliza package. (See page 81.)

  15. In your eliza.cl file, define the function eliza to print an informative message, and then be a read-eval-print loop that reads sentences from the user and:
    1. uses apply-rules-fully to apply manditory rules to the user's sentences, such as those that change "I" to "you";

    2. uses apply-one-rule to further transform the user's sentences into replies;

    3. prints the reply, without any enclosing parentheses, and followed by a newline.

  16. Make eliza an external symbol of the eliza package.

  17. Create two sets of rules for your eliza to use. Suggestions of manditory rules are above in the section on apply-rules-fully. Suggestions for the other set of rules are in the text on page 227. Since apply-one-rule tries rules in order, you can end the list of rules with a very general one like
    ($x (Tell me more.))
    
    or
    ($x (Very interesting.))
    
    You can get additional ideas by evaluating M-x doctor in your XEmacs, and interacting with the version of Eliza there.

  18. Make the last form in your eliza.cl file the form (eliza) so that your eliza function is called as soon as your eliza file is loaded.

  19. Note the following problem: Your users will probably be in the user package when they load your eliza file. Since the final form of your file is a call to the eliza function, the interaction with your users will be in the eliza package, and everything should go well. However, if they should exit your eliza function, and try to reenter it by executing (eliza:eliza), they will then be interacting in the user package, and that will make your rules fail. Here's how to fix this:

    Wrap the read-eval-print loop of your eliza function in a let with the variable *package* set to (find-package 'eliza), and declare *package* to be special. That way, you will read your users' sentences in the eliza package, and they will return to their original package when eliza terminates.

  20. Submit your enhanced match.cl file and your eliza.cl file.

  21. Create and submit a file ch29.cl containing a demonstration interaction with your Eliza.

  22. When you have submitted correct exercises through this chapter, you will have finished your project, and earned a grade of A. Congratulations!

Next

Copyright © 1999, 2000 by Stuart C. Shapiro. All rights reserved.

Stuart C. Shapiro <shapiro@cse.buffalo.edu>