2014-02-20 9 views
3

Я пытаюсь выполнить «перегрузочный вызов» многоточия в Common Lisp. Вот упрощенная изношенном корпуса:«Перегрузка» CLOS-мультиметодов с различными списками параметров

(defclass foo() 
    ((slotty :accessor slotty :initarg :slotty))) 

(defclass bar() 
    ((slotty :accessor slotty :initarg :slotty))) 

(defparameter *foo* (make-instance 'foo :slotty "defnoodle")) 
(defparameter *bar* (make-instance 'bar :slotty "Chocolate")) 

(defmethod contrived ((f foo) (b bar)) 
    (format t "i pity the foo ~A, who has a bar ~A ~%" (slotty f) (slotty b))) 

(contrived *foo* *bar*) 

выходы: i pity the foo defnoodle, who has a bar Chocolate

Но как только я пытаюсь определить следующий метод:

(defmethod contrived ((f foo)) 
    (format t "i just pity the foo ~A ~%" (slotty f))) 

CL злится:

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

Кто-нибудь знает, что я делаю неправильно здесь? Я знаю, что initialize-instance имеет подобную гибкость, поскольку нужно иметь возможность идентифицировать n количество методов initialize-instance для каждого класса и для любого количества аргументов.

(defmethod initialize-instance :after ((f foo) &key) 
()) 

, но мне непонятно, как я могу перевести это на пример ванили, который я дал выше. И я чувствую, что могу лаять неправильное дерево, так как это часть СС.

+1

Это не перегрузка. Перегрузка означает раннее (компиляция) время привязки символов с тем же именем. То, что делает CLOS, - это _dispatch_, то есть поздняя (временная) привязка. Если у вас есть другое количество аргументов, нет необходимости откладывать это на время выполнения. Ограничение состоит в том, что у вас не может быть более одной общей функции с одним и тем же полным именем. – Svante

ответ

6

Вы пишете: Кто-нибудь знает, что я делаю неправильно здесь?

Чтобы было ясно: CLOS не поддерживает это. Вы не можете иметь разные числа требуемых аргументов в списках параметров метода методов одной общей функции. Диспетчер работает только с необходимыми аргументами. Common Lisp не поддерживает «перегрузку».

INITIALIZE-INSTANCE определяется с этим синтаксисом:

initialize-instance instance &rest initargs &key &allow-other-keys => instance 

Все методы принимают один обязательный аргумент, экземпляр. Отправка осуществляется только над этим объектом. Затем он разрешает различные аргументы ключевых слов - для них не выполняется диспетчеризация.

Таким образом, вам нужно согласовать количество требуемых аргументов, которые должна выполнять ваша общая функция, и называть это в вашем коде.

См. CL Hyperspec для правил: Congruent Lambda-lists for all Methods of a Generic Function.

3

Все методы общей функции должны иметь список конгруэнтных аргументов. Списки аргументов конгруэнтны, если у вас одинаковое количество требуемых аргументов, одинаковое количество необязательных аргументов и используйте &rest и &key в совместимом режиме.

Но, конечно, вы не можете специализироваться на видах аргументов &optional, &rest или &key.