调用下一个最具体的方法不起作用

Moo*_*ter 0 parameters methods common-lisp clos

考虑班级account:

(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)))
Run Code Online (Sandbox Code Playgroud)

对于这个类,我们定义一个方法withdraw:

(defmethod withdraw ((acct account) amt)
  (if (< amt (balance acct))
      (decf (balance acct) amt)
      'insufficient-funds))
Run Code Online (Sandbox Code Playgroud)

并且,另一个类password-account,它是以下的子类account:

(defclass password-account (account)
  ((password :initarg :password :reader password )))
Run Code Online (Sandbox Code Playgroud)

并且,该方法withdraw,对于这个类:

(defmethod withdraw ((acct password-account) amt pass)
  (if (equal (password acct) pass)
      (call-next-method acct amt )
      'wrong-password))
Run Code Online (Sandbox Code Playgroud)

但是这给出了一个错误:

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}>)
Run Code Online (Sandbox Code Playgroud)

为什么会这样?什么呢

被要求找到一个专业化的方法

这意味着什么

这里,主withdraw功能有两个参数acctamt,所以为了从一个更具体的方法,即用3个参数,而不是2调用它,我们可以提供call-next-method与较不具体的参数withdraw方法.但这仍然无效.
任何帮助赞赏.

Rai*_*wig 7

一致函数的全等lambda列表

通用函数的方法需要具有一致的 lambda列表.语言标准描述了这意味着:通用函数的所有方法的全等Lambda列表.

正如您所看到的,第一条规则说:

  • 每个lambda列表必须具有相同数量的必需参数.

必需参数告诉我们必须始终提供哪些参数.通用函数还允许可选,关键字和rest参数.但是这些都没有发送.调度仅适用于所需的参数和所有这些参数.

具有相同数量的必需参数使得调度更容易,并允许编译器检查具有错误数量的参数的函数调用.

可选参数也必须是一致的

另请注意,泛型函数的所有方法都需要具有相同数量的可选参数.请参阅标准中的第二条规则.

说法

  • 一个参数是像在拉姆达列表中的命名变量
  • 函数调用中提供了一个参数

例子:

(defun foo (a b) (list a b))
Run Code Online (Sandbox Code Playgroud)

a并且b是该功能的参数foo.

(foo (+ 2 3) (* 4 5))
Run Code Online (Sandbox Code Playgroud)

5并且20是函数调用的两个参数foo.