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))