Lisp自定义比较函数

时间:2013-11-22 09:46:56

标签: common-lisp

假设我定义了一个新类foo

(defclass foo ()
  ((bar :initarg :bar ...)
   (baz :initarg :baz ...)
   ...))

我想为foo创建一个自定义比较器,例如:

(defun foo-equalp (foo1 foo2)
  (equalp (bar foo1)))

是否有更好,更明确的方法将此foo-equalp函数与foo类绑定?

我在考虑不必将#'foo-equalp作为:test参数传递给像REMOVE-DUPLICATES这样的函数,但即使这是不可能的,我仍然想知道是否有一个更惯用的Lisp方法来定义这个函数。

1 个答案:

答案 0 :(得分:3)

如果我理解了您的问题,那么generic functions可以提供帮助

(defgeneric foo-equalp (foo1 foo2))

(defmethod foo-equalp ((foo1 foo) (foo2 foo))
  (and (equal (bar foo1) (bar foo2))
       (equal (baz foo1) (baz foo2))))

现在当您使用非foo类型的对象调用foo-equalp时,会出现此错误。

There is no applicable method for the generic function
  #<STANDARD-GENERIC-FUNCTION FOO-EQUALP (1)>
when called with arguments
  (1 2).

或者您可能希望其他所有内容都返回

(defmethod foo-equalp ((foo1 t) (foo2 t))
  nil)

这里我们专注于t which is the set of all objects。当你调用一个方法时,常见的lisp将始终为参数选择“最接近/最具体”的类型匹配(这是一个可怕的描述错误......我需要更多咖啡,请查看链接,因为它很棒 :)

  • 您实际上并不需要专门研究t,因为这是默认设置,但我想将其包含在内以显示正在发生的事情。

以下是来自Practical Common Lisp 的片段(链接在此顶部 回答)

  

泛型函数定义抽象操作,指定其名称   和参数列表,但没有实现。实际执行情况   通用函数的方法由方法提供。

     

方法表明他们可以处理哪种类型的参数   专门化泛型函数定义的必需参数。

     

例如,对于通用函数绘制,您可以定义一个方法   专门为作为实例的对象的形状参数   类圈,而另一种方法专门为对象的形状   这是班级三角形的实例。