From: Steve Haflich

Subject: Re: One question

Date: 1998-9-2 18:50

   From: <LMP.UFRJ.BR at JLUIZ>
       I take the program below from Internet, and I don't know why it 
   does not work. What is missing ? Can anybody help me ?
    
    (defclass point ()
    ((x :accessor x-coord :initarg :x)
     (y :accessor y-coord :initarg :y)))
    
    (defclass jLine ()
        ((point1 :type point :accessor p1 :initarg :p1)
         (point2 :type point :accessor p2 :initarg :p2)))
    
    (defclass jPolygon ()
        ((number-of-sides :type integer :accessor number-of-sides
          :initarg :number-of-sides)
         (sides :type list :accessor sides :initarg :sides
          :documentation "set of jLine segments")))
    
    (defmethod jLine-length ((l jLine))
       (let ((delta-x (- (x-coord (p1 l)) (x-coord (p2 l))))
             (delta-y (- (y-coord (p1 l)) (y-coord (p2 l)))))
          (sqrt (+ (* delta-x delta-x) (* delta-y delta-y)))))
                
    (defmethod perimeter ((p jPolygon))
       (reduce #'+ (mapcar #'jLine-length (sides p))))
    
    (setf pt1 (make-instance 'point :x 0 :y 0))
    (setf pt2 (make-instance 'point :x 0 :y 5))
    (setf pt3 (make-instance 'point :x 5 :y 5))
    (setf pt4 (make-instance 'point :x 5 :y 0))
    (setf l1 (make-instance 'jLine :p1 pt1 :p2 pt2))
    (setf l2 (make-instance 'jLine :p1 pt2 :p2 pt3))
    (setf l3 (make-instance 'jLine :p1 pt3 :p2 pt4))
    (setf l4 (make-instance 'jLine :p1 pt4 :p2 pt1))
    (setf poly1 (make-instance 'jPolygon))
    
    (setf (sides poly1) '(l1 l2 l3 l4))
    (setf (number-of-sides poly1) 4)
    
    (perimeter poly1)

The error that is signalled when you run this tells you what is wrong:

   <18> (perimeter poly1)
   Error: No methods applicable for generic function #<standard-generic-function jLine-length>
          with args (l1) of classes (symbol)
     [condition type: program-error]

   Restart actions (select using :continue):
    0: Try calling it again
    1: Return to Top Level (an "abort" restart)
   [1c] <19> :zo
   Evaluation stack:

      (cerror "Try calling it again" program-error ...)
    ->((method no-applicable-method (t)) #<standard-generic-function jLine-length> l1)
      (mapcar #<standard-generic-function jLine-length> (l1 l2 l3 ...))
      ((method perimeter (jPolygon)) #<jPolygon @ #x30911d62>)
      (eval (progn # # ...))
      (tpl:top-level-read-eval-print-loop)
      (tpl:start-interactive-top-level
	 #<bidirectional-terminal-stream [initial terminal io] fd 0/1 @ #x3014bd5a>
	 #<Function top-level-read-eval-print-loop> ...)
   [1c] <20> 

This is a common confusion of beginning lisp programmers. The problem
is here:

		(setf (sides poly1) '(l1 l2 l3 l4))

This sets the SIDES slot of the polygon to a list of four symbols.
The function jLine-length is applicable only to jLine objects.  What
you want is for the slot to be a list of jLine objects (which happen
to be the values of variables named by those symbols).  The code
should be:

		(setf (sides poly1) (listg l1 l2 l3 l4))