2017-06-18 3 views
0

die Klasse Betrachten account:Aufruf an die nächst spezifische Methode funktioniert nicht

(defclass account() 
    ((name :initarg :name :reader name) 
    (balance :initarg :balance :initform 0.00 :accessor balance) 
    (interest-rate :allocation :class :initform 0.06 
        :reader interest-rate))) 

Für diese Klasse definieren wir eine Methode withdraw:

(defmethod withdraw ((acct account) amt) 
    (if (< amt (balance acct)) 
     (decf (balance acct) amt) 
     'insufficient-funds)) 

Und eine andere Klasse password-account, dh eine Unterklasse von account:

(defclass password-account (account) 
    ((password :initarg :password :reader password))) 

Und, das Verfahren withdraw, für diese Klasse:

(defmethod withdraw ((acct password-account) amt pass) 
    (if (equal (password acct) pass) 
     (call-next-method acct amt) 
     'wrong-password)) 

Aber das gibt einen Fehler:

The generic function 
#<STANDARD-GENERIC-FUNCTION COMMON-LISP-USER::WITHDRAW (1)> 
takes 2 required arguments; was asked to find a method with 
specializers 
(#<STANDARD-CLASS COMMON-LISP-USER::PASSWORD-ACCOUNT> 
#1=#<SB-PCL:SYSTEM-CLASS COMMON-LISP:T> #1#) 
    [Condition of type SB-PCL::FIND-METHOD-LENGTH-MISMATCH] 
See also: 
    Common Lisp Hyperspec, FIND-METHOD [:function] 

Restarts: 
0: [RETRY] Retry SLIME REPL evaluation request. 
1: [*ABORT] Return to SLIME's top level. 
2: [ABORT] abort thread (#<THREAD "repl-thread" RUNNING {1005308033}>) 

Warum ist das passiert? Und was bedeutet

wurde gebeten, eine Methode mit specializers zu finden

hier bedeuten?

Hier ist die primäre withdraw Funktion hatte zwei Argumente acct und amt, so, um sie von einer spezifischeren Methode aufzurufen, die anstelle von 2 3 Argumente verwendet, wir call-next-method mit den Argumenten der weniger spezifischen withdraw Verfahren bereitstellen . Aber das funktioniert immer noch nicht.
Jede Hilfe wird geschätzt.

+5

Sie können keine Methode mit zwei erforderlichen Parametern und eine andere mit drei erforderlichen Argumenten in derselben generischen Funktion verwenden. CLOS erlaubt das nicht. Die erste Methodendefinition bestimmt die Anzahl der benötigten Argumente. Die generische Funktion in Ihrem Beispiel hat zwei erforderliche Argumente und Sie versuchen, eine Methode mit drei erforderlichen Argumenten zu definieren. Dies wird nicht unterstützt und auch nicht erlaubt. –

+0

Danke @RainerJoswig. Gibt es einen besonderen Grund dafür, solche Methoden nicht zu unterstützen? – Mooncrater

+0

Und was ist der Zweck, die nächste spezifische Methode über 'call-next-method' mit Argumenten aufzurufen? Da alle Methoden dieselbe Anzahl von Argumenten erfordern würden. (Also die gleichen Argumente) – Mooncrater

Antwort

7

Kongruente Lambda-Listen für generische Funktionen

Methoden einer generischen Funktion benötigencongruentLambda-Listen haben. Der Sprachstandard beschreibt, was das bedeutet: Congruent Lambda-lists for all Methods of a Generic Function.

Wie Sie die erste Regel sehen, sagt:

  • Jede Lambda-Liste die gleiche Anzahl von erforderlichen Parameter aufweisen müssen.

Erforderliche Parameter uns sagen, welche Argumente immer vorgesehen werden müssen. Generische Funktionen erlauben zusätzlich optionale Schlüsselwort- und Restargumente. Aber es gibt keinen Versand über diese. Der Versand funktioniert nur über die erforderlichen Argumente und alle diese.

Die gleiche Anzahl erforderlicher Parameter vereinfacht den Versand und ermöglicht dem Compiler, Funktionsaufrufe mit der falschen Anzahl von Argumenten zu prüfen.

Optionale Parameter müssen auch deckungsgleich auch

Hinweis sein, dass alle Methoden einer generischen Funktion die gleiche Anzahl von optionalen Parameter haben müssen. Siehe die zweite Regel im Standard.

Wording

  • ein Parameter ist so etwas wie eine benannte Variable in einer Lambda-Liste
  • ein Argument in einem Aufruf einer Funktion versehen ist

Beispiele:

(defun foo (a b) (list a b)) 

a und b sind Parameter für die Funktion foo.

(foo (+ 2 3) (* 4 5)) 

5 und 20 sind die beiden Argumente für den Aufruf der Funktion foo.

Verwandte Themen