defstruct
(defstruct person
name
(alter 0)
(hobbys nil))
(let ((p (make-person :name "Mia" :alter 17)))
(format t "~a ~a~%" (person-name p) (person-alter p))
(setf (person-alter p) 18)
(push "Lesen" (person-hobbys p))
(format t "~a ~a~%" (person-alter p) (person-hobbys p))
(format t "~a~%" (person-p p))
(let ((kopie (copy-person p)))
(setf (person-name kopie) "Tom")
(format t "~a ~a~%" (person-name p) (person-name kopie)))
(format t "~a~%" p))Ausgabe
Mia 17 18 (Lesen) T Mia Tom #S(PERSON :NAME Mia :ALTER 18 :HOBBYS (Lesen))
Klassen mit CLOS
Das Common Lisp Object System ist eines der mächtigsten Objektsysteme. Methoden gehören nicht zu Klassen, sondern zu generischen Funktionen:
(defclass tier ()
((name :initarg :name :accessor tier-name)
(laut :initarg :laut :initform "..." :accessor tier-laut)))
(defclass hund (tier)
((rasse :initarg :rasse :initform "Mischling" :reader hund-rasse))
(:default-initargs :laut "Wau"))
(defclass katze (tier) ()
(:default-initargs :laut "Miau"))
(defgeneric vorstellen (tier)
(:documentation "Stellt das Tier vor."))
(defmethod vorstellen ((tier tier))
(format t "~a sagt ~a~%" (tier-name tier) (tier-laut tier)))
(defmethod vorstellen ((h hund))
(call-next-method)
(format t " Rasse: ~a~%" (hund-rasse h)))
(let ((tiere (list (make-instance 'hund :name "Rex" :rasse "Schäferhund")
(make-instance 'katze :name "Mimi"))))
(mapc #'vorstellen tiere)
(format t "~a~%" (typep (first tiere) 'tier))
(format t "~a~%" (class-name (class-of (second tiere)))))Ausgabe
Rex sagt Wau Rasse: Schäferhund Mimi sagt Miau T KATZE
Mehrfach-Dispatch und Hilfsmethoden
Methoden können auf mehreren Argumenten verzweigen:
(defclass form () ())
(defclass kreis (form) ())
(defclass rechteck (form) ())
(defgeneric kollision (a b))
(defmethod kollision ((a kreis) (b kreis)) "Kreis trifft Kreis")
(defmethod kollision ((a kreis) (b rechteck)) "Kreis trifft Rechteck")
(defmethod kollision ((a rechteck) (b form)) "Rechteck trifft irgendeine Form")
(format t "~a~%" (kollision (make-instance 'kreis) (make-instance 'kreis)))
(format t "~a~%" (kollision (make-instance 'kreis) (make-instance 'rechteck)))
(format t "~a~%" (kollision (make-instance 'rechteck) (make-instance 'kreis)))
(defclass konto () ((stand :initform 0 :accessor stand)))
(defmethod einzahlen :before ((k konto) betrag)
(format t "vor Einzahlung ~a~%" betrag))
(defmethod einzahlen ((k konto) betrag) (incf (stand k) betrag))
(defmethod einzahlen :after ((k konto) betrag)
(format t "danach ~a~%" (stand k)))
(let ((k (make-instance 'konto)))
(einzahlen k 50))Ausgabe
Kreis trifft Kreis Kreis trifft Rechteck Rechteck trifft irgendeine Form vor Einzahlung 50 danach 50
Fehler und das Condition-System
Das Condition-System trennt Fehler melden von Fehler behandeln und erlaubt Wiederaufnahme (Restarts):
(define-condition eigener-fehler (error)
((code :initarg :code :reader fehler-code))
(:report (lambda (c s) (format s "Eigener Fehler Nr. ~a" (fehler-code c)))))
(defun gefaehrlich (n)
(cond ((< n 0) (error 'eigener-fehler :code n))
((= n 0) (error "Null nicht erlaubt"))
(t (/ 100 n))))
(handler-case (gefaehrlich -5)
(eigener-fehler (e) (format t "gefangen: ~a~%" e)))
(handler-case (gefaehrlich 0)
(error (e) (format t "Fehler: ~a~%" e)))
(handler-case (/ 1 0)
(division-by-zero () (format t "durch null~%")))
(format t "~a~%" (handler-case (gefaehrlich 4) (error () :fehler)))
(unwind-protect
(handler-case (error "kaputt") (error () (format t "behandelt~%")))
(format t "aufräumen~%"))
(defun mit-restart (n)
(restart-case (error "Problem ~a" n)
(nimm-null () 0)
(nimm-wert (w) w)))
(format t "~a~%" (handler-bind ((error (lambda (c) (declare (ignore c)) (invoke-restart 'nimm-wert 99))))
(mit-restart 1)))Ausgabe
gefangen: Eigener Fehler Nr. -5 Fehler: Null nicht erlaubt durch null 25 behandelt aufräumen 99
Merke
defstructerzeugt einfache Datensätze mit Zugriffsfunktionendefclass,defgenericunddefmethodbilden CLOS: Methoden gehören zu generischen Funktionen- Mehrfach-Dispatch und
:before/:aftermachen Verhalten flexibel - Das Condition-System bietet
handler-case,handler-bindundrestart-case
Aufgabe
Modelliere Formen als Klassen mit einer generischen Funktion flaeche.