1
0
Fork 0
cl-sites/novaspec.org/cl/m_dynamic-extent.html
2025-02-05 18:52:26 +01:00

718 lines
No EOL
16 KiB
HTML

<!DOCTYPE HTML>
<HTML LANG="en-us"
><HEAD
><TITLE
>dynamic-extent | Common Lisp Nova Spec</TITLE
><META CHARSET="US-ASCII"
><LINK REL="canonical" HREF="m_dynamic-extent.html"
><LINK REL="next" HREF="m_type.html" TYPE="text/html" TITLE="type"
><LINK REL="prev" HREF="m_ignore.html" TYPE="text/html" TITLE="ignore, ignorable"
><LINK REL="up" HREF="3_8_Evaluation_and_Compilation_Dictionary.html" TYPE="text/html" TITLE="3.8 Evaluation and Compilation Dictionary"
><LINK REL="start" HREF="index.html" TYPE="text/html" TITLE="Common Lisp Nova Spec"
><META NAME="VIEWPORT" CONTENT="width=device-width, initial-scale=1.0"
><LINK REL="STYLESHEET" HREF="dpans.css%3F3909942064.css"
><SCRIPT SRC="dpans.js%3F3909942064"
></SCRIPT
><SCRIPT SRC="apropos.js%3F3909942064"
></SCRIPT
></HEAD
><BODY
><DIV
><DIV CLASS="topnav"
><DIV CLASS="breadcrumb"
><SPAN CLASS="breadcrumb-item"
><A HREF="index.html"
>Common Lisp Nova Spec</A
></SPAN
> <SPAN CLASS="breadcrumb-item"
>&#8594; <A HREF="3_Evaluation_and_Compilation.html"
>3. Evaluation and Compilation</A
></SPAN
> <SPAN CLASS="breadcrumb-item"
>&#8594; <A HREF="3_8_Evaluation_and_Compilation_Dictionary.html"
>3.8 Evaluation and Compilation Dictionary</A
></SPAN
> <SPAN CLASS="breadcrumb-item"
>&#8594; <A HREF="m_dynamic-extent.html"
>dynamic-extent</A
></SPAN
></DIV
><DIV CLASS="apropos"
><DIV CLASS="apropos-io"
><A HREF="m_ignore.html" CLASS="prev"
>&#8592;</A
><SPAN ID="apropos-label"
>Apropos </SPAN
><INPUT ID="apropos" AUTOFOCUS="AUTOFOCUS" PLACEHOLDER="Type here to search" ONINPUT="aproposInput(this);" ONKEYUP="aproposKeyup(event);" ONCHANGE="aproposChange(this);" ONFOCUS="aproposFocus(this);" ONFOCUSOUT="aproposFocusout(this);"
><A HREF="m_type.html" CLASS="next"
>&#8594;</A
></DIV
><DIV ID="apropos-res"
></DIV
></DIV
></DIV
><DIV CLASS="matter"
><DIV CLASS="com"
><DIV CLASS="begincom"
><HR
><TABLE WIDTH="100%" CELLSPACING="0" CELLPADDING="0"
><TR
><TD ALIGN="LEFT" VALIGN="BASELINE" WIDTH="100%" CLASS="name"
><SPAN CLASS="idx" DATA-KIND="idxref" DATA-TERM="dynamic-extent"
></SPAN
><B
>dynamic-extent</B
></TD
><TD ALIGN="RIGHT" VALIGN="BASELINE" WIDTH="0" NOWRAP="NOWRAP" CLASS="ftype"
><I
>Declaration</I
></TD
></TR
></TABLE
><HR
></DIV
><UL CLASS="subtoc"
></UL
><DL
><DT
><B
>Syntax</B
></DT
><DD
><P CLASS="j"
><CODE CLASS="f"
>(dynamic-extent <SPAN CLASS="cmr"
>&#10214;&#8201;</SPAN
><SPAN CLASS="cmsy"
>{</SPAN
><VAR CLASS="param"
>var</VAR
><SPAN CLASS="cmsy"
>}</SPAN
><SPAN CLASS="cmr"
>*</SPAN
> | <SPAN CLASS="cmr"
>(</SPAN
><SPAN CLASS="misc"
><B
>function</B
></SPAN
> <VAR CLASS="param"
>fn</VAR
><SPAN CLASS="cmr"
>)*</SPAN
>&#8201;<SPAN CLASS="cmr"
>&#8201;&#10215;</SPAN
>)</CODE
></P
></DD
><DT
><B
>Arguments</B
></DT
><DD
><P CLASS="j"
><VAR CLASS="param"
>var</VAR
> &#8212; a <A HREF="26_1_Glossary.html#variable"
><EM CLASS="term"
>variable</EM
></A
> <A HREF="26_1_Glossary.html#name"
><EM CLASS="term"
>name</EM
></A
>. </P
><P CLASS="j"
><VAR CLASS="param"
>fn</VAR
> &#8212; a <A HREF="26_1_Glossary.html#function"
><EM CLASS="term"
>function</EM
></A
> <A HREF="26_1_Glossary.html#name"
><EM CLASS="term"
>name</EM
></A
>.</P
></DD
><DT
><B
>Valid Context</B
></DT
><DD
><P CLASS="j"
><A HREF="26_1_Glossary.html#declaration"
><EM CLASS="term"
>declaration</EM
></A
></P
></DD
><DT
><B
>Binding Types Affected</B
></DT
><DD
><P CLASS="j"
><A HREF="26_1_Glossary.html#variable"
><EM CLASS="term"
>variable</EM
></A
>, <A HREF="26_1_Glossary.html#function"
><EM CLASS="term"
>function</EM
></A
></P
></DD
><DT
><B
>Description</B
></DT
><DD
><P CLASS="j"
>In some containing <A HREF="26_1_Glossary.html#form"
><EM CLASS="term"
>form</EM
></A
>, <VAR CLASS="param"
>F</VAR
>, this declaration asserts for each <VAR CLASS="param"
>var<SUB CLASS="sub"
><I
>i</I
></SUB
></VAR
> (which need not be bound by <VAR CLASS="param"
>F</VAR
>), and for each <A HREF="26_1_Glossary.html#value"
><EM CLASS="term"
>value</EM
></A
> <VAR CLASS="param"
>v<SUB CLASS="sub"
><I
>ij</I
></SUB
></VAR
> that <VAR CLASS="param"
>var<SUB CLASS="sub"
><I
>i</I
></SUB
></VAR
> takes on, and for each <A HREF="26_1_Glossary.html#object"
><EM CLASS="term"
>object</EM
></A
> <VAR CLASS="param"
>x<SUB CLASS="sub"
><I
>ijk</I
></SUB
></VAR
> that is an <A HREF="26_1_Glossary.html#otherwise_inaccessible_part"
><EM CLASS="term"
>otherwise inaccessible part</EM
></A
> of <VAR CLASS="param"
>v<SUB CLASS="sub"
><I
>ij</I
></SUB
></VAR
> at any time when <VAR CLASS="param"
>v<SUB CLASS="sub"
><I
>ij</I
></SUB
></VAR
> becomes the value of <VAR CLASS="param"
>var<SUB CLASS="sub"
><I
>i</I
></SUB
></VAR
>, that just after the execution of <VAR CLASS="param"
>F</VAR
> terminates, <VAR CLASS="param"
>x<SUB CLASS="sub"
><I
>ijk</I
></SUB
></VAR
> is either <A HREF="26_1_Glossary.html#inaccessible"
><EM CLASS="term"
>inaccessible</EM
></A
> (if <VAR CLASS="param"
>F</VAR
> established a <A HREF="26_1_Glossary.html#binding"
><EM CLASS="term"
>binding</EM
></A
> for <VAR CLASS="param"
>var<SUB CLASS="sub"
><I
>i</I
></SUB
></VAR
>) or still an <A HREF="26_1_Glossary.html#otherwise_inaccessible_part"
><EM CLASS="term"
>otherwise inaccessible part</EM
></A
> of the current value of <VAR CLASS="param"
>var<SUB CLASS="sub"
><I
>i</I
></SUB
></VAR
> (if <VAR CLASS="param"
>F</VAR
> did not establish a <A HREF="26_1_Glossary.html#binding"
><EM CLASS="term"
>binding</EM
></A
> for <VAR CLASS="param"
>var<SUB CLASS="sub"
><I
>i</I
></SUB
></VAR
>). The same relation holds for each <VAR CLASS="param"
>fn<SUB CLASS="sub"
><I
>i</I
></SUB
></VAR
>, except that the <A HREF="26_1_Glossary.html#binding"
><EM CLASS="term"
>bindings</EM
></A
> are in the <A HREF="26_1_Glossary.html#function"
><EM CLASS="term"
>function</EM
></A
> <A HREF="26_1_Glossary.html#namespace"
><EM CLASS="term"
>namespace</EM
></A
>. </P
><P CLASS="j"
>The compiler is permitted to use this information in any way that is appropriate to the <A HREF="26_1_Glossary.html#implementation"
><EM CLASS="term"
>implementation</EM
></A
> and that does not conflict with the semantics of Common Lisp. </P
><P CLASS="j"
><A HREF="m_dynamic-extent.html" CLASS="declref"
><B
>dynamic-extent</B
></A
> declarations can be <A HREF="26_1_Glossary.html#free_declaration"
><EM CLASS="term"
>free declarations</EM
></A
> or <A HREF="26_1_Glossary.html#bound_declaration"
><EM CLASS="term"
>bound declarations</EM
></A
>. </P
><P CLASS="j"
>The <VAR CLASS="param"
>vars</VAR
> and <VAR CLASS="param"
>fns</VAR
> named in a <A HREF="m_dynamic-extent.html" CLASS="declref"
><B
>dynamic-extent</B
></A
> declaration must not refer to <A HREF="26_1_Glossary.html#symbol_macro"
><EM CLASS="term"
>symbol macro</EM
></A
> or <A HREF="26_1_Glossary.html#macro"
><EM CLASS="term"
>macro</EM
></A
> bindings.</P
></DD
><DT
><B
>Examples</B
></DT
><DD
><P CLASS="j"
>Since stack allocation of the initial value entails knowing at the <A HREF="26_1_Glossary.html#object"
><EM CLASS="term"
>object</EM
></A
>&#8217;s creation time that the <A HREF="26_1_Glossary.html#object"
><EM CLASS="term"
>object</EM
></A
> can be <A HREF="26_1_Glossary.html#stack-allocated"
><EM CLASS="term"
>stack-allocated</EM
></A
>, it is not generally useful to make a <A HREF="m_dynamic-extent.html" CLASS="declref"
><B
>dynamic-extent</B
></A
> <A HREF="26_1_Glossary.html#declaration"
><EM CLASS="term"
>declaration</EM
></A
> for <A HREF="26_1_Glossary.html#variable"
><EM CLASS="term"
>variables</EM
></A
> which have no lexically apparent initial value. For example, it is probably useful to write:</P
><PRE CLASS="screen"
>(defun f ()
(let ((x (list 1 2 3)))
(declare (dynamic-extent x))
...))</PRE
><P CLASS="j"
>This would permit those compilers that wish to do so to <A HREF="26_1_Glossary.html#stack_allocate"
><EM CLASS="term"
>stack allocate</EM
></A
> the list held by the local variable <SPAN CLASS="cmtt"
>x</SPAN
>. It is permissible, but in practice probably not as useful, to write:</P
><PRE CLASS="screen"
>(defun g (x) (declare (dynamic-extent x)) ...)
(defun f () (g (list 1 2 3)))</PRE
><P CLASS="j"
>Most compilers would probably not <A HREF="26_1_Glossary.html#stack_allocate"
><EM CLASS="term"
>stack allocate</EM
></A
> the <A HREF="26_1_Glossary.html#argument"
><EM CLASS="term"
>argument</EM
></A
> to <SPAN CLASS="cmtt"
>g</SPAN
> in <SPAN CLASS="cmtt"
>f</SPAN
> because it would be a modularity violation for the compiler to assume facts about <SPAN CLASS="cmtt"
>g</SPAN
> from within <SPAN CLASS="cmtt"
>f</SPAN
>. Only an implementation that was willing to be responsible for recompiling <SPAN CLASS="cmtt"
>f</SPAN
> if the definition of <SPAN CLASS="cmtt"
>g</SPAN
> changed incompatibly could legitimately <A HREF="26_1_Glossary.html#stack_allocate"
><EM CLASS="term"
>stack allocate</EM
></A
> the <A HREF="26_1_Glossary.html#list"
><EM CLASS="term"
>list</EM
></A
> argument to <SPAN CLASS="cmtt"
>g</SPAN
> in <SPAN CLASS="cmtt"
>f</SPAN
>. </P
><P CLASS="j"
>Here is another example:</P
><PRE CLASS="screen"
>(declaim (inline g))
(defun g (x) (declare (dynamic-extent x)) ...)
(defun f () (g (list 1 2 3)))
(defun f ()
(flet ((g (x) (declare (dynamic-extent x)) ...))
(g (list 1 2 3))))</PRE
><P CLASS="j"
>In the previous example, some compilers might determine that optimization was possible and others might not. </P
><P CLASS="j"
>A variant of this is the so-called &#8220;stack allocated rest list&#8221; that can be achieved (in implementations supporting the optimization) by:</P
><PRE CLASS="screen"
>(defun f (&amp;rest x)
(declare (dynamic-extent x))
...)</PRE
><P CLASS="j"
>Note that although the initial value of <SPAN CLASS="cmtt"
>x</SPAN
> is not explicit, the <SPAN CLASS="cmtt"
>f</SPAN
> function is responsible for assembling the list <SPAN CLASS="cmtt"
>x</SPAN
> from the passed arguments, so the <SPAN CLASS="cmtt"
>f</SPAN
> function can be optimized by the compiler to construct a <A HREF="26_1_Glossary.html#stack-allocated"
><EM CLASS="term"
>stack-allocated</EM
></A
> list instead of a heap-allocated list in implementations that support such. </P
><P CLASS="j"
>In the following example,</P
><PRE CLASS="screen"
>(let ((x (list 'a1 'b1 'c1))
(y (cons 'a2 (cons 'b2 (cons 'c2 nil)))))
(declare (dynamic-extent x y))
...)</PRE
><P CLASS="j"
>The <A HREF="26_1_Glossary.html#otherwise_inaccessible_part"
><EM CLASS="term"
>otherwise inaccessible parts</EM
></A
> of <SPAN CLASS="cmtt"
>x</SPAN
> are three <A HREF="26_1_Glossary.html#cons"
><EM CLASS="term"
>conses</EM
></A
>, and the <A HREF="26_1_Glossary.html#otherwise_inaccessible_part"
><EM CLASS="term"
>otherwise inaccessible parts</EM
></A
> of <SPAN CLASS="cmtt"
>y</SPAN
> are three other <A HREF="26_1_Glossary.html#cons"
><EM CLASS="term"
>conses</EM
></A
>. None of the symbols <SPAN CLASS="cmtt"
>a1</SPAN
>, <SPAN CLASS="cmtt"
>b1</SPAN
>, <SPAN CLASS="cmtt"
>c1</SPAN
>, <SPAN CLASS="cmtt"
>a2</SPAN
>, <SPAN CLASS="cmtt"
>b2</SPAN
>, <SPAN CLASS="cmtt"
>c2</SPAN
>, or <SPAN CLASS="misc"
><B
>nil</B
></SPAN
> is an <A HREF="26_1_Glossary.html#otherwise_inaccessible_part"
><EM CLASS="term"
>otherwise inaccessible part</EM
></A
> of <SPAN CLASS="cmtt"
>x</SPAN
> or <SPAN CLASS="cmtt"
>y</SPAN
> because each is <A HREF="26_1_Glossary.html#interned"
><EM CLASS="term"
>interned</EM
></A
> and hence <A HREF="26_1_Glossary.html#accessible"
><EM CLASS="term"
>accessible</EM
></A
> by the <A HREF="26_1_Glossary.html#package"
><EM CLASS="term"
>package</EM
></A
> (or <A HREF="26_1_Glossary.html#package"
><EM CLASS="term"
>packages</EM
></A
>) in which it is <A HREF="26_1_Glossary.html#interned"
><EM CLASS="term"
>interned</EM
></A
>. However, if a freshly allocated <A HREF="26_1_Glossary.html#uninterned"
><EM CLASS="term"
>uninterned</EM
></A
> <A HREF="26_1_Glossary.html#symbol"
><EM CLASS="term"
>symbol</EM
></A
> had been used, it would have been an <A HREF="26_1_Glossary.html#otherwise_inaccessible_part"
><EM CLASS="term"
>otherwise inaccessible part</EM
></A
> of the <A HREF="26_1_Glossary.html#list"
><EM CLASS="term"
>list</EM
></A
> which contained it.</P
><PRE CLASS="screen"
>;; In this example, the implementation is permitted to <A HREF="26_1_Glossary.html#stack_allocate"
><EM CLASS="term"
>stack allocate</EM
></A
>
;; the list that is bound to X.
(let ((x (list 1 2 3)))
(declare (dynamic-extent x))
(print x)
:done)
<SPAN CLASS="cmr"
>&#8883;</SPAN
> (1 2 3)
<SPAN CLASS="cmsy"
><SPAN CLASS="arrow"
>&#8594;</SPAN
></SPAN
> :DONE
;; In this example, the list to be bound to L can be <A HREF="26_1_Glossary.html#stack-allocated"
><EM CLASS="term"
>stack-allocated</EM
></A
>.
(defun zap (x y z)
(do ((l (list x y z) (cdr l)))
((null l))
(declare (dynamic-extent l))
(prin1 (car l)))) <SPAN CLASS="cmsy"
><SPAN CLASS="arrow"
>&#8594;</SPAN
></SPAN
> ZAP
(zap 1 2 3)
<SPAN CLASS="cmr"
>&#8883;</SPAN
> 123
<SPAN CLASS="cmsy"
><SPAN CLASS="arrow"
>&#8594;</SPAN
></SPAN
> NIL
;; Some implementations might open-code LIST-ALL-PACKAGES in a way
;; that permits using <EM CLASS="term"
>stack allocation</EM
> of the list to be bound to L.
(do ((l (list-all-packages) (cdr l)))
((null l))
(declare (dynamic-extent l))
(let ((name (package-name (car l))))
(when (string-search "COMMON-LISP" name) (print name))))
<SPAN CLASS="cmr"
>&#8883;</SPAN
> "COMMON-LISP"
<SPAN CLASS="cmr"
>&#8883;</SPAN
> "COMMON-LISP-USER"
<SPAN CLASS="cmsy"
><SPAN CLASS="arrow"
>&#8594;</SPAN
></SPAN
> NIL
;; Some implementations might have the ability to <A HREF="26_1_Glossary.html#stack_allocate"
><EM CLASS="term"
>stack allocate</EM
></A
>
;; rest lists. A declaration such as the following should be a cue
;; to such implementations that stack-allocation of the rest list
;; would be desirable.
(defun add (&amp;rest x)
(declare (dynamic-extent x))
(apply #'+ x)) <SPAN CLASS="cmsy"
><SPAN CLASS="arrow"
>&#8594;</SPAN
></SPAN
> ADD
(add 1 2 3) <SPAN CLASS="cmsy"
><SPAN CLASS="arrow"
>&#8594;</SPAN
></SPAN
> 6
(defun zap (n m)
;; Computes (RANDOM (+ M 1)) at relative speed of roughly O(N).
;; It may be slow, but with a good compiler at least it
;; doesn't waste much heap storage. :-}
(let ((a (make-array n)))
(declare (dynamic-extent a))
(dotimes (i n)
(declare (dynamic-extent i))
(setf (aref a i) (random (+ i 1))))
(aref a m))) <SPAN CLASS="cmsy"
><SPAN CLASS="arrow"
>&#8594;</SPAN
></SPAN
> ZAP
(&lt; (zap 5 3) 3) <SPAN CLASS="cmsy"
><SPAN CLASS="arrow"
>&#8594;</SPAN
></SPAN
> <A HREF="26_1_Glossary.html#true"
><EM CLASS="term"
>true</EM
></A
></PRE
><P CLASS="j"
>The following are in error, since the value of <SPAN CLASS="cmtt"
>x</SPAN
> is used outside of its <A HREF="26_1_Glossary.html#extent"
><EM CLASS="term"
>extent</EM
></A
>:</P
><PRE CLASS="screen"
>(length (list (let ((x (list 1 2 3))) ; Invalid
(declare (dynamic-extent x))
x)))
(progn (let ((x (list 1 2 3))) ; Invalid
(declare (dynamic-extent x))
x)
nil)</PRE
></DD
><DT
><B
>See Also</B
></DT
><DD
><P CLASS="j"
><A HREF="m_declare.html" CLASS="misc"
><B
>declare</B
></A
></P
></DD
><DT
><B
>Notes</B
></DT
><DD
><P CLASS="j"
>The most common optimization is to <A HREF="26_1_Glossary.html#stack_allocate"
><EM CLASS="term"
>stack allocate</EM
></A
> the initial value of the <A HREF="26_1_Glossary.html#object"
><EM CLASS="term"
>objects</EM
></A
> named by the <VAR CLASS="param"
>vars</VAR
>. </P
><P CLASS="j"
>It is permissible for an implementation to simply ignore this declaration.</P
></DD
></DL
></DIV
></DIV
><DIV CLASS="footer"
><DIV CLASS="btmnav"
><A HREF="m_ignore.html" CLASS="prev"
>&#8592;</A
><A HREF="m_type.html" CLASS="next"
>&#8594;</A
></DIV
><DIV CLASS="trail"
>Conversion to HTML copyright 2023 by Gilbert Baumann</DIV
></DIV
></DIV
><SCRIPT
>domReady();</SCRIPT
></BODY
></HTML
>