使用defstruct在结构内定义函数

时间:2013-11-11 18:30:10

标签: lisp common-lisp

是否可以像函数一样定义结构的一个插槽并访问插槽以使用该功能?如果是的话,怎么用呢?例如,像这样:

(defstruct problem
   state
   (player (defun getplayer (some-state) (findplayer 1 some-state))) 
   (points (defun getpoints (some-state someplayer) (findpoints someplayer some-state)))
 )

3 个答案:

答案 0 :(得分:2)

你所写的内容不起作用,但你可以这样做:

(defstruct problem () state)
(defgeneric getplayer (problem)
  (:method ((p problem))
    (find-player 1 (problem-state p))))
(defgeneric getpoints (problem player)
  (:method ((p problem) player)
    (findpoints player (problem-state p))))

答案 1 :(得分:2)

这也是你能做的好事:

(defclass get-player ()
  ((state :initarg :state :accessor state-of))
  (:metaclass sb-mop:funcallable-standard-class))

(defmethod initialize-instance :after ((this get-player) &rest initargs)
  (declare (ignore initargs))
  (sb-mop:set-funcallable-instance-function
   this (lambda ()
          (format t "~&I am: ~s, my state is: ~s" this (state-of this)))))

(let ((get-player (make-instance 'get-player :state :initial-state)))
  (funcall get-player)
  (setf (state-of get-player) :advanced-state)
  (funcall get-player))

;; I am: #<GET-PLAYER {10036104BB}>, my state is: :INITIAL-STATE
;; I am: #<GET-PLAYER {10036104BB}>, my state is: :ADVANCED-STATE

也就是说,您可以使用函数对象来控制它们捕获的变量。因此,由于您在示例代码中不需要problem的实例来调用getplayer(您只需要state),因此这种方法可能很有趣。

答案 2 :(得分:2)

我会使用以下两种技术之一:

第一种方法是,不是在槽中存储函数,而是存储命名函数的符号。请注意,这假定命名函数在结构def本身之外的其他地方定义。

(Defstruct problem
  State
 (Points 'getpoints)
 (Player 'getplayer))

这可以类似于:

的方式使用
 (Defvar p (make-problem ...))
 (Funcall (problem-points p) x)
 (Funcall (problem-player p) x y)

这样做的原因是,当提供符号时,Funcall会在调用之前自动解析其fdefinition。第二种方法非常相似,但是代替表示命名函数的符号,槽直接设置为匿名函数(称为“lambda表达式”)。这种方法与您列出的示例有额外的相似之处,我是分配给槽值的函数是在结构的定义或实例化中定义的,并且不依赖于已在别处定义的函数。所以:

(Defstruct problem
  State
 (Points (lambda (arg0) (some-computation arg0)))
 (Player (lambda (arg0 arg1) (other-computation arg0 arg1))))

然后:

 (Defvar q (make-problem ...))
 (Funcall (problem-points q) x)
 (Funcall (problem-player q) x y)

希望有帮助!