Fonctions de comparaison personnalisées Lisp

Disons que je définis une nouvelle classe foo :

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

Et je veux créer un comparateur personnalisé pour foo , tel que:

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

Y aurait-il une meilleure façon plus explicite de lier cette fonction foo-equalp à la classe foo ?

Je pensais ne pas avoir à passer # 'foo-equalp comme l'argument : test à des fonctions comme REMOVE-DUPLICATES , mais même si n'est pas possible, j'aimerais quand même savoir s'il existe une façon plus idiomatique de définir cette fonction.

0
ajouté édité
Vues: 2
@JoshuaTaylor: Connaissez-vous cdr.eurolisp.org/document/8/cleqcmp.html ? J'ai mis en place une implémentation de CDR8, mais je ne l'ai pas encore publié (besoin de le nettoyer et de le soumettre).
ajouté l'auteur Paul Nathan, source
@JoshuaTaylor: github.com/pnathan/generic-comparability (J'ai également travaillé sur les implémentations de CDR 2 mais c'est moins cuit).
ajouté l'auteur Paul Nathan, source
Il semble que vous vouliez un prédicat d'égalité qui est une fonction générique à laquelle des méthodes spécialisées peuvent être ajoutées (un peu comme vous pouvez spécialiser .equals() en Java). Malheureusement, aucun des prédicats "communs" ( éq , éql , égal , égalp ) ne sont des fonctions génériques, alors même si ce n'est pas trop difficile d'écrire une telle fonction générique, vous devrez toujours la passer aux fonctions de la bibliothèque comme remove , etc., car ce ne sera pas la comparaison par défau
ajouté l'auteur Joshua Taylor, source
@PaulNathan J'étais au courant du dépôt CDR, mais je n'avais pas lu celui-là en particulier auparavant. Cela ressemble à une bonne idée. Je reverrais certainement une réponse qui en ferait usage. :) Je me rends compte que vous avez dit que vous ne l'aviez pas encore publié, mais est-il disponible en ligne n'importe où dans n'importe quel état encore?
ajouté l'auteur Joshua Taylor, source

1 Réponses

Si je comprends votre question, alors fonctions génériques pourrait aider ici

(defgeneric foo-equalp (foo1 foo2))

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

et maintenant quand vous appelez foo-equalp avec des objets qui ne sont pas de type foo vous obtenez cette erreur.

There is no applicable method for the generic function
  #
when called with arguments
  (1 2).

ou vous pourriez vouloir tout le reste pour revenir à zéro

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

Ici, nous nous spécialisons sur t qui est l'ensemble de tous les objets . Quand vous appelez une méthode, le lisp commun choisira toujours le type le plus proche/le plus spécifique pour les arguments (ugh qui est un mangling terrible d'une description .. J'ai besoin de plus de café, vérifiez le lien car c'est génial :) )

  • Vous n'avez pas besoin de spécialiser de t car c'est la valeur par défaut mais je voulais l'inclure pour montrer ce qui se passait.

The following are snippets from Practical Common Lisp (which is linked at the top of this answer)

Une fonction générique définit une opération abstraite, en spécifiant son nom   et une liste de paramètres mais pas de mise en œuvre. L'implémentation réelle   d'une fonction générique est fournie par des méthodes.

     

Les méthodes indiquent quels types d'arguments peuvent être traités par   spécialiser les paramètres requis définis par la fonction générique.

     

Par exemple, pour un tirage de fonction générique, vous pouvez définir une méthode   qui se spécialise le paramètre de forme pour les objets qui sont des instances de   le cercle de classe tandis qu'une autre méthode spécialise la forme pour les objets   ce sont des instances du triangle de classe.

3
ajouté
Utilisez des fonctions génériques lorsque vous prévoyez de l'étendre avec plusieurs méthodes utilisant des combinaisons d'héritage et/ou de méthode. Sinon, cela pourrait être exagéré.
ajouté l'auteur Rainer Joswig, source
Bravo, j'ai toujours été un peu brumeux quand choisir quelle technique. C'est bien d'avoir cela comme règle générale.
ajouté l'auteur Baggers, source