1
0
Fork 0
cl-sites/HyperSpec-7-0/HyperSpec/Issues/iss242_w.htm
2024-04-01 10:24:07 +02:00

224 lines
14 KiB
HTML

<!-- Common Lisp HyperSpec (TM), version 7.0 generated by Kent M. Pitman on Mon, 11-Apr-2005 2:31am EDT -->
<HTML>
<HEAD>
<TITLE>CLHS: Issue METHOD-COMBINATION-ARGUMENTS Writeup</TITLE>
<LINK HREF="../Data/clhs.css" REL="stylesheet" TYPE="text/css" />
<META HTTP-EQUIV="Author" CONTENT="Kent M. Pitman">
<META HTTP-EQUIV="Organization" CONTENT="LispWorks Ltd.">
<LINK REL=TOP HREF="../Front/index.htm">
<LINK REL=COPYRIGHT HREF="../Front/Help.htm#Legal">
<LINK REL=DISCLAIMER HREF="../Front/Help.htm#Disclaimer">
<LINK REL=PREV HREF="../Issues/iss241_w.htm">
<LINK REL=UP HREF="../Issues/iss242.htm">
<LINK REL=NEXT HREF="../Issues/iss243_w.htm">
</HEAD>
<BODY>
<H1><A REV=MADE HREF="http://www.lispworks.com/"><IMG WIDTH=80 HEIGHT=65 ALT="[LISPWORKS]" SRC="../Graphics/LWSmall.gif" ALIGN=Bottom></A><A REL=TOP HREF="../Front/index.htm"><IMG WIDTH=237 HEIGHT=65 ALT="[Common Lisp HyperSpec (TM)]" SRC="../Graphics/CLHS_Sm.gif" ALIGN=Bottom></A> <A REL=PREV HREF="../Issues/iss241_w.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Previous]" SRC="../Graphics/Prev.gif" ALIGN=Bottom></A><A REL=UP HREF="../Issues/iss242.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Up]" SRC="../Graphics/Up.gif" ALIGN=Bottom></A><A REL=NEXT HREF="../Issues/iss243_w.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Next]" SRC="../Graphics/Next.gif" ALIGN=Bottom></A></H1>
<HR>
<H2>Issue METHOD-COMBINATION-ARGUMENTS Writeup</H2>
<PRE><B>Issue:</B> <A HREF="iss242.htm">METHOD-COMBINATION-ARGUMENTS</A><P>
<P>
<B>References:</B> Draft ANSI CL specification p.6-71<P>
88-002R p.2-34<P>
<P>
<B>Category:</B> CLARIFICATION<P>
<P>
<B>Edit history:</B> 29-Apr-90, Version 1 by Moon<P>
30-Apr-90, Version 2 by Moon (rewrite more clearly)<P>
1-May-90, Version 3 by Moon (minor wording improvements)<P>
4-May-90, Version 4 by Moon (update current practice)<P>
6-Jun-90, Version 5 by Moon (add <A REL=DEFINITION HREF="../Body/03_dd.htm#AMwhole"><B>&amp;WHOLE</B></A>, update current practice)<P>
8-Jun-90, Version 6 by Moon (include one-word amendment to <A REL=DEFINITION HREF="../Body/03_dd.htm#AMwhole"><B>&amp;WHOLE</B></A><P>
that was passed by X3J13 meeting)<P>
<P>
<B>Problem description:<P>
</B><P>
The :ARGUMENTS option to <A REL=DEFINITION HREF="../Body/m_defi_4.htm#define-method-combination"><B>DEFINE-METHOD-COMBINATION</B></A> is not specified very<P>
clearly. In particular, different generic functions using the type of<P>
<A REL=DEFINITION HREF="../Body/t_method.htm#method"><B>method</B></A> combination being defined might accept different argument<P>
patterns, so the lambda-list in the :ARGUMENTS option is unlikely to be<P>
congruent to the generic function's lambda-list; the behavior when they<P>
are not congruent should be clearly specified. Such mismatches often<P>
occur in practice, as in the example on p.6-74 where the generic function<P>
would typically have more than one argument.<P>
<P>
88-002R says:<P>
<P>
If lambda-list is not congruent to the generic function's lambda-list,<P>
additional ignored parameters are automatically inserted until it is<P>
congruent. Thus it is permissible for lambda-list to receive fewer<P>
arguments than the number that the generic function expects.<P>
<P>
The current ANSI CL draft says:<P>
<P>
If the arguments supplied to the generic function do not match<P>
lambda-list, extra arguments are ignored and missing arguments are<P>
defaulted to nil. Thus it is permissible for lambda-list to receive<P>
fewer arguments than the number of required arguments for the generic<P>
function.<P>
<P>
This is Symbolics issue #10.<P>
<P>
<B>Proposal (METHOD-COMBINATION-ARGUMENTS:CLARIFY):<P>
</B><P>
Replace the sentences quoted above with the following sentences. Note<P>
that these sentences immediately follow &quot;When this form is evaluated<P>
during execution of the effective <A REL=DEFINITION HREF="../Body/t_method.htm#method"><B>method</B></A>, its value is the corresponding<P>
argument to the generic function.&quot;<P>
<P>
This correspondence is computed by dividing the :ARGUMENTS lambda-list<P>
and the generic function lambda-list into three sections: the required<P>
parameters, the optional parameters, and the keyword/rest parameters.<P>
The arguments supplied to the generic function for a particular call<P>
are also divided into three sections; the required arguments section<P>
contains as many arguments as the generic function has required<P>
parameters, the optional arguments section contains as many arguments<P>
as the generic function has optional parameters, and the keyword/rest<P>
arguments section contains the remaining arguments. Each parameter in<P>
the required and optional sections of the :ARGUMENTS lambda-list<P>
accesses the argument at the same position in the corresponding section<P>
of the arguments. If the section of the :ARGUMENTS lambda-list is<P>
shorter, extra arguments are ignored. If the section of the :ARGUMENTS<P>
lambda-list is longer, excess required parameters are bound to forms<P>
that evaluate to <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A> and excess optional parameters are bound to their<P>
initforms. The keyword/rest parameters in the :ARGUMENTS lambda-list<P>
access the keyword/rest section of the arguments. If the :ARGUMENTS<P>
lambda-list contains <A REL=DEFINITION HREF="../Body/03_da.htm#AMkey"><B>&amp;KEY</B></A>, it behaves as if it also contained<P>
<A REL=DEFINITION HREF="../Body/03_da.htm#AMallow-other-keys"><B>&amp;ALLOW-OTHER-KEYS</B></A>.<P>
<P>
In addition, <A REL=DEFINITION HREF="../Body/03_dd.htm#AMwhole"><B>&amp;WHOLE</B></A> &lt;var&gt; can be placed first in the :ARGUMENTS<P>
lambda-list. It causes &lt;var&gt; to be bound to a form that evaluates to<P>
a list of all of the arguments supplied to the generic function. This<P>
is different from <A REL=DEFINITION HREF="../Body/03_da.htm#AMrest"><B>&amp;REST</B></A> because it accesses all of the arguments, not<P>
just the keyword/rest arguments.<P>
<P>
<B>Examples:<P>
</B><P>
The example in both documents is:<P>
<P>
;;; Example of the use of :arguments<P>
(<A REL=DEFINITION HREF="../Body/m_defi_4.htm#define-method-combination"><B>define-method-combination</B></A> progn-with-lock ()<P>
((methods ()))<P>
(:arguments object)<P>
`(<A REL=DEFINITION HREF="../Body/s_unwind.htm#unwind-protect"><B>unwind-protect</B></A><P>
(<A REL=DEFINITION HREF="../Body/s_progn.htm#progn"><B>progn</B></A> (lock (object-lock ,object))<P>
,@(<A REL=DEFINITION HREF="../Body/f_mapc_.htm#mapcar"><B>mapcar</B></A> #'(<A REL=DEFINITION HREF="../Body/a_lambda.htm#lambda"><B>lambda</B></A> (<A REL=DEFINITION HREF="../Body/t_method.htm#method"><B>method</B></A>)<P>
`(<A REL=DEFINITION HREF="../Body/m_call_m.htm#call-method"><B>call-method</B></A> ,<A REL=DEFINITION HREF="../Body/t_method.htm#method"><B>method</B></A>))<P>
methods))<P>
(unlock (object-lock ,object))))<P>
<P>
This would be used as follows:<P>
<P>
(<A REL=DEFINITION HREF="../Body/m_defgen.htm#defgeneric"><B>defgeneric</B></A> send (channel buffer <A REL=DEFINITION HREF="../Body/03_da.htm#AMoptional"><B>&amp;optional</B></A> (start 0) end)<P>
(:method-combination progn-with-lock))<P>
<P>
where each channel <A REL=DEFINITION HREF="../Body/t_class.htm#class"><B>class</B></A> has an object-lock <A REL=DEFINITION HREF="../Body/t_method.htm#method"><B>method</B></A>.<P>
<P>
A variation that uses non-required arguments in :arguments is:<P>
<P>
(<A REL=DEFINITION HREF="../Body/m_defi_4.htm#define-method-combination"><B>define-method-combination</B></A> progn-with-lock-2 ()<P>
((methods ()))<P>
(:arguments <A REL=DEFINITION HREF="../Body/03_da.htm#AMkey"><B>&amp;key</B></A> lock)<P>
`(<A REL=DEFINITION HREF="../Body/s_unwind.htm#unwind-protect"><B>unwind-protect</B></A><P>
(<A REL=DEFINITION HREF="../Body/s_progn.htm#progn"><B>progn</B></A> (lock ,lock)<P>
,@(<A REL=DEFINITION HREF="../Body/f_mapc_.htm#mapcar"><B>mapcar</B></A> #'(<A REL=DEFINITION HREF="../Body/a_lambda.htm#lambda"><B>lambda</B></A> (<A REL=DEFINITION HREF="../Body/t_method.htm#method"><B>method</B></A>)<P>
`(<A REL=DEFINITION HREF="../Body/m_call_m.htm#call-method"><B>call-method</B></A> ,<A REL=DEFINITION HREF="../Body/t_method.htm#method"><B>method</B></A>))<P>
methods))<P>
(unlock ,lock)))<P>
<P>
This would be used as follows:<P>
<P>
(<A REL=DEFINITION HREF="../Body/m_defgen.htm#defgeneric"><B>defgeneric</B></A> send (channel buffer<P>
<A REL=DEFINITION HREF="../Body/03_da.htm#AMoptional"><B>&amp;optional</B></A> (start 0) end<P>
<A REL=DEFINITION HREF="../Body/03_da.htm#AMkey"><B>&amp;key</B></A> lock character-set-translation)<P>
(:method-combination progn-with-lock-2))<P>
<P>
The :lock keyword argument comes from the third section of the arguments,<P>
which for this generic function starts at the fourth argument.<P>
<P>
To show how lambda-list mismatch works:<P>
<P>
If (:ARGUMENTS a b c) meets <A REL=DEFINITION HREF="../Body/m_defgen.htm#defgeneric"><B>DEFGENERIC</B></A> (x y &amp;optional z), the value of<P>
the value of C will be <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A>, not the value of Z.<P>
<P>
To show the use of &amp;WHOLE:<P>
<P>
(<A REL=DEFINITION HREF="../Body/m_defi_4.htm#define-method-combination"><B>define-method-combination</B></A> progn-with-gf-lock ()<P>
((methods ()))<P>
(:arguments <A REL=DEFINITION HREF="../Body/03_dd.htm#AMwhole"><B>&amp;whole</B></A> args)<P>
(:generic-function gf)<P>
`(<A REL=DEFINITION HREF="../Body/s_unwind.htm#unwind-protect"><B>unwind-protect</B></A><P>
(<A REL=DEFINITION HREF="../Body/s_progn.htm#progn"><B>progn</B></A> (lock-gf-args ,gf ,args) <P>
,@(<A REL=DEFINITION HREF="../Body/f_mapc_.htm#mapcar"><B>mapcar</B></A> #'(<A REL=DEFINITION HREF="../Body/a_lambda.htm#lambda"><B>lambda</B></A> (<A REL=DEFINITION HREF="../Body/t_method.htm#method"><B>method</B></A>)<P>
`(<A REL=DEFINITION HREF="../Body/m_call_m.htm#call-method"><B>call-method</B></A> ,<A REL=DEFINITION HREF="../Body/t_method.htm#method"><B>method</B></A>))<P>
methods))<P>
(unlock (unlock-gf-args ,gf ,args))))<P>
<P>
<B>Rationale:<P>
</B><P>
This seems the only useful way to allow <A REL=DEFINITION HREF="../Body/v_lambda.htm#lambda-list-keywords"><B>lambda-list-keywords</B></A> in the<P>
:ARGUMENTS lambda-list while solving the congruency problems. It's likely<P>
that this is not a change from what was originally intended, but just a<P>
more precise way of describing it. The examples show why both <A REL=DEFINITION HREF="../Body/03_dd.htm#AMwhole"><B>&amp;WHOLE</B></A> and<P>
<A REL=DEFINITION HREF="../Body/03_da.htm#AMrest"><B>&amp;REST</B></A> are needed; using <A REL=DEFINITION HREF="../Body/03_da.htm#AMrest"><B>&amp;REST</B></A> in the progn-with-gf-lock example is not<P>
consistent with using <A REL=DEFINITION HREF="../Body/03_da.htm#AMkey"><B>&amp;KEY</B></A> in the progn-with-lock-2 example.<P>
<P>
<B>Current practice:<P>
</B><P>
Symbolics Genera 8.0.1 (to be released in a few months) will implement the<P>
proposal, possibly omitting <A REL=DEFINITION HREF="../Body/03_dd.htm#AMwhole"><B>&amp;WHOLE</B></A>. In Symbolics Genera 8.0 the :ARGUMENTS<P>
option to <A REL=DEFINITION HREF="../Body/m_defi_4.htm#define-method-combination"><B>DEFINE-METHOD-COMBINATION</B></A> does not work at all (it produces<P>
incorrect code that does not compile).<P>
<P>
TI Explorer release 6 has :ARGUMENTS in <A REL=DEFINITION HREF="../Body/m_defi_4.htm#define-method-combination"><B>DEFINE-METHOD-COMBINATION</B></A>, but<P>
its status relative to the proposed clarification is unknown at present.<P>
<P>
Recent versions of PCL support :ARGUMENTS in <A REL=DEFINITION HREF="../Body/m_defi_4.htm#define-method-combination"><B>DEFINE-METHOD-COMBINATION</B></A><P>
but do not seem to conform to the proposal -- I think PCL just<P>
effectively appends &quot;&amp;rest ignore&quot; to the :arguments lambda-list.<P>
<P>
I did not discover any other CLOS implementations that support<P>
:ARGUMENTS.<P>
<P>
<B>Cost to Implementors:<P>
</B><P>
This does not make supporting :ARGUMENTS more difficult.<P>
<P>
<B>Cost to Users:<P>
</B><P>
None.<P>
<P>
<B>Cost of non-adoption:<P>
</B><P>
:ARGUMENTS will be specified in a way that can't be understood.<P>
<P>
<B>Performance impact:<P>
</B><P>
None.<P>
<P>
<B>Benefits:<P>
</B><P>
:ARGUMENTS will be usable in the relatively rare circumstances where it<P>
is needed.<P>
<P>
<B>Esthetics:<P>
</B><P>
A specification that can be understood is more esthetic than one that<P>
cannot be.<P>
<P>
<B>Discussion:<P>
</B><P>
None.<P>
</PRE>
<HR>
<A REL=NAVIGATOR HREF="../Front/StartPts.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Starting Points]" SRC="../Graphics/StartPts.gif" ALIGN=Bottom></A><A REL=TOC HREF="../Front/Contents.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Contents]" SRC="../Graphics/Contents.gif" ALIGN=Bottom></A><A REL=INDEX HREF="../Front/X_Master.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Index]" SRC="../Graphics/Index.gif" ALIGN=Bottom></A><A REL=INDEX HREF="../Front/X_Symbol.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Symbols]" SRC="../Graphics/Symbols.gif" ALIGN=Bottom></A><A REL=GLOSSARY HREF="../Body/26_a.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Glossary]" SRC="../Graphics/Glossary.gif" ALIGN=Bottom></A><A HREF="../Front/X3J13Iss.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Issues]" SRC="../Graphics/Issues.gif" ALIGN=Bottom></A><BR>
<A REL=COPYRIGHT HREF="../Front/Help.htm#Legal"><I>Copyright 1996-2005, LispWorks Ltd. All rights reserved.</I></A><P>
</BODY>
</HTML>