[HARLEQUIN][Common Lisp HyperSpec (TM)] [Previous][Up][Next]


Issue METHOD-COMBINATION-ARGUMENTS Writeup

Issue:         METHOD-COMBINATION-ARGUMENTS

References: Draft ANSI CL specification p.6-71

88-002R p.2-34

Category: CLARIFICATION

Edit history: 29-Apr-90, Version 1 by Moon

30-Apr-90, Version 2 by Moon (rewrite more clearly)

1-May-90, Version 3 by Moon (minor wording improvements)

4-May-90, Version 4 by Moon (update current practice)

6-Jun-90, Version 5 by Moon (add &WHOLE, update current practice)

8-Jun-90, Version 6 by Moon (include one-word amendment to &WHOLE

that was passed by X3J13 meeting)

Problem description:

The :ARGUMENTS option to DEFINE-METHOD-COMBINATION is not specified very

clearly. In particular, different generic functions using the type of

method combination being defined might accept different argument

patterns, so the lambda-list in the :ARGUMENTS option is unlikely to be

congruent to the generic function's lambda-list; the behavior when they

are not congruent should be clearly specified. Such mismatches often

occur in practice, as in the example on p.6-74 where the generic function

would typically have more than one argument.

88-002R says:

If lambda-list is not congruent to the generic function's lambda-list,

additional ignored parameters are automatically inserted until it is

congruent. Thus it is permissible for lambda-list to receive fewer

arguments than the number that the generic function expects.

The current ANSI CL draft says:

If the arguments supplied to the generic function do not match

lambda-list, extra arguments are ignored and missing arguments are

defaulted to nil. Thus it is permissible for lambda-list to receive

fewer arguments than the number of required arguments for the generic

function.

This is Symbolics issue #10.

Proposal (METHOD-COMBINATION-ARGUMENTS:CLARIFY):

Replace the sentences quoted above with the following sentences. Note

that these sentences immediately follow "When this form is evaluated

during execution of the effective method, its value is the corresponding

argument to the generic function."

This correspondence is computed by dividing the :ARGUMENTS lambda-list

and the generic function lambda-list into three sections: the required

parameters, the optional parameters, and the keyword/rest parameters.

The arguments supplied to the generic function for a particular call

are also divided into three sections; the required arguments section

contains as many arguments as the generic function has required

parameters, the optional arguments section contains as many arguments

as the generic function has optional parameters, and the keyword/rest

arguments section contains the remaining arguments. Each parameter in

the required and optional sections of the :ARGUMENTS lambda-list

accesses the argument at the same position in the corresponding section

of the arguments. If the section of the :ARGUMENTS lambda-list is

shorter, extra arguments are ignored. If the section of the :ARGUMENTS

lambda-list is longer, excess required parameters are bound to forms

that evaluate to NIL and excess optional parameters are bound to their

initforms. The keyword/rest parameters in the :ARGUMENTS lambda-list

access the keyword/rest section of the arguments. If the :ARGUMENTS

lambda-list contains &KEY, it behaves as if it also contained

&ALLOW-OTHER-KEYS.

In addition, &WHOLE <var> can be placed first in the :ARGUMENTS

lambda-list. It causes <var> to be bound to a form that evaluates to

a list of all of the arguments supplied to the generic function. This

is different from &REST because it accesses all of the arguments, not

just the keyword/rest arguments.

Examples:

The example in both documents is:

;;; Example of the use of :arguments

(define-method-combination progn-with-lock ()

((methods ()))

(:arguments object)

`(unwind-protect

(progn (lock (object-lock ,object))

,@(mapcar #'(lambda (method)

`(call-method ,method))

methods))

(unlock (object-lock ,object))))

This would be used as follows:

(defgeneric send (channel buffer &optional (start 0) end)

(:method-combination progn-with-lock))

where each channel class has an object-lock method.

A variation that uses non-required arguments in :arguments is:

(define-method-combination progn-with-lock-2 ()

((methods ()))

(:arguments &key lock)

`(unwind-protect

(progn (lock ,lock)

,@(mapcar #'(lambda (method)

`(call-method ,method))

methods))

(unlock ,lock)))

This would be used as follows:

(defgeneric send (channel buffer

&optional (start 0) end

&key lock character-set-translation)

(:method-combination progn-with-lock-2))

The :lock keyword argument comes from the third section of the arguments,

which for this generic function starts at the fourth argument.

To show how lambda-list mismatch works:

If (:ARGUMENTS a b c) meets DEFGENERIC (x y &optional z), the value of

the value of C will be NIL, not the value of Z.

To show the use of &WHOLE:

(define-method-combination progn-with-gf-lock ()

((methods ()))

(:arguments &whole args)

(:generic-function gf)

`(unwind-protect

(progn (lock-gf-args ,gf ,args)

,@(mapcar #'(lambda (method)

`(call-method ,method))

methods))

(unlock (unlock-gf-args ,gf ,args))))

Rationale:

This seems the only useful way to allow lambda-list-keywords in the

:ARGUMENTS lambda-list while solving the congruency problems. It's likely

that this is not a change from what was originally intended, but just a

more precise way of describing it. The examples show why both &WHOLE and

&REST are needed; using &REST in the progn-with-gf-lock example is not

consistent with using &KEY in the progn-with-lock-2 example.

Current practice:

Symbolics Genera 8.0.1 (to be released in a few months) will implement the

proposal, possibly omitting &WHOLE. In Symbolics Genera 8.0 the :ARGUMENTS

option to DEFINE-METHOD-COMBINATION does not work at all (it produces

incorrect code that does not compile).

TI Explorer release 6 has :ARGUMENTS in DEFINE-METHOD-COMBINATION, but

its status relative to the proposed clarification is unknown at present.

Recent versions of PCL support :ARGUMENTS in DEFINE-METHOD-COMBINATION

but do not seem to conform to the proposal -- I think PCL just

effectively appends "&rest ignore" to the :arguments lambda-list.

I did not discover any other CLOS implementations that support

:ARGUMENTS.

Cost to Implementors:

This does not make supporting :ARGUMENTS more difficult.

Cost to Users:

None.

Cost of non-adoption:

:ARGUMENTS will be specified in a way that can't be understood.

Performance impact:

None.

Benefits:

:ARGUMENTS will be usable in the relatively rare circumstances where it

is needed.

Esthetics:

A specification that can be understood is more esthetic than one that

cannot be.

Discussion:

None.


[Starting Points][Contents][Index][Symbols][Glossary][Issues]
Copyright 1996, The Harlequin Group Limited. All Rights Reserved.