; Beispiele zum objektorientierten Programmieren:

(setq *print-circle* t)

; (defns fun funktionalesObjekt)
; definiert die Funktion fun so, da sie eine noeval,spread-Funktion ist:
; die Argumente werden 1. nicht ausgewertet, 2. mit der Lambda-Liste gematcht,
; 3. der Body ausgewertet und 4. normal zurckgegeben.
; bersetzung: (fun x1 ... xk) -> (funcall funobj x1 ... xk)
; also (defmacro fun (&rest x) (list* 'funcall funobj x))
(defun defns (funname funobj)
  (eval `(defmacro ,funname (&rest x)
           (list* 'funcall '',funobj (mapcar #'(lambda (y) `',y) x)))))

; Ein "Mensch" sei eine Funktion, die Kommandos wie WIEHEISSTDU, LERNE, RECHNE,
; ISS, WIEGDICH, GEBAERE versteht.

(labels ((mensch (&key name (wissen 0.0) (gewicht 5)
                  &aux (kinder nil))
           #'(lambda (kommando &rest args)
               (case kommando
                 (WIEHEISSTDU name)
                 (LERNE (setq wissen (/ (- 2 wissen))) 'OK)
                 (RECHNE (dolist (expr args)
                           (format t "~%~S  =  ~S" expr (* wissen (eval expr)))
                         ) 'OK)
                 (ISS (setq gewicht (+ gewicht 1)) 'OK)
                 (WIEGDICH gewicht)
                 (GEBAERE (let ((kind (first args)))
                            (cond ((member kind kinder)
                                   (format t
                                    "~%Ein Kind mit Namen ~S habe ich schon."
                                    kind))
                                  (t (defns kind
                                           (mensch :name kind :wissen wissen))
                                     (push kind kinder)
                                     kind
                 )        ) )     )
             ) )
        ))
  (defns 'adam (mensch :name 'adam :wissen 0 :gewicht 10))
)

