2010-03-28 19 views
2

J'ai écrit une classe polynomiale selon les lignes décrites dans SICP 2.5.3 (sauf en utilisant defclass). J'aimerais pouvoir ajouter et multiplier de manière transparente des polynômes et des nombres réguliers, mais je ne peux pas faire accepter un nombre par un changement de classe.Créer un objet polynomial à partir d'un nombre en utilisant la classe de changement

J'ai essayé de simplifier le problème en changeant la classe d'un nombre entier à un flotteur:

(change-class 4 'float) 

mais cela m'a donné l'erreur:

There is no applicable method for the generic function 
#<STANDARD-GENERIC-FUNCTION CHANGE-CLASS (7)> 
when called with arguments 
(4 #<BUILT-IN-CLASS FLOAT>). 
[Condition of type SIMPLE-ERROR] 

Je reçois une erreur de la même forme de (fyi):

(change-class 4 'polynomial) 

Je vais aller de l'avant et implémenter une conversion manuelle mais je préférerais utiliser les installations de fermeture intégrées. Comme le souligne Xach, je pourrais utiliser coercitive ou float pour changer 4 en float. Cela a été conçu comme un exemple plus simple de ce que j'essayais de faire et de supprimer toute possibilité que ma classe update-instance-for-different soit erronée.

Voici la version plus longue de ce que j'ai essayé qui ne fonctionne pas:

(defclass polynomial() 
((var :accessor var :initarg :var :initform 'x) 
    (terms :accessor terms :initarg :terms :initform (make-empty-term-list)))) 

(defmethod update-instance-for-different-class :before ((old number) 
         (new polynomial) 
         &key) 
    (setf (slot-value new 'terms) (adjoin-term (make-term old 0) 
          (make-empty-term-list)))) 

(change-class 4 'polynomial) 

Je reçois encore une erreur comme dans l'exemple ci-dessus:

There is no applicable method for the generic function 
    #<STANDARD-GENERIC-FUNCTION CHANGE-CLASS (7)> 
when called with arguments 
    (4 #<STANDARD-CLASS POLYNOMIAL>). 
    [Condition of type SIMPLE-ERROR] 

Répondre

1

Vous ne pouvez pas utiliser CHANGE-CLASS avec des nombres. Les nombres ne sont pas des instances de classes CLOS. CHANGE-CLASS est également pensé destructivement modifier une instance à une nouvelle classe, sans modifier l'identité de l'instance d'origine.

Je voudrais soit:

  • ajouter des méthodes de changement CLASS qui fait ce que vous voulez

  • ou écrire une fonction CHANGE, qui met en œuvre diverses règles de coercition sur mesure et appelle CHANGE-classe pour tout passer d'une classe CLOS à une autre classe CLOS.

+0

Merci, il me semble que je suis confus car je me souviens que cl est des objets tout le chemin vers le bas mais peut-être que ce n'est pas tout à fait vers le bas CLOS. Je viens de vérifier l'hyperspéc et il dit qu'à propos de t que "2. le nom du type auquel appartiennent tous les objets --- le supertype de tous les types (y compris lui-même) 3. le nom de la superclasse de toutes les classes sauf moi-même. " Peut-être que je vais créer une nouvelle question dans ce sens. – charlieb

+0

@charlieb: gardez à l'esprit que les classes et les types sont deux choses différentes dans CL. CL divise également les objets en trois catégories: 1) les classes intégrées telles que les nombres, les caractères et les chaînes. 2) structures et 3) instances CLOS. CLOS vous permet d'écrire des méthodes pour les types et les structures intégrés, mais ce ne sont pas encore des objets CLOS à cause de cela.Les objets CLOS héritent tous de STANDARD-OBJECT. Les nombres ont par exemple une classe NUMBER, qui n'est pas une classe standard, mais une classe intégrée. –

+0

Je pense qu'une partie de la confusion pourrait être le mot "objet". Dans de nombreuses langues, cela signifie "une instance d'une classe". Dans Common Lisp, cela signifie «n'importe quelle donnée Lisp» - http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_o.htm – Ken

2

Vous pouvez utiliser COERCE ou FLOAT Pour ce faire:

(float 4) => 4.0 
(coerce 4 'float) => 4.0 
+0

Hey Xach, mais puis-je utiliser coercition pour changer le nombre à une classe personnalisée? – charlieb

+0

Non. Vous ne pouvez pas utiliser les fonctions arithmétiques CL normales sur les instances de vos propres classes - ce ne sont pas des fonctions génériques. – Xach