173 lines
63 KiB
HTML
173 lines
63 KiB
HTML
|
<!doctype html>
|
|||
|
<html lang="en" dir="ltr" class="docs-wrapper plugin-docs plugin-id-default docs-version-current docs-doc-page docs-doc-id-meta-object-protocol/chap-5/5-4-processing" data-has-hydrated="false">
|
|||
|
<head>
|
|||
|
<meta charset="UTF-8">
|
|||
|
<meta name="generator" content="Docusaurus v3.0.1">
|
|||
|
<title data-rh="true">5.4 Processing Of The User Interface Macros | Common Lisp (New) Language Reference</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:image" content="https://lisp-docs.github.io/cl-language-reference/img/1024px-Lisp_logo.svg.png"><meta data-rh="true" name="twitter:image" content="https://lisp-docs.github.io/cl-language-reference/img/1024px-Lisp_logo.svg.png"><meta data-rh="true" property="og:url" content="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/chap-5/5-4-processing"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="google-site-verification" content="Vzaw013_bfdKeUVG89Ch3W1zC9_vH9ID2dPB9Dz0vr0"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="5.4 Processing Of The User Interface Macros | Common Lisp (New) Language Reference"><meta data-rh="true" name="description" content="5.4.1 Compile File Processing Of The User Interface Macros"><meta data-rh="true" property="og:description" content="5.4.1 Compile File Processing Of The User Interface Macros"><link data-rh="true" rel="icon" href="../../img/favicon.ico"><link data-rh="true" rel="canonical" href="5-4-processing.html"><link data-rh="true" rel="alternate" href="5-4-processing.html" hreflang="en"><link data-rh="true" rel="alternate" href="5-4-processing.html" hreflang="x-default"><link data-rh="true" rel="preconnect" href="https://C1F2Q5VM6X-dsn.algolia.net" crossorigin="anonymous"><link rel="preconnect" href="https://www.google-analytics.com">
|
|||
|
<link rel="preconnect" href="https://www.googletagmanager.com">
|
|||
|
<script async src="https://www.googletagmanager.com/gtag/js?id=G-8TJCE4NSF8"></script>
|
|||
|
<script>function gtag(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],gtag("js",new Date),gtag("config","G-8TJCE4NSF8",{})</script>
|
|||
|
|
|||
|
|
|||
|
<link rel="search" type="application/opensearchdescription+xml" title="Common Lisp (New) Language Reference" href="../../opensearch.xml"><link rel="stylesheet" href="../../assets/css/styles.f13b59fe.css">
|
|||
|
<script src="../../assets/js/runtime~main.02699c25.js" defer="defer"></script>
|
|||
|
<script src="../../assets/js/main.4f0a7a76.js" defer="defer"></script>
|
|||
|
</head>
|
|||
|
<body class="navigation-with-keyboard">
|
|||
|
<script>!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){try{return new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}}()||function(){try{return localStorage.getItem("theme")}catch(t){}}();t(null!==e?e:"light")}(),function(){try{const c=new URLSearchParams(window.location.search).entries();for(var[t,e]of c)if(t.startsWith("docusaurus-data-")){var a=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}()</script><div id="__docusaurus"><div role="region" aria-label="Skip to main content"><a class="skipToContent_fXgn" href="5-4-processing.html#__docusaurus_skipToContent_fallback">Skip to main content</a></div><nav aria-label="Main" class="navbar navbar--fixed-top"><div class="navbar__inner"><div class="navbar__items"><button aria-label="Toggle navigation bar" aria-expanded="false" class="navbar__toggle clean-btn" type="button"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a href="../../../index.html" target="_blank" rel="noopener noreferrer" class="navbar__brand"><div class="navbar__logo"><img src="../../img/logo.svg" alt="Lisp Logo" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="../../img/logo.svg" alt="Lisp Logo" class="themedComponent_mlkZ themedComponent--dark_xIcU"></div><b class="navbar__title text--truncate">Common Lisp Docs</b></a><a href="../../../docs/tutorial/index.html" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">Tutorial</a><a href="../../index.html" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">Technical Reference</a><a href="../../../docs/whylisp.html" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">Why Lisp?</a><a href="../../../docs/howto.html" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">Guides</a></div><div class="navbar__items navbar__items--right"><a href="../../../docs/contribute.html" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">Contribute!</a><a href="../../../docs/help.html" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">Getting Help</a><a href="../../../docs/about.html" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">About</a><a href="../../../blog.html" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">Blog</a><a href="https://github.com/lisp-docs" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">GitHub<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a><div class="toggle_vylO colorModeToggle_DEke"><button class="clean-btn toggleButton_gllP toggleButtonDisabled_aARS" type="button" disabled="" title="Switch between dark and light mode (currently light mode)" aria-label="Switch between dark and light mode (currently light mode)" aria-live="polite"><svg viewBox="0 0 24 24" width="24" height="24" class="lightToggleIcon_pyhR"><path fill="currentColor" d="M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.
|
|||
|
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="processing-of-the-user-interface-macros-1">Processing of the user interface macros<a href="5-4-processing.html#processing-of-the-user-interface-macros-1" class="hash-link" aria-label="Direct link to Processing of the user interface macros" title="Direct link to Processing of the user interface macros"></a></h2>
|
|||
|
<p>A list in which the first element is one of the symbols <a href="http://www.lispworks.com/documentation/HyperSpec/Body/m_defcla.htm#defclass" target="_blank" rel="noopener noreferrer">defclass</a>, <a href="http://www.lispworks.com/documentation/HyperSpec/Body/m_defmet.htm#defmethod" target="_blank" rel="noopener noreferrer">defmethod</a>, <a href="http://www.lispworks.com/documentation/HyperSpec/Body/m_defgen.htm#defgeneric" target="_blank" rel="noopener noreferrer">defgeneric</a>, <a href="http://www.lispworks.com/documentation/HyperSpec/Body/m_defi_4.htm#define-method-combination" target="_blank" rel="noopener noreferrer">define-method-combination</a>, <code>generic-function</code>, <code>generic-flet</code> or <code>generic-labels</code>, and which has proper syntax for that macro is called a <em>user interface macro form</em>. This document provides an extended specification of the <a href="http://www.lispworks.com/documentation/HyperSpec/Body/m_defcla.htm#defclass" target="_blank" rel="noopener noreferrer">defclass</a>, <a href="http://www.lispworks.com/documentation/HyperSpec/Body/m_defmet.htm#defmethod" target="_blank" rel="noopener noreferrer">defmethod</a> and <a href="http://www.lispworks.com/documentation/HyperSpec/Body/m_defgen.htm#defgeneric" target="_blank" rel="noopener noreferrer">defgeneric</a> macros.</p>
|
|||
|
<p>The user interface macros <a href="http://www.lispworks.com/documentation/HyperSpec/Body/m_defcla.htm#defclass" target="_blank" rel="noopener noreferrer">defclass</a>, <a href="http://www.lispworks.com/documentation/HyperSpec/Body/m_defgen.htm#defgeneric" target="_blank" rel="noopener noreferrer">defgeneric</a> and <a href="http://www.lispworks.com/documentation/HyperSpec/Body/m_defmet.htm#defmethod" target="_blank" rel="noopener noreferrer">defmethod</a> can be used not only to define metaobjects that are instances of the corresponding standard metaobject class, but also to define metaobjects that are instances of appropriate portable metaobject classes. To make it possible for portable metaobject classes to properly process the information appearing in the macro form, this document provides a limited specification of the processing of these macro forms.</p>
|
|||
|
<p>User interface macro forms can be <code>evaluated</code> or <code>compiled</code> and later <code>executed</code>. The effect of evaluating or executing a user interface macro form is specified in terms of calls to specified functions and generic functions which provide the actual behavior of the macro. The arguments received by these functions and generic functions are derived in a specified way from the macro form.</p>
|
|||
|
<p>Converting a user interface macro form into the arguments to the appropriate functions and generic functions has two major aspects: the conversion of the macro argument syntax into a form more suitable for later processing, and the processing of macro arguments which are forms to be evaluated (including method bodies).</p>
|
|||
|
<p>In the syntax of the <a href="http://www.lispworks.com/documentation/HyperSpec/Body/m_defcla.htm#defclass" target="_blank" rel="noopener noreferrer">defclass</a> macro, the <em>initform</em> and <em>default-initarg-initial-value-form</em> arguments are forms which will be evaluated one or more times after the macro form is evaluated or executed. Special processing must be done on these arguments to ensure that the lexical scope of the forms is captured properly. This is done by building a function of zero arguments which, when called, returns the result of evaluating the form in the proper lexical environment.</p>
|
|||
|
<p>In the syntax of the <a href="http://www.lispworks.com/documentation/HyperSpec/Body/m_defmet.htm#defmethod" target="_blank" rel="noopener noreferrer">defmethod</a> macro the <em>form</em>* argument is a list of forms that comprise the body of the method definition. This list of forms must be processed specially to capture the lexical scope of the macro form. In addition, the lexical functions available only in the body of methods must be introduced. To allow this and any other special processing (such as slot access optimization), a specializable protocol is used for processing the body of methods. This is discussed in <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/processing-method-bodies">the section ``Processing Method Bodies.''</a></p>
|
|||
|
<ul>
|
|||
|
<li><a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/compile-file-processing-of-the-user-interface-macros">Compile-file processing of the user interface macros.</a></li>
|
|||
|
<li><a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/the-defclass-macro">The <code>defclass</code> macro.</a></li>
|
|||
|
<li><a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/the-defmethod-macro">The <code>defmethod</code> macro.</a></li>
|
|||
|
<li><a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/processing-method-bodies">Processing method bodies.</a></li>
|
|||
|
<li><a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/the-defgeneric-macro">The <code>defgeneric</code> macro.</a></li>
|
|||
|
</ul>
|
|||
|
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="541-compile-file-processing-of-the-user-interface-macros">5.4.1 Compile File Processing Of The User Interface Macros<a href="5-4-processing.html#541-compile-file-processing-of-the-user-interface-macros" class="hash-link" aria-label="Direct link to 5.4.1 Compile File Processing Of The User Interface Macros" title="Direct link to 5.4.1 Compile File Processing Of The User Interface Macros"></a></h2>
|
|||
|
<!-- -->
|
|||
|
<h1>Compile-file processing of the user interface macros</h1>
|
|||
|
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="compile-file-processing-of-the-user-interface-macros-1">Compile-file processing of the user interface macros<a href="5-4-processing.html#compile-file-processing-of-the-user-interface-macros-1" class="hash-link" aria-label="Direct link to Compile-file processing of the user interface macros" title="Direct link to Compile-file processing of the user interface macros"></a></h3>
|
|||
|
<p>It is common practice for Common Lisp compilers, while processing a file or set of files, to maintain information about the definitions that have been compiled so far. Among other things, this makes it possible to ensure that a global macro definition (<a href="http://www.lispworks.com/documentation/HyperSpec/Body/m_defmac.htm#defmacro" target="_blank" rel="noopener noreferrer">defmacro</a> form) which appears in a file will affect uses of the macro later in that file. This information about the state of the compilation is called the <em>compile-file environment</em>.</p>
|
|||
|
<p>When compiling files containing CLOS definitions, it is useful to maintain certain additional information in the compile-file environment. This can make it possible to issue various kinds of warnings (e.g., lambda list congruence) and to do various performance optimizations that would not otherwise be possible.</p>
|
|||
|
<p>At this time, there is such significant variance in the way existing Common Lisp implementations handle compile-file environments that it would be premature to specify this mechanism. Consequently, this document specifies only the behavior of evaluating or executing user interface macro forms. What functions and generic functions are called during compile-file processing of a user interface macro form is not specified. Implementations are free to define and document their own behavior. Users may need to check implementation-specific behavior before attempting to compile certain portable programs.</p>
|
|||
|
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="542-the-defclass-macro">5.4.2 The Defclass Macro<a href="5-4-processing.html#542-the-defclass-macro" class="hash-link" aria-label="Direct link to 5.4.2 The Defclass Macro" title="Direct link to 5.4.2 The Defclass Macro"></a></h2>
|
|||
|
<!-- -->
|
|||
|
<h1>The defclass macro</h1>
|
|||
|
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="the-defclass-macro-1">The <code>defclass</code> macro<a href="5-4-processing.html#the-defclass-macro-1" class="hash-link" aria-label="Direct link to the-defclass-macro-1" title="Direct link to the-defclass-macro-1"></a></h3>
|
|||
|
<p>The evaluation or execution of a <code>defclass</code> form results in a call to the <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-class">ensure-class</a> function. The arguments received by <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-class">ensure-class</a> are derived from the <code>defclass</code> form in a defined way. The exact macro-expansion of the <code>defclass</code> form is not defined, only the relationship between the arguments to the <code>defclass</code> macro and the arguments received by the <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-class">ensure-class</a> function. Examples of typical <code>defclass</code> forms and sample expansions are shown in the Figures below.</p>
|
|||
|
<hr>
|
|||
|
<p>(defclass plane (moving-object graphics-object)
|
|||
|
((altitude <!-- -->:initform<!-- --> 0 <!-- -->:accessor<!-- --> plane-altitude)
|
|||
|
(speed))
|
|||
|
(<!-- -->:default-initargs<!-- --> <!-- -->:engine<!-- --> <em>jet</em>))</p>
|
|||
|
<p>(ensure-class 'plane
|
|||
|
'<!-- -->:direct-superclasses<!-- --> '(moving-object graphics-object)
|
|||
|
'<!-- -->:direct-slots<!-- --> (list (list '<!-- -->:name<!-- --> 'altitude
|
|||
|
'<!-- -->:initform<!-- --> '0
|
|||
|
'<!-- -->:initfunction<!-- --> #'(lambda () 0)
|
|||
|
'<!-- -->:readers<!-- --> '(plane-altitude)
|
|||
|
'<!-- -->:writers<!-- --> '((setf plane-altitude)))
|
|||
|
(list '<!-- -->:name<!-- --> 'speed))
|
|||
|
'<!-- -->:direct-default-initargs<!-- --> (list (list '<!-- -->:engine<!-- -->
|
|||
|
'<em>jet</em>
|
|||
|
#'(lambda () <em>jet</em>))))</p>
|
|||
|
<hr>
|
|||
|
<p>A <code>defclass</code> form with standard slot and class options and an expansion of it that would result in the proper call to <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-class">ensure-class</a>.</p>
|
|||
|
<hr>
|
|||
|
<p>(defclass sst (plane)
|
|||
|
((mach mag-step 2
|
|||
|
locator sst-mach
|
|||
|
locator mach-location
|
|||
|
<!-- -->:reader<!-- --> mach-speed
|
|||
|
<!-- -->:reader<!-- --> mach))
|
|||
|
(<!-- -->:metaclass<!-- --> faster-class)
|
|||
|
(another-option foo bar))</p>
|
|||
|
<p>(ensure-class 'sst
|
|||
|
'<!-- -->:direct-superclasses<!-- --> '(plane)
|
|||
|
'<!-- -->:direct-slots<!-- --> (list (list '<!-- -->:name<!-- --> 'mach
|
|||
|
'<!-- -->:readers<!-- --> '(mach-speed mach)
|
|||
|
'mag-step '2
|
|||
|
'locator '(sst-mach mach-location)))
|
|||
|
'<!-- -->:metaclass<!-- --> 'faster-class
|
|||
|
'another-option '(foo bar))</p>
|
|||
|
<hr>
|
|||
|
<p>A <code>defclass</code> form with non-standard class and slot options, and an expansion of it which results in the proper call to <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-class">ensure-class</a>. Note that the order of the slot options has not affected the order of the properties in the canonicalized slot specification, but has affected the order of the elements in the lists which are the values of those properties.</p>
|
|||
|
<p>The <em>name</em> argument to <code>defclass</code> becomes the value of the first argument to <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-class">ensure-class</a>. This is the only positional argument accepted by <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-class">ensure-class</a>; all other arguments are keyword arguments.</p>
|
|||
|
<p>The <em>direct-superclasses</em> argument to <code>defclass</code> becomes the value of the <code>:direct-super-classes</code> keyword argument to <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-class">ensure-class</a>.</p>
|
|||
|
<p>The <em>direct slots</em> argument to <code>defclass</code> becomes the value of the <code>:direct-slots</code> keyword argument to <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-class">ensure-class</a>. Special processing of this value is done to regularize the form of each slot specification and to properly capture the lexical scope of the initialization forms. This is done by converting each slot specification to a property list called a <em>canonicalized slot specification</em>. The resulting list of canonicalized slot specifications is the value of the <code>:direct-slots</code> keyword argument.</p>
|
|||
|
<p>Canonicalized slot specifications are later used as the keyword arguments to a generic function which will, in turn, pass them to <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/make-instance">make-instance</a> for use as a set of initialization arguments. Each canonicalized slot specification is formed from the corresponding slot specification as follows:</p>
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
<p>The name of the slot is the value of the <code>:name</code> property. This property appears in every canonicalized slot specification.</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p>When the <code>:initform</code> slot option is present in the slot specification, then both the <code>:initform</code> and <code>:initfunction</code> properties are present in the canonicalized slot specification. The value of the <code>:initform</code> property is the initialization form. The value of the <code>:initfunction</code> property is a function of zero arguments which, when called, returns the result of evaluating the initialization form in its proper lexical environment.</p>
|
|||
|
<p>If the <code>:initform</code> slot option is not present in the slot specification, then either the <code>:initfunction</code> property will not appear, or its value will be false. In such cases, the value of the <code>:initform</code> property, or whether it appears, is unspecified.</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p>The value of the <code>:initargs</code> property is a list of the values of each <code>:initarg</code> slot option. If there are no <code>:initarg</code> slot options, then either the <code>:initargs</code> property will not appear or its value will be the empty list.</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p>The value of the <code>:readers</code> property is a list of the values of each <code>:reader</code> and <code>:accessor</code> slot option. If there are no <code>:reader</code> or <code>:accessor</code> slot options, then either the <code>:readers</code> property will not appear or its value will be the empty list.</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p>The value of the <code>:writers</code> property is a list of the values specified by each <code>:writer</code> and <code>:accessor</code> slot option. The value specified by a <code>:writer</code> slot option is just the value of the slot option. The value specified by an <code>:accessor</code> slot option is a two element list: the first element is the symbol <code>setf</code>, the second element is the value of the slot option. If there are no <code>:writer</code> or <code>:accessor</code> slot options, then either the <code>:writers</code> property will not appear or its value will be the empty list.</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p>The value of the <code>:documentation</code> property is the value of the <code>:documentation</code> slot option. If there is no <code>:documentation</code> slot option, then either the <code>:documentation</code> property will not appear or its value will be false.</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p>All other slot options appear as the values of properties with the same name as the slot option. Note that this includes not only the remaining standard slot options (<code>:allocation</code> and <code>:type</code>), but also any other options and values appearing in the slot specification. If one of these slot options appears more than once, the value of the property will be a list of the specified values.</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p>An implementation is free to add additional properties to the canonicalized slot specification provided these are not symbols accessible in the <code>common-lisp-user</code> package, or exported by any package defined in the ANSI Common Lisp standard.</p>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
<p>Returning to the correspondence between arguments to the <code>defclass</code> macro and the arguments received by the <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-class">ensure-class</a> function:</p>
|
|||
|
<p>The <em>default initargs</em> class option, if it is present in the <code>defclass</code> form, becomes the value of the <code>:direct-default-initargs</code> keyword argument to <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-class">ensure-class</a>. Special processing of this value is done to properly capture the lexical scope of the default value forms. This is done by converting each default initarg in the class option into a <em>canonicalized default initarg</em>. The resulting list of canonicalized default initargs is the value of the <code>:direct-default-initargs</code> keyword argument to <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-class">ensure-class</a>.</p>
|
|||
|
<p>A canonicalized default initarg is a list of three elements. The first element is the name; the second is the actual form itself; and the third is a function of zero arguments which, when called, returns the result of evaluating the default value form in its proper lexical environment.</p>
|
|||
|
<p>The <em>metaclass</em> class option, if it is present in the <code>defclass</code> form, becomes the value of the <code>:metaclass</code> keyword argument to <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-class">ensure-class</a>.</p>
|
|||
|
<p>The <em>documentation</em> class option, if it is present in the <code>defclass</code> form, becomes the value of the <code>:documentation</code> keyword argument to <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-class">ensure-class</a>.</p>
|
|||
|
<p>Any other class options become the value of keyword arguments with the same name. The value of the keyword argument is the tail of the class option. An error is signaled if any class option appears more than once in the <code>defclass</code> form.</p>
|
|||
|
<p>In the call to <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-class">ensure-class</a>, every element of its arguments appears in the same left-to-right order as the corresponding element of the <code>defclass</code> form, except that the order of the properties of canonicalized slot specifications is unspecified. The values of properties in canonicalized slot specifications do follow this ordering requirement. Other ordering relationships in the keyword arguments to <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-class">ensure-class</a> are unspecified.</p>
|
|||
|
<p>The result of the call to <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-class">ensure-class</a> is returned as the result of evaluating or executing the <code>defclass</code> form.</p>
|
|||
|
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="543-the-defmethod-macro">5.4.3 The Defmethod Macro<a href="5-4-processing.html#543-the-defmethod-macro" class="hash-link" aria-label="Direct link to 5.4.3 The Defmethod Macro" title="Direct link to 5.4.3 The Defmethod Macro"></a></h2>
|
|||
|
<!-- -->
|
|||
|
<h1>The defmethod macro</h1>
|
|||
|
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="the-defmethod-macro-1">The <code>defmethod</code> macro<a href="5-4-processing.html#the-defmethod-macro-1" class="hash-link" aria-label="Direct link to the-defmethod-macro-1" title="Direct link to the-defmethod-macro-1"></a></h3>
|
|||
|
<p>The evaluation or execution of a <code>defmethod</code> form requires first that the body of the method be converted to a method function. This process is described in the next section. The result of this process is a method function and a set of additional initialization arguments to be used when creating the new method. Given these two values, the evaluation or execution of a <code>defmethod</code> form proceeds in three steps. The first step ensures the existence of a generic function with the specified name. This is done by calling the function <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-generic-function">ensure-generic-function</a>. The first argument in this call is the generic function name specified in the <code>defmethod</code> form. The second step is the creation of the new method metaobject by calling <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/make-instance">make-instance</a>. The class of the new method metaobject is determined by calling <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/generic-function-method-class">generic-function-method-class</a> on the result of the call to <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-generic-function">ensure-generic-function</a> from the first step. The initialization arguments received by the call to <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/make-instance">make-instance</a> are as follows:</p>
|
|||
|
<ul>
|
|||
|
<li>The value of the <code>qualifiers</code> initialization argument is a list of the qualifiers which appeared in the <code>defmethod</code> form. No special processing is done on these values. The order of the elements of this list is the same as in the <code>defmethod</code> form.</li>
|
|||
|
<li>The value of the <code>lambda-list</code> initialization argument is the unspecialized lambda list from the <code>defmethod</code> form.</li>
|
|||
|
<li>The value of the <code>specializers</code> initialization argument is a list of the specializers for the method. For specializers which are classes, the specializer is the class metaobject itself. In the case of <code>eql</code> specializers, it will be an <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/class-eql-specializer">eql-specializer</a> metaobject obtained by calling <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/intern-eql-specializer">intern-eql-specializer</a> on the result of evaluating the <code>eql</code> specializer form in the lexical environment of the <code>defmethod</code> form.</li>
|
|||
|
<li>The value of the <code>function</code> initialization argument is the method function.</li>
|
|||
|
<li>The value of the <code>declarations</code> initialization argument is a list of the declarations from the <code>defmethod</code> form. If there are no declarations in the macro form, this initialization argument either doesn't appear, or appears with a value of the empty list.</li>
|
|||
|
<li>The value of the <code>documentation</code> initialization argument is the documentation string from the <code>defmethod</code> form. If there is no documentation string in the macro form this initialization argument either doesn't appear, or appears with a value of false.</li>
|
|||
|
<li>Any other initialization argument produced in conjunction with the method function are also included.</li>
|
|||
|
<li>The implementation is free to include additional initialization arguments provided these are not symbols accessible in the <code>common-lisp-user</code> package, or exported by any package defined in the ANSI Common Lisp standard.</li>
|
|||
|
</ul>
|
|||
|
<p>In the third step, <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/add-method">add-method</a> is called to add the newly created method to the set of methods associated with the generic function metaobject. The result of the call to <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/add-method">add-method</a> is returned as the result of evaluating or executing the <code>defmethod</code> form. An example showing a typical <code>defmethod</code> form and a sample expansion is shown in <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/fig-defmethod-1">this figure</a>. The processing of the method body for this method is shown in <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/fig-defmethod-2">this figure</a>.</p>
|
|||
|
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="544-processing-method-bodies">5.4.4 Processing Method Bodies<a href="5-4-processing.html#544-processing-method-bodies" class="hash-link" aria-label="Direct link to 5.4.4 Processing Method Bodies" title="Direct link to 5.4.4 Processing Method Bodies"></a></h2>
|
|||
|
<!-- -->
|
|||
|
<h1>Processing method bodies</h1>
|
|||
|
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="processing-method-bodies-1">Processing method bodies<a href="5-4-processing.html#processing-method-bodies-1" class="hash-link" aria-label="Direct link to Processing method bodies" title="Direct link to Processing method bodies"></a></h3>
|
|||
|
<p>Before a method can be created, the list of forms comprising the method body must be converted to a method function. This conversion is a two step process.</p>
|
|||
|
<p><strong>Note:</strong></p>
|
|||
|
<p>The body of methods can also appear in the <code>:initial-methods</code> option of <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/the-defgeneric-macro">defgeneric</a> forms. Initial methods are not considered by any of the protocols specified in this document.</p>
|
|||
|
<p>The first step occurs during macro-expansion of the macro form. In this step, the method lambda list, declarations and body are converted to a lambda expression called a <em>method lambda</em>. This conversion is based on information associated with the generic function definition in effect at the time the macro form is expanded.</p>
|
|||
|
<p>The generic function definition is obtained by calling <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-generic-function">ensure-generic-function</a> with a first argument of the generic function name specified in the macro form. The <code>:lambda-list</code> keyword argument is not passed in this call.</p>
|
|||
|
<p>Given the generic function, production of the method lambda proceeds by calling <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/make-method-lambda">make-method-lambda</a>. The first argument in this call is the generic function obtained as described above. The second argument is the result of calling <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/class-prototype">class-prototype</a> on the result of calling <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/generic-function-method-class">generic-function-method-class</a> on the generic function. The third argument is a lambda expression formed from the method lambda list, declarations and body. The fourth argument is the macro-expansion environment of the macro form; this is the value of the <code>&environment</code> argument to the <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/the-defmethod-macro">defmethod</a> macro.</p>
|
|||
|
<p>The generic function <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/make-method-lambda">make-method-lambda</a> returns two values. The first is the method lambda itself. The second is a list of initialization arguments and values. These are included in the initialization arguments when the method is created.</p>
|
|||
|
<p>In the second step, the method lambda is converted to a function which properly captures the lexical scope of the macro form. This is done by having the method lambda appear in the macro-expansion as the argument of the <a href="http://www.lispworks.com/documentation/HyperSpec/Body/s_fn.htm" target="_blank" rel="noopener noreferrer">function</a> special form. During the subsequent evaluation of the macro-expansion, the result of the <a href="http://www.lispworks.com/documentation/HyperSpec/Body/s_fn.htm" target="_blank" rel="noopener noreferrer">function</a> special form is the methodfunction.</p>
|
|||
|
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="545-the-defgeneric-macro">5.4.5 The Defgeneric Macro<a href="5-4-processing.html#545-the-defgeneric-macro" class="hash-link" aria-label="Direct link to 5.4.5 The Defgeneric Macro" title="Direct link to 5.4.5 The Defgeneric Macro"></a></h2>
|
|||
|
<!-- -->
|
|||
|
<!-- -->
|
|||
|
<h1>The defgeneric macro</h1>
|
|||
|
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="the-defgeneric-macro-1">The <code>defgeneric</code> macro<a href="5-4-processing.html#the-defgeneric-macro-1" class="hash-link" aria-label="Direct link to the-defgeneric-macro-1" title="Direct link to the-defgeneric-macro-1"></a></h3>
|
|||
|
<p>The evaluation or execution of a <code>defgeneric</code> form results in a call to the <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-generic-function">ensure-generic-function</a> function. The arguments received by <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-generic-function">ensure-generic-function</a> are derived from the <code>defgeneric</code> form in a defined way. As with <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/the-defclass-macro">defclass</a> and <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/the-defmethod-macro">defmethod</a>, the exact macro-expansion of the <code>defgeneric</code> form is not defined, only the relationship between the arguments to the macro and the arguments received by <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-generic-function">ensure-generic-function</a>.</p>
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
<p>The <em>function-name</em> argument to <code>defgeneric</code> becomes the first argument to <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-generic-function">ensure-generic-function</a>. This is the only positional argument accepted by <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-generic-function">ensure-generic-function</a>; all other arguments are keyword arguments.</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p>The <em>lambda-list</em> argument to <code>defgeneric</code> becomes the value of the <code>:lambda-list</code> keyword argument to <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-generic-function">ensure-generic-function</a>.</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p>For each of the options <code>:argument-precedence-order</code>, <code>:documentation</code>, <code>:generic-function-class</code> and <code>:method-class</code>, the value of the option becomes the value of the keyword argument with the same name. If the option does not appear in the macro form, the keyword argument does not appear in the resulting call to <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-generic-function">ensure-generic-function</a>.</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p>For the option <code>declare</code>, the list of declarations becomes the value of the <code>:declarations</code> keyword argument. If the <code>declare</code> option does not appear in the macro form, the <code>:declarations</code> keyword argument does not appear in the call to <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-generic-function">ensure-generic-function</a>.</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p>The handling of the <code>:method-combination</code> option is not specified.</p>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
<p>The result of the call to <a href="https://lisp-docs.github.io/cl-language-reference/meta-object-protocol/ensure-generic-function">ensure-generic-function</a> is returned as the result of evaluating or executing the <code>defgeneric</code> form.</p></div><footer class="theme-doc-footer docusaurus-mt-lg"><div class="theme-doc-footer-edit-meta-row row"><div class="col"><a href="https://github.com/lisp-docs/cl-language-reference/tree/main/docs/meta-object-protocol/chap-5/5-4-processing.md" target="_blank" rel="noopener noreferrer" class="theme-edit-this-page"><svg fill="currentColor" height="20" width="20" viewBox="0 0 40 40" class="iconEdit_Z9Sw" aria-hidden="true"><g><path d="m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"></path></g></svg>Edit this page</a></div><div class="col lastUpdated_vwxv"><span class="theme-last-updated">Last updated<!-- --> by <b>daninus14</b></span></div></div></footer></article><nav class="pagination-nav docusaurus-mt-lg" aria-label="Docs pages"><a class="pagination-nav__link pagination-nav__link--prev" href="5-3-inheritance.html"><div class="pagination-nav__sublabel">Previous</div><div class="pagination-nav__label">5.3 Inheritance Structure Of Metaobject Classes</div></a><a class="pagination-nav__link pagination-nav__link--next" href="5-5-subprotocols.html"><div class="pagination-nav__sublabel">Next</div><div class="pagination-nav__label">5.5 Subprotocols</div></a></nav></div></div><div class="col col--3"><div class="tableOfContents_bqdL thin-scrollbar theme-doc-toc-desktop"><ul class="table-of-contents table-of-contents__left-border"><li><a href="5-4-processing.html#541-compile-file-processing-of-the-user-interface-macros" class="table-of-contents__link toc-highlight">5.4.1 Compile File Processing Of The User Interface Macros</a></li><li><a href="5-4-processing.html#542-the-defclass-macro" class="table-of-contents__link toc-highlight">5.4.2 The Defclass Macro</a></li><li><a href="5-4-processing.html#543-the-defmethod-macro" class="table-of-contents__link toc-highlight">5.4.3 The Defmethod Macro</a></li><li><a href="5-4-processing.html#544-processing-method-bodies" class="table-of-contents__link toc-highlight">5.4.4 Processing Method Bodies</a></li><li><a href="5-4-processing.html#545-the-defgeneric-macro" class="table-of-contents__link toc-highlight">5.4.5 The Defgeneric Macro</a></li></ul></div></div></div></div></main></div></div></div><footer class="footer footer--dark"><div class="container container-fluid"><div class="row footer__links"><div class="col footer__col"><div class="footer__title">Docs</div><ul class="footer__items clean-list"><li class="footer__item"><a href="../../../docs/tutorial.html" target="_blank" rel="noopener noreferrer" class="footer__link-item">Common Lisp Tutorial</a></li><li class="footer__item"><a href="../../index.html" target="_blank" rel="noopener noreferrer" class="footer__link-item">Common Lisp Technical Reference</a></li><li class="footer__item"><a href="../../../docs/help.html" target="_blank" rel="noopener noreferrer" class="footer__link-item">Help</a></li></ul></div><div class="col footer__col"><div class="footer__title">Community</div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://stackoverflow.com/questions/tagged/common-lisp" target="_blank" rel="noopener noreferrer" class="footer__link-item">Stack Overflow<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a href="https://discord.gg/hhk46CE" target="_blank" rel="noopener noreferrer" class="footer__link-item">Discord<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.12
|
|||
|
</body>
|
|||
|
</html>
|