Return 来自泛型方法的实例列表
Return list of instances from generic method
我需要 return 通用方法中的矩形坐标列表。坐标是 class 'cart' 实例。
我用 make-instancereturn 试试
(defclass line ()
((start :initarg :start :accessor line-start)
(end :initarg :end :accessor line-end)))
(defmethod print-object ((lin line) stream)
(format stream "[LINE ~s ~s]"
(line-start lin) (line-end lin)))
(defclass cart ()
((x :initarg :x :reader cart-x)
(y :initarg :y :reader cart-y)))
(defmethod print-object ((c cart) stream)
(format stream "[CART x ~d y ~d]"
(cart-x c) (cart-y c)))
(setq lin (make-instance 'line
:start (make-instance 'cart :x 4 :y 3)
:end (make-instance 'cart :x 7 :y 5)))
(defgeneric containing-rect (shape))
(defmethod containing-rect ((l line))
(let ((x1 (cart-x (line-start l)))
(y1 (cart-y (line-start l)))
(x2 (cart-x (line-end l)))
(y2 (cart-y (line-end l))))
(cond ((= x1 x2)
'((make-instance 'cart :x (1- x1) :y y1)
(make-instance 'cart :x (1+ x1) :y y1)
(make-instance 'cart :x (1- x2) :y y2)
(make-instance 'cart :x (1+ x2) :y y2)))
((= y1 y2)
'((make-instance 'cart :x x1 :y (1- y1))
(make-instance 'cart :x x1 :y (1+ y1))
(make-instance 'cart :x x2 :y (1- y2))
(make-instance 'cart :x x2 :y (1+ y2))))
(t
(rect '((make-instance 'cart :x x1 :y y1)
(make-instance 'cart :x x1 :y y2)
(make-instance 'cart :x x2 :y y2)
(make-instance 'cart :x x2 :y y1)))))))
(print (containing-rect lin))
我想 make-instance
应该为某物分配一个实例
所以我得到了错误的结果
((MAKE-INSTANCE 'CART :X X1 :Y Y1) (MAKE-INSTANCE 'CART :X X1 :Y Y2)
(MAKE-INSTANCE 'CART :X X2 :Y Y2) (MAKE-INSTANCE 'CART :X X2 :Y Y1))
但我需要这样的输出
([CART x 4 y 3] [CART x 4 y 3] [CART x 4 y 3] [CART x 4 y 3])
如果你quote
某样东西,它不被评价。
这个:
'((make-instance 'cart :x (1- x1) :y y1)
(make-instance 'cart :x (1+ x1) :y y1)
(make-instance 'cart :x (1- x2) :y y2)
(make-instance 'cart :x (1+ x2) :y y2))
是一个包含四个文字列表的文字列表,每个列表都以符号MAKE-INSTANCE
开头,然后有一个列表(QUOTE CART)
,依此类推。就是你看到的结果。
你似乎想实际评估一下。最简单的事情就是这样做并列一个清单:
(list (make-instance 'cart :x (1- x1) :y y1)
(make-instance 'cart :x (1+ x1) :y y1)
(make-instance 'cart :x (1- x2) :y y2)
(make-instance 'cart :x (1+ x2) :y y2))
这与引用某事完全不同。
关于您的代码的一些额外提示。
类
这不是硬性规定,但访问器函数(通用函数)通常仅以槽命名,即 x
而不是 get-X
(绝对是 "bad" 风格)或object-X
(还不错,还是很常见)。
(defclass line ()
((start :initarg :start :accessor start)
(end :initarg :end :accessor end)))
(defclass cart ()
((x :initarg :x :reader x)
(y :initarg :y :reader y)))
(defclass rect ()
((upper-left :initarg :upper-left :accessor upper-left)
(bootom-right :initarg :bottom-right :accessor bottom-right)))
我不知道你的要求是什么,所以我发明了一些;特别是,我将矩形表示为 2 个点(upper-left 和 bottom-right)。
构造函数
拥有构造函数对拥有简洁易读的代码有很大帮助:
(defun cart (x y)
(make-instance 'cart :x x :y y))
(defun line (start end)
(make-instance 'line :start start :end end))
对于矩形,首先对点进行排序以构建 upper-left 和 bottom-right 点。
(defun sorted-coordinate (points coordinate)
(sort (mapcar coordinate points) #'<))
(defun rect (point-1 point-2)
(let ((points (list point-1 point-2)))
(destructuring-bind (low-x high-x) (sorted-coordinate points #'x)
(destructuring-bind (low-y high-y) (sorted-coordinate points #'y)
(make-instance 'rect
:upper-left (cart low-x high-y)
:bottom-right (cart high-x low-y))))))
打印机方法
您的代码几乎 打印了 Lisp 表单,并且为了不增加复杂性,您实际上可以使打印机方法发出可以读回的代码以构建相同的数据。以下方法使用 PRIN1
打印 可读 对象,作为对先前定义的构造函数的调用:
(defmethod print-object ((line line) stream)
(prin1 `(line ,(start line) ,(end line)) stream))
(defmethod print-object ((c cart) stream)
(prin1 `(cart ,(x c) ,(y c)) stream))
(defmethod print-object ((rect rect) stream)
(prin1 `(rect ,(upper-left rect) ,(bottom-right rect)) stream))
例子
(defparameter *test-line*
(line (cart 4 3) (cart 7 5)))
然后,评估结果行给出:
CL-USER> *TEST-LINE*
=> (LINE (CART 4 3) (CART 7 5))
以上是一个值,由 REPL 打印,正是用于构建它的表达式。
矩形的边界
通用函数要简单得多(但可能是错误的,因为矩形的处理方式不同):
(defgeneric containing-rect (shape))
(defmethod containing-rect ((line line))
(rect (start line) (end line)))
例如:
CL-USER> (containing-rect *test-line*)
=> (RECT (CART 4 5) (CART 7 3))
我需要 return 通用方法中的矩形坐标列表。坐标是 class 'cart' 实例。
我用 make-instancereturn 试试
(defclass line ()
((start :initarg :start :accessor line-start)
(end :initarg :end :accessor line-end)))
(defmethod print-object ((lin line) stream)
(format stream "[LINE ~s ~s]"
(line-start lin) (line-end lin)))
(defclass cart ()
((x :initarg :x :reader cart-x)
(y :initarg :y :reader cart-y)))
(defmethod print-object ((c cart) stream)
(format stream "[CART x ~d y ~d]"
(cart-x c) (cart-y c)))
(setq lin (make-instance 'line
:start (make-instance 'cart :x 4 :y 3)
:end (make-instance 'cart :x 7 :y 5)))
(defgeneric containing-rect (shape))
(defmethod containing-rect ((l line))
(let ((x1 (cart-x (line-start l)))
(y1 (cart-y (line-start l)))
(x2 (cart-x (line-end l)))
(y2 (cart-y (line-end l))))
(cond ((= x1 x2)
'((make-instance 'cart :x (1- x1) :y y1)
(make-instance 'cart :x (1+ x1) :y y1)
(make-instance 'cart :x (1- x2) :y y2)
(make-instance 'cart :x (1+ x2) :y y2)))
((= y1 y2)
'((make-instance 'cart :x x1 :y (1- y1))
(make-instance 'cart :x x1 :y (1+ y1))
(make-instance 'cart :x x2 :y (1- y2))
(make-instance 'cart :x x2 :y (1+ y2))))
(t
(rect '((make-instance 'cart :x x1 :y y1)
(make-instance 'cart :x x1 :y y2)
(make-instance 'cart :x x2 :y y2)
(make-instance 'cart :x x2 :y y1)))))))
(print (containing-rect lin))
我想 make-instance
应该为某物分配一个实例
所以我得到了错误的结果
((MAKE-INSTANCE 'CART :X X1 :Y Y1) (MAKE-INSTANCE 'CART :X X1 :Y Y2)
(MAKE-INSTANCE 'CART :X X2 :Y Y2) (MAKE-INSTANCE 'CART :X X2 :Y Y1))
但我需要这样的输出
([CART x 4 y 3] [CART x 4 y 3] [CART x 4 y 3] [CART x 4 y 3])
如果你quote
某样东西,它不被评价。
这个:
'((make-instance 'cart :x (1- x1) :y y1)
(make-instance 'cart :x (1+ x1) :y y1)
(make-instance 'cart :x (1- x2) :y y2)
(make-instance 'cart :x (1+ x2) :y y2))
是一个包含四个文字列表的文字列表,每个列表都以符号MAKE-INSTANCE
开头,然后有一个列表(QUOTE CART)
,依此类推。就是你看到的结果。
你似乎想实际评估一下。最简单的事情就是这样做并列一个清单:
(list (make-instance 'cart :x (1- x1) :y y1)
(make-instance 'cart :x (1+ x1) :y y1)
(make-instance 'cart :x (1- x2) :y y2)
(make-instance 'cart :x (1+ x2) :y y2))
这与引用某事完全不同。
关于您的代码的一些额外提示。
类
这不是硬性规定,但访问器函数(通用函数)通常仅以槽命名,即 x
而不是 get-X
(绝对是 "bad" 风格)或object-X
(还不错,还是很常见)。
(defclass line ()
((start :initarg :start :accessor start)
(end :initarg :end :accessor end)))
(defclass cart ()
((x :initarg :x :reader x)
(y :initarg :y :reader y)))
(defclass rect ()
((upper-left :initarg :upper-left :accessor upper-left)
(bootom-right :initarg :bottom-right :accessor bottom-right)))
我不知道你的要求是什么,所以我发明了一些;特别是,我将矩形表示为 2 个点(upper-left 和 bottom-right)。
构造函数
拥有构造函数对拥有简洁易读的代码有很大帮助:
(defun cart (x y)
(make-instance 'cart :x x :y y))
(defun line (start end)
(make-instance 'line :start start :end end))
对于矩形,首先对点进行排序以构建 upper-left 和 bottom-right 点。
(defun sorted-coordinate (points coordinate)
(sort (mapcar coordinate points) #'<))
(defun rect (point-1 point-2)
(let ((points (list point-1 point-2)))
(destructuring-bind (low-x high-x) (sorted-coordinate points #'x)
(destructuring-bind (low-y high-y) (sorted-coordinate points #'y)
(make-instance 'rect
:upper-left (cart low-x high-y)
:bottom-right (cart high-x low-y))))))
打印机方法
您的代码几乎 打印了 Lisp 表单,并且为了不增加复杂性,您实际上可以使打印机方法发出可以读回的代码以构建相同的数据。以下方法使用 PRIN1
打印 可读 对象,作为对先前定义的构造函数的调用:
(defmethod print-object ((line line) stream)
(prin1 `(line ,(start line) ,(end line)) stream))
(defmethod print-object ((c cart) stream)
(prin1 `(cart ,(x c) ,(y c)) stream))
(defmethod print-object ((rect rect) stream)
(prin1 `(rect ,(upper-left rect) ,(bottom-right rect)) stream))
例子
(defparameter *test-line*
(line (cart 4 3) (cart 7 5)))
然后,评估结果行给出:
CL-USER> *TEST-LINE*
=> (LINE (CART 4 3) (CART 7 5))
以上是一个值,由 REPL 打印,正是用于构建它的表达式。
矩形的边界
通用函数要简单得多(但可能是错误的,因为矩形的处理方式不同):
(defgeneric containing-rect (shape))
(defmethod containing-rect ((line line))
(rect (start line) (end line)))
例如:
CL-USER> (containing-rect *test-line*)
=> (RECT (CART 4 5) (CART 7 3))