2011-01-02 6 views
10

Ich habe eine Los von guten Dingen über Land of Lisp gelesen, also dachte ich, dass ich durchgehen könnte, um zu sehen, was es zu sehen gab.Land von Lisp Beispiel Redundanz?

(defun tweak-text (lst caps lit) 
    (when lst 
    (let ((item (car lst)) 
     (rest (cdr lst))) 
     (cond 
     ; If item = space, then call recursively starting with ret 
     ; Then, prepend the space on to the result. 
     ((eq item #\space) (cons item (tweak-text rest caps lit))) 
     ; if the item is an exclamation point. Make sure that the 
     ; next non-space is capitalized. 
     ((member item '(#\! #\? #\.)) (cons item (tweak-text rest t lit))) 
     ; if item = " then toggle whether we are in literal mode 
     ((eq item #\") (tweak-text rest caps (not lit))) 
     ; if literal mode, just add the item as is and continue 
     (lit (cons item (tweak-text rest nil lit))) 
     ; if either caps or literal mode = true capitalize it? 
     ((or caps lit) (cons (char-upcase item) (tweak-text rest nil lit))) 
     ; otherwise lower-case it. 
     (t (cons (char-downcase item) (tweak-text rest nil nil))))))) 

(Kommentare Mine sind)
(. FYI - die Methodensignatur ist (list-of-symbols bool-whether-to-caps bool-whether-to-treat-literally) aber der Autor diese (lst caps lit) verkürzt)

Aber wie auch immer, hier ist die Frage:
Dies hat (cond... (lit ...) ((or caps lit) ...)) in es. Mein Verständnis ist, dass dies if(lit){ ... } else if(caps || lit){...} in einer C-Stil-Syntax übersetzen würde. Ist das oder die Aussage dann nicht überflüssig? Gibt es jemals eine Bedingung, bei der die (or caps lit) Bedingung aufgerufen wird, wenn caps nil ist?

Antwort

10

In der Tat, Sie haben Recht. Siehe das errata für das Buch.

Seite 97: Die Funktion Tweak-Text enthält zwei Glitches, obwohl sie bei den meisten Lisp-Implementierungen OK ist. Zuallererst verwendet es die eq-Funktion zum Vergleichen von Zeichen. Zeichen sollten immer mit anderen Funktionen wie eql oder char-equal gemäß der ANSI-Spezifikation überprüft werden. Außerdem gibt es eine unnötige Überprüfung von (oder Kappen leuchtet), die zu Obergrenzen vereinfacht werden können.

+0

Dank. Ich fing an zu denken, dass ich verrückt werde (ich werde daran denken, Errata das nächste Mal zu überprüfen) – cwallenpoole

8

Ich würde schreiben, dass als:

(defun tweak-text (list caps lit) 
    (when list 
    (destructuring-bind (item . rest) list 
     (case item 
     ((#\space)    (cons item (tweak-text rest caps lit))) 
     ((#\! #\? #\.)   (cons item (tweak-text rest t lit))) 
     ((#\")     (tweak-text rest caps (not lit))) 
     (otherwise (cond (lit (cons item (tweak-text rest nil lit))) 
         (caps (cons (char-upcase item) 
            (tweak-text rest nil lit))) 
         (t (cons (char-downcase item) 
            (tweak-text rest nil nil))))))))) 

Die CASE-Anweisung Depeschen auf den Charakter. Die COND-Anweisung kümmert sich dann um die anderen Bedingungen. CASE vergleicht mit EQL. Das heißt, CASE funktioniert auch für Charaktere und kann sogar mit mehreren Elementen verglichen werden. Ich bin auch ein Fan eines Code-Layout-Stils, der entsprechende Ausdrücke ausrichtet - das ist nur bei Schriften mit einfachem Abstand nützlich. Dies hilft mir, Muster visuell im Code zu erkennen und Code zu erkennen, der vereinfacht werden kann.

DESTRUCTURING-BIND nimmt die Liste auseinander.

Für Spaß, neu geschrieben LOOP mit:

(defun tweak-text (list) 
    (loop with caps and lit 

     for item in list 

     when (eql item #\space) 
     collect item 

     else when (member item '(#\! #\? #\.)) 
     collect item and do (setf caps t) 

     else when (eql item #\") 
     do (setf lit (not lit)) 

     else when lit 
     collect item and do (setf caps nil) 

     else when caps 
     collect (char-upcase item) and do (setf caps nil) 

     else 
     collect (char-downcase item) and 
     do (setf caps nil lit nil))) 
+1

'((Es gibt ein paar Dinge in dem Buch, die ich bemerkt habe, hätte ich anders gemacht (er hat hier ein bisschen Rekursion) Iteration ist viel sauberer und (meiner Meinung nach) leichter zu verstehen)) (aber (ich folge den Beispielen (im Fall (er hat einen besseren Plan, als ich mir vorgestellt hätte))))) (Lisp macht Englisch) . – cwallenpoole