User Tools

A PCRE internal error occured. This might be caused by a faulty plugin

====== Declaration DYNAMIC-EXTENT ====== ====Syntax==== * (**dynamic-extent** //<nowiki>[[</nowiki>var''*'' | (**[[CL:Special Operators:function]]** //fn//)''*''<nowiki>]]</nowiki>//) ====Arguments==== * //var// - a //[[CL:Glossary:variable]]// //[[CL:Glossary:name]]//. * //fn// - a //[[CL:Glossary:function]]// //[[CL:Glossary:name]]//. ====Valid Context==== //[[CL:Glossary:declaration]]// ====Binding Types Affected==== //[[CL:Glossary:variable]]//, //[[CL:Glossary:function]]// ====Description==== In some containing //[[CL:Glossary:form]]//, **''F''**, this declaration asserts for each ''var<sub>i</sub>'' (which need not be bound by **''F''**), and for each //[[CL:Glossary:value]]// ''v<sub>ij</sub>'' that ''var<sub>i</sub>'' takes on, and for each //[[CL:Glossary:object]]// ''x<sub>ijk</sub>'' that is an //[[CL:Glossary:otherwise inaccessible part]]// of ''v<sub>ij</sub>'' at any time when ''v<sub>ij</sub>'' becomes the value of ''var<sub>i</sub>'', that just after the execution of **''F''** terminates, ''x<sub>ijk</sub>'' is either //[[CL:Glossary:inaccessible]]// (if **''F''** established a //[[CL:Glossary:binding]]// for ''var<sub>i</sub>'') or still an //[[CL:Glossary:otherwise inaccessible part]]// of the current value of ''var<sub>i</sub>'' (if **''F''** did not establish a //[[CL:Glossary:binding]]// for ''var<sub>i</sub>''). The same relation holds for each ''fn<sub>i</sub>'', except that the //[[CL:Glossary:binding|bindings]]// are in the //[[CL:Glossary:function]]// //[[CL:Glossary:namespace]]//. The compiler is permitted to use this information in any way that is appropriate to the //[[CL:Glossary:implementation]]// and that does not conflict with the semantics of Common Lisp. **dynamic-extent** declarations can be //[[CL:Glossary:free declaration|free declarations]]// or //[[CL:Glossary:bound declaration|bound declarations]]//. The //vars// and //fns// named in a **dynamic-extent** declaration must not refer to //[[CL:Glossary:symbol macro]]// or //[[CL:Glossary:macro]]// bindings. ====Examples==== Since stack allocation of the initial value entails knowing at the //[[CL:Glossary:object]]//'s creation time that the //[[CL:Glossary:object]]// can be //[[CL:Glossary:stack-allocated]]//, it is not generally useful to make a **dynamic-extent** //[[CL:Glossary:declaration]]// for //[[CL:Glossary:variables]]// which have no lexically apparent initial value. For example, it is probably useful to write: <blockquote> ([[CL:Macros:defun]] f () ([[CL:Special Operators:let]] ((x ([[CL:Functions:list]] 1 2 3))) ([[CL:Symbols:declare]] (dynamic-extent x)) ...)) </blockquote> This would permit those compilers that wish to do so to //[[CL:Glossary:stack allocate]]// the list held by the local variable **[[CL:Functions:x]]**. It is permissible, but in practice probably not as useful, to write: <blockquote> ([[CL:Macros:defun]] g (x) ([[CL:Symbols:declare]] (dynamic-extent x)) ...) ([[CL:Macros:defun]] f () (g ([[CL:Functions:list]] 1 2 3))) </blockquote> Most compilers would probably not //[[CL:Glossary:stack allocate]]// the //[[CL:Glossary:argument]]// to ''g'' in ''f'' because it would be a modularity violation for the compiler to assume facts about ''g'' from within ''f''. Only an implementation that was willing to be responsible for recompiling ''f'' if the definition of ''g'' changed incompatibly could legitimately //[[CL:Glossary:stack allocate]]// the //[[CL:Glossary:list]]// argument to ''g'' in ''f''. Here is another example: <blockquote> ([[CL:Macros:declaim]] ([[CL:Declarations:inline]] g)) ([[CL:Macros:defun]] g (x) ([[CL:Symbols:declare]] (dynamic-extent x)) ...) ([[CL:Macros:defun]] f () (g ([[CL:Functions:list]] 1 2 3))) ([[CL:Macros:defun]] f () ([[CL:Special Operators:flet]] ((g (x) ([[CL:Symbols:declare]] (dynamic-extent x)) ...)) (g ([[CL:Functions:list]] 1 2 3)))) </blockquote> In the previous example, some compilers might determine that optimization was possible and others might not. A variant of this is the so-called "stack allocated rest list" that can be achieved (in implementations supporting the optimization) by: <blockquote> ([[CL:Macros:defun]] f (&rest x) ([[CL:Symbols:declare]] (dynamic-extent x)) ...) </blockquote> Note that although the initial value of ''x'' is not explicit, the ''f'' function is responsible for assembling the list ''x'' from the passed arguments, so the ''f'' function can be optimized by the compiler to construct a //[[CL:Glossary:stack-allocated]]// list instead of a heap-allocated list in implementations that support such. In the following example, <blockquote> ([[CL:Special Operators:let]] ((x ([[CL:Functions:list]] 'a1 'b1 'c1)) (y ([[CL:Functions:cons]] 'a2 ([[CL:Functions:cons]] 'b2 ([[CL:Functions:cons]] 'c2 nil))))) ([[CL:Symbols:declare]] (dynamic-extent x y)) ...) </blockquote> The //[[CL:Glossary:otherwise inaccessible part|otherwise inaccessible parts]]// of ''x'' are three //[[CL:Glossary:cons|conses]]//, and the //[[CL:Glossary:otherwise inaccessible part|otherwise inaccessible parts]]// of ''y'' are three other //[[CL:Glossary:cons|conses]]//. None of the symbols ''a1'', ''b1'', ''c1'', ''a2'', ''b2'', ''c2'', or **[[CL:Constant Variables:nil]]** is an //[[CL:Glossary:otherwise inaccessible part]]// of ''x'' or ''y'' because each is //[[CL:Glossary:interned]]// and hence //[[CL:Glossary:accessible]]// by the //[[CL:Glossary:package]]// (or //[[CL:Glossary:package|packages]]//) in which it is //[[CL:Glossary:interned]]//. However, if a freshly allocated //[[CL:Glossary:uninterned]]// //[[CL:Glossary:symbol]]// had been used, it would have been an //[[CL:Glossary:otherwise inaccessible part]]// of the //[[CL:Glossary:list]]// which contained it. <blockquote> ;;; In this example, the implementation is permitted to stack-allocate the list ;;; that is bound to X. ([[CL:Special Operators:let]] ((x ([[CL:Functions:list]] 1 2 3))) ([[CL:Symbols:declare]] (dynamic-extent x)) ([[CL:Functions:print]] x) :done) <o>(1 2 3)</o> <r>:DONE</r> ;;; In this example, the list to be bound to L can be stack-allocated. ([[CL:Macros:defun]] zap (x y z) ([[CL:Macros:do]] ((l ([[CL:Functions:list]] x y z) (cdr l))) (([[CL:Functions:null]] l)) ([[CL:Symbols:declare]] (dynamic-extent l)) ([[CL:Functions:prin1]] ([[CL:Functions:car]] l)))) <r>ZAP</r> (zap 1 2 3) <o>123</o> <r>NIL</r> ;;; Some implementations might open-code LIST-ALL-PACKAGES in a way that permits ;;; using stack-allocation of the list to be bound to L. ([[CL:Macros:do]] ((l ([[CL:Functions:list-all-packages]]) ([[CL:Functions:cdr]] l))) (([[CL:Functions:null]] l)) ([[CL:Symbols:declare]] (dynamic-extent l)) ([[CL:Special Operators:let]] ((name ([[CL:Functions:package-name]] ([[CL:Functions:car]] l)))) ([[CL:Macros:when]] ([[CL:Functions:search]] "COMMON-LISP" name) ([[CL:Functions:print]] name)))) <o>"COMMON-LISP" "COMMON-LISP-USER" </o> <r>NIL</r> ;;; Some implementations might have the ability to stack allocate 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. ([[CL:Macros:defun]] add (&rest x) ([[CL:Symbols:declare]] (dynamic-extent x)) ([[CL:Functions:apply]] #'[[CL:Functions:math-add|+]] x)) <r>ADD</r> (add 1 2 3) <r>6</r> ([[CL:Macros: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. :-}" ([[CL:Special Operators:let]] ((a ([[CL:Functions:make-array]] n))) ([[CL:Symbols:declare]] (dynamic-extent a)) ([[CL:Macros:dotimes]] (i n) ([[CL:Symbols:declare]] (dynamic-extent i)) ([[CL:Macros:setf]] ([[CL:Functions:aref]] a i) ([[CL:Functions:random]] ([[CL:Functions:math-one-plus|1+]] i)))) ([[CL:Functions:aref]] a m))) <r>ZAP</r> ([[CL:Functions:math-less|<]] (zap 5 3) 3) <r>//[[CL:Glossary:true]]//</r> </blockquote> The following are in error, since the value of ''x'' is used outside of its //[[CL:Glossary:extent]]//: <blockquote> ([[CL:Functions:length]] ([[CL:Functions:list]] ([[CL:Special Operators:let]] ((x ([[CL:Functions:list]] 1 2 3))) ; invalid ([[CL:Symbols:declare]] (dynamic-extent x)) x))) ([[CL:Special Operators:progn]] ([[CL:Special Operators:let]] ((x ([[CL:Functions:list]] 1 2 3))) ; invalid ([[CL:Symbols:declare]] (dynamic-extent x)) x) [[CL:Constant Variables:nil]]) </blockquote> ====See Also==== **[[CL:Symbols:declare|Symbol DECLARE]]** ====Notes==== The most common optimization is to //[[CL:Glossary:stack allocate]]// the initial value of the //[[CL:Glossary:object|objects]]// named by the //vars//. It is permissible for an implementation to simply ignore this declaration. \issue{DYNAMIC-EXTENT:NEW-DECLARATION} \issue{DYNAMIC-EXTENT-FUNCTION:EXTEND} \issue{MACRO-DECLARATIONS:MAKE-EXPLICIT}