第玖章學習 Lisp 3rd Edition, Winston & Horn

章學習範例:

* (setf temperature 100)
* (print temperature)
100            ;PRINT's printing action does this.
100            ;This is the value of the PRINT form.
---------------------------------------------------------
* (if  (< -1 (print (- temperature 98.6)) +1)    ;Print a value.
       'normal
       'abnormal)
1.4                    ;Value printed by PRINT form.    
ABNORMAL               ;Value returned by IF form.
---------------------------------------------------------
* (setf name 'kirsh symptoms '(fever rash nausea))
* (print (list 'patient name
               'presented (length symptons)
               'symptons symptoms))
(PATIENT KIRSH PRESENTED 3 SYMPTOMS (FEVER RASH NAUSEA)) ;Side effect.
(PATIENT KIRSH PRESENTED 3 SYMPTOMS (FEVER RASH NAUSEA)) ;Value.
---------------------------------------------------------------
* (read)kirsh
KIRSH
----------------------------------------------------------
* (let ((p nil))                     ;P's initial value is NIL.
    (print                           ;Prompt.
      '(please type a patient name))
    (setf p (read))                  ;Get name from user.
    (print (append '(ok the name is) ;Compose and print message.
                   (list p)))
    p)                               ;Final form inside LET is P.
(PLEASE TYPE A PATIENT NAME) Kirsh   ;Prompt plus user's response.
(OK THE NAME IS KIRSH)               ;Acknowledgement message.
KIRSH                                ;The value returned by the LET.
--------------------------------------------------------------
* (format t "Hello!")Hello!    ;Format prints Hello!
NIL                            ;Format's value is NIL.
-----------------------------------------------------------
* (format t "~%Hello!")
Hello!                        ;FORMAT prints Hello!
NIL                           ;FORMAT's value is NIL.

* (format t "~%Hello!~%I'm ready to start now.")
Hello!                        ;Printed by FORMAT.
I'm ready to start now.       ;Printed by FORMAT.
NIL                           ;FORMAT's value.
--------------------------------------------------------------
* (progn (format t "~%Line followed by % sign directive.~%")
         (format t "~%Line preceded by % sign directive.~%")
         (format t "~&Line preceded by & sign directive."))
Line followed by % sign directive.    ;Concluding % sign directive.
                                      ;Preceding % sign directive.
Line preceded by % sign directive.    ;Concluding % sign directive.
Line preceded by & sign directive.    ;Preceding & sign directive.
NIL
--------------------------------------------------------------
* (format t                           ;Print on your terminal.
          "~%The next patient is ~a." ;An A directive appears.
          name)                       ;The A's matching argument.
The next patient is KIRSH.            ;Side effect.
NIL                                   ;Value.
----------------------------------------------------------------
* (format t
          "~%Patient ~a presented ~a symptoms ~a."
          name                        ;Argument for first A.
          (length symptoms)           ;For the second A.
          symptoms)                   ;For the third A.
Patient KIRSH presented 3 symptoms (FEVER RASH NAUSEA). ;Side effect.
NIL                                                     ;Value.
----------------------------------------------------------------
* (format t "~%Patient: ~10aSymptoms: ~a" name (length symptoms))
Patient: KIRSH     Symptoms: 3   ;Ten characters in KIRSH plus spaces.
NIL                              ;The value returned.

題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題

9-1: In a previous problem in chapter 5, you defined TOWER-OF-HANOI,
a procedure which counts the number of moves required to move a
stack of disks from one pin to another under the following conditions:
* Only one disk can be moved at a time.
* The disks all have different diameters, and disk can ever be placed
  on top of a smaller one.
* Initially all disks are on one pin and each disk rests on a larger one.
The official solution, expanded abit so as to pass along the names of
pins involved in the moves, looks like this:

(defun tower-of-hanoi (disks from to spare)
  (if (endp disks)
      0
      (+ (tower-of-hanoi (rest disks) from spare to)
         1
         (tower-of-hanoi (rest disks) spare to from))))

Now the problem.  Modify TOWER-OF-HANOI so that it prints a series of
instructions for moving disks, rather than counting the number of moves,
as in the following example:

* (tower-of-hanoi '(3 2 1) 'a 'b 'c)
Move 1 from A to B.
Move 2 from A to C.
Move 1 from B to C.
Move 3 from A to B.
Move 1 from C to A.
Move 2 from C to B.
Move 1 from A to B.
NIL

---------------------------------------------------------------------
((David Kirsh) (fever rash))
((Gerog Hegel) (fever headache))
((Immanuel Kant) (nausea))
((Rene Descartes) (nausea))
((Jean-Paul Sartre) (nausea stomachache))
--------------------------------------------------------------
(with-open-file (<stream name>
                 <file specification>
                 :direction <:input or :output>)
  ...)
------------------------------------------------------------------
(with-open-file (<stream name>
                 <file specification>
                 :direction :input)
  ...
  (read <stream name>)
  ...)
-----------------------------------------------------------
(with-open-file (patient-stream "/phw/lisp3/patients.lsp"
                                :direction :input)
  ...)
--------------------------------------------------------------
* (with-open-file (patient-stream "/phw/lisp3/patients.lsp"
                                :direction :input)
    (dotimes (n 2) (print (read patient-stream))))
((DAVID KIRSH) (FEVER RASH))        ;First expression read.
((gEORG hEGEL) (FEVER HEADACHE))    ;Second expression read.
NIL
--------------------------------------------------------------
* (with-open-file (patient-stream "/phw/lisp3/patients.lsp"
                                  :direction :input)
    (do ((patient (read patient-stream nil)
                  (read patient-stream nil)))
        ((not patient))
      (print patient)))
((DAVID KIRSH) (FEVER RASH))
((GEORG HEGEL) (FEVER HEADACHE))
((IMMANUEL KANT) (NAUSEA))
((RENE DESCARTES) (NAUSEA))
((JEAN-PAUL SARTRE) (NAUSEA STOMACHACHE))
NIL
---------------------------------------------------------------
(with-open-file (<stream name>
                 <file specification>
                 :direction :output)
  ...
  (print <expression whose value is to be printed> <stream name>)
  ...)
---------------------------------------------------------------
(defun nauseated-p (description)
  (member 'nausea (second description)))

* (with-open-file (patient-stream "/phw/lisp3/patients.lsp"
                                  :direction :input)
    (with-open-file (nausea-stream "/phw/lisp3/nausea.lsp"
                                   :direction :output)
      (do ((patient-description (read patient-stream nil)
                                (read patient-stream nil)))
          ((not patient-description))
        (when (nauseated-p patient-description)
          (print patient-description nausea-stream)))))
NIL
--------------
((IMMANUEL KANT) (NAUSEA))
((RENE DESCARTES) (NAUSEA))
((JEAN-PAUL SARTRE) (NAUSEA STOMACHACHE))

題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題

9-2: Sometimes NIL can appear in a file.  In such situations,
(READ <input stream> NIL) could return NIL before encountering
the end of a file, promoting confusion and error.  To avoid 
this confusion and error, you can supply still another optional 
argument that is returned on encountering the end of a file.  
Many programmers use EOF for end-of-file:

(read patient-stream nil 'eof)

Show how to print out all the patient records in the patient 
description file using a READ from which an EOF argument.
------------------------------------------------------------
9-3: In chapter 6, five book descriptions were combined into 
one list assigned to BOOKS:

(setf books
      (list
        (make-book '(artificial intelligence)
                   '(patrick henry winston)
                   '(technical ai))
        (make-book '(common lisp)
                   '(guy l steele)
                   '(technical lisp))
        (make-book '(moby dick)
                   '(herman melville)
                   '(fiction))
        (make-book '(tom sawyer)
                   '(mark twain)
                   '(fiction))
        (make-book '(the black orchid)
                   '(rex stout)
                   '(fiction mystery))))

You would never type such an expression directly into LISP for 
two reasons: first, you could not expect to type so much without 
mistakes; and second, you want a permanent bibliography, not 
one that will vanish when you terminate your session with LISP.
    Consequently, it is much more natural to create a file in 
which the SETF form is the sole contents.  Reading from the file,
using LOAD, would assign the list of book descriptions to BOOKS.
    Usually it is better to put just the book descriptions in
the file without the SETF, just as in the patient-descriptions
example.  Explain why.
----------------------------------------------------------------
9-4: FORMAT also can print to output streams.  You need only 
replace the T with an output stream name.  Show how you would
create a file containing the following, given the usual patients
in the patients file:

Patient 1 is not nauseous.
Patient 2 is not nauseous.
Patient 3 is nauseous.
Patient 4 is nauseous.
Patient 5 is nauseous.

-----------------------------------------------------------------

* (setf form-to-evaluate '(+ 2 2))    ;Variable's value is assigned.
(+ 2 2)

* form-to-evaluate                    ;Variable's value is a form.
(+ 2 2)

* (eval form-to-evaluate)             ;Variable of that form is a number.
4
---------------------------------------------------------------------
* (read)(+ 2 2)                ;You type (+ 2 2) for READ.
(+ 2 2)                        ;READ returns (+2 2)

* (eval (read))(+ 2 2)         ;You type (+ 2 2) for READ.
4                              ;EVAL evaluates READ's result.

題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題

9-5: Define ECHO1, a procedure that reads expressions and returns
them without evaluation, and define ECHO2, a procedure that
returns with evaluation:

------------------------------------------------------------------

* (length '(a b c))
3

* (length "abc")
3

* (reverse '(a b c))
(C B A)

* (reverse "abc")
"cba"
----------------------------------------------------------------
* (elt '(a b c) 0)
A

* (elt '(a b c) 2)
C

* (elt "abc" 0)
#\a

* (elt "abc" 2)
#\c
---------------------------------------------------------------
* (string= "abc" "xyz")
NIL

* (string= "abc" "abc")
T

* (string= "abc" "ABC")
NIL

* (String-equal "abc" "xyz")
NIL

* (string-equal "abc" "abc")
T

* (string-equal "abc" "ABC")
T
--------------------------------------------------------------------
* (char= #\a #\b)
NIL

* (char= #\a #\a)
T

* (char= #\a #\A)
NIL

* (char-equal #\a #\b)
NIL

* (char-equal #\a #\a)
T

* (char-equal #\a #\A)
T
-------------------------------------------------------------
* (search "Katz" "Katz, Boris")
0

* (search "Boris" "Katz, Boris")
6

* (search "Pushkin" "Katz, Boris")
NIL
-------------------------------------------------------------
* (search "BORIS" "Katz, Boris")
NIL

* (search "BORIS" "Katz, Boris" :test #'char-equal)
6
-----------------------------------------------------------
* (search '(Katz) '(katz boriz))
0

* (search '(boris) '(katz boris))
1

* (search '(pushkin) '(katz boris))
NIL
----------------------------------------------------------
* (read-line)This is a READ-LINE test.
"This is a READ-LINE test."
NIL

* (read-char)x
#\x
* (read-char)X
#\X
-----------------------------------------------------------
Horn, Berthold        5863        BKPH
Katz, Boris           6032        BORIS
Winston, Patrick      6754        PHW
Woven Hose Cafe       577-8444    
-----------------------------------------------------------
(defun fetch (fragment file)
  (with-open-file (line-stream file: direction :input)
    (do ((line (read-line line-stream nil)
               (read-line line-stream nil)))
        ((not line) (format t "~%No such entry!"))
      (when (search fragment line:test #'char-equal)
        (format t "~%~a" line)
        (return t)))))
------------------------------------------------------------
* (fetch "Katz" "people.ail")
Katz, Boris             6032            BORIS
T

* (fetch "Pushkin" "people.ail")
No such entry!
NIL

解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解

9-1:
(defun tower-of-hanoi (disks from to spare)
  (unless (endp disks)
    (tower-of-hanoi (rest disks) from spare to)
    (format t "~%Move ~a from ~a to ~a." (first disks) from to)
    (tower-of-hanoi (rest disks) spare to from)))

Note that the placement of the FORMAT form between the two recursive calls
to TOWER-OF-HANOI is important because the instruction to move the bottom
disk must be given after the instructions for moving all but the bottom disk
to the spare pin.  Similarly, the instruction to move the bottom disk must
be given before the instructions for moving the disks back from the spare
pin to the destination pin.
--------------------------------------------------------------------------
9-2:
* (with-open-file (patient-stream "/phw/lisp3/patients.lsp"
                                  :direction :input)
    (do ((patient (read patient-stream nil 'eof)
                  (read patient-stream nil 'eof)))
        ((eq patient 'eof))
      (print patient)))
--------------------------------------------------------------------------
9-3: Data base files are often large to huge.  Under such conditions,
it is better to read individual descriptions from a file, rather than
forming a long list of descriptions that would consume too much
random-access memory.
-------------------------------------------------------------------------
9-4:
(with-open-file (patient-stream "/phw/lisp3/patients.lsp"
                                :direction :input)
  (with-open-file (nausea-stream "/phw/lisp3/nausea.lsp"
                                :direction :output)
    (do ((patient-description (read patient-stream nil)
                              (read patient-stream nil))
         (n 1 (+ 1 n)))
        ((not patient-description))
      (format nausea-stream
              "~%Patient ~a is ~a."
              n
              (if (nauseated-p patient-description)
                  "nauseous"
                  "not nauseous")))))
NIL
---------------------------------------------------------------
9-5:
(defun echo1 ()
  (loop (print (read))))

(defun echo2 ()
  (loop (print (eval (read)))))

你可能感兴趣的:(erlang,Scheme,haskell,lisp,clojure)