defgeneric中的可选参数?

时间:2012-02-20 02:37:03

标签: common-lisp clos

我正在编写一些方法来为各种元素发出HTML。每种方法都有相同的输出,但不一定需要相同的输入。

回复game-board的方法也需要player(因为每个玩家只看到自己的棋子)

(defmethod echo ((board game-board) (p player)) ... )

回应棋盘空间不需要更换每个玩家(该调度实际上是在game-board方法中完成的,后来在空格上调用echo。理想情况下,我能够做到

(defmethod echo ((space board-space)) ... )
(defmethod echo ((space empty-space)) ... )

我也可以想到,我后来遇到的对象需要了解的不仅仅是玩家才能正确展示自己。既然已经有专门针对相同泛型的方法,那么会产生错误

The generic function #<STANDARD-GENERIC-FUNCTION ECHO (4)> takes 2 required arguments;

回过头来命名这些方法echo-spaceecho-board等等似乎不太理想。

是否存在基于专门对象改变其他参数的规范方法?我应该做点什么吗

(defgeneric echo (thing &key player ...) ...)

(defgeneric echo (thing &rest other-args) ...)

?更一般地说,有人能指点我defgeneric专门的教程吗? (我已经阅读了相关的PCL章节和some CLOS tutorials,但它们并没有涵盖我在这里要求的情况。)

3 个答案:

答案 0 :(得分:5)

一般来说,如果两个函数的接口太不相同,则表明它们实际上不是同一操作的特化,也不应该具有相同的名称。如果你只想专注于可选/键参数,那么实现它的方法是使用一个普通的函数来调用一个泛型函数,并为缺少的参数提供默认值来专门研究。

我认为,

Keene's book是CLOS最全面的指南。不幸的是,它似乎只能以书本形式提供。

答案 1 :(得分:3)

每当方法采用相同的参数但仅在数据类型上有所不同时,它会更容易。但是在通用函数和方法都使用相同名称(当然)但lambda列表变化很大的情况下,我个人倾向于使用&amp; key参数来明确我的意图,而不是使用&amp;可选参数。我认为它有助于以后的可读性。

尝试这样的事情(假装我们已经有类class -a和class-b):

(defgeneric foo (object &key &allow-other-keys)
  (:documentation "The generic function. Here is where the docstring is defined."))

(defmethod foo ((object class-a) &key &allow-other-keys)
  (print "Code goes here. We dispatched based on type Class A."))

(defmethod foo ((object class-b) &key (x 1) (y 2) &allow-other-keys)
  (print "Code goes here. We dispatched based on type Class B. We have args X and Y."))

由于涉及“方法组合”,为了使调度逻辑“流”通过其可能的方法选择来使用,我们需要将方法定义看作有不兼容的lambda列表的链(即参数列表) )将打破这一链。这就是为什么方法定义中的&amp; key和&amp; allow-other-keys并不特别需要它们。将它们放在DEFGENERIC中,方法定义允许我们根据class-b调度方法定义。

免责声明:我自己就是一个Common Lisp新手,所以带上一粒盐吧!

答案 2 :(得分:0)

如何重构对象/类,以便每个要回显的对象在其自己的(和继承的)插槽中具有所有必需的属性?

这样,当你在对象上调用echo时,你不必将它们作为参数传递,因为你需要的东西已经存储在对象中了。