User Tools

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

====== Special Operator FLET, LABELS, MACROLET ====== ====Syntax==== * **flet** ((//function-name lambda-list <nowiki>[[</nowiki>local-declaration''*'' | local-documentation<nowiki>]]</nowiki> local-form''*'')''*'') declaration''*'' form''*''// → //result''*''// * **labels** ((//function-name lambda-list <nowiki>[[</nowiki>local-declaration''*'' | local-documentation<nowiki>]]</nowiki> local-form''*'')''*'') declaration''*'' form''*''// → //result''*''// * **macrolet** ((//name lambda-list <nowiki>[[</nowiki>local-declaration''*'' | local-documentation<nowiki>]]</nowiki> local-form''*'')''*'') declaration''*'' form''*''// → //result''*''// ====Arguments and Values==== * //function-name// - a //[[CL:Glossary:function name]]//. * //name// - a //[[CL:Glossary:symbol]]//. * //lambda-list// - a //[[CL:Glossary:lambda list]]//; for **flet** and **labels**, it is an //[[CL:Glossary:ordinary lambda list]]//; for **macrolet**, it is a //[[CL:Glossary:macro lambda list]]//. * //local-declaration// - a **[[CL:Special Operators:declare]]** //[[CL:Glossary:expression]]//; not evaluated. * //declaration// - a **[[CL:Special Operators:declare]]** //[[CL:Glossary:expression]]//; not evaluated. * //local-documentation// - a //[[CL:Glossary:string]]//; not evaluated. * //local-forms//, //forms// - an //[[CL:Glossary:implicit progn]]//. * //results// - the //[[CL:Glossary:value|values]]// of the //forms//. ====Description==== **flet**, **labels**, and **macrolet** define local //[[CL:Glossary:function|functions]]// and //[[CL:Glossary:macro|macros]]//, and execute //forms// using the local definitions. //Forms// are executed in order of occurrence. The body forms (but not the //[[CL:Glossary:lambda list]]//) of each //[[CL:Glossary:function]]// created by **flet** and **labels** and each //[[CL:Glossary:macro]]// created by **macrolet** are enclosed in an //[[CL:Glossary:implicit block]]// whose name is the //[[CL:Glossary:function block name]]// of the //function-name// or //name//, as appropriate. The scope of the //declarations// between the list of local function/macro definitions and the body //forms// in **flet** and **labels** does not include the bodies of the locally defined //[[CL:Glossary:function|functions]]//, except that for **labels**, any **[[CL:Declarations:inline]]**, **[[CL:Declarations:notinline]]**, or **[[CL:Declarations:ftype]]** declarations that refer to the locally defined functions do apply to the local function bodies. That is, their //[[CL:Glossary:scope]]// is the same as the function name that they affect. The scope of these //declarations// does not include the bodies of the macro expander functions defined by **macrolet**. ===flet=== **flet** defines locally named //[[CL:Glossary:function|functions]]// and executes a series of //forms// with these definition //[[CL:Glossary:binding|bindings]]//. Any number of such local //[[CL:Glossary:function|functions]]// can be defined. The //[[CL:Glossary:scope]]// of the name //[[CL:Glossary:binding]]// encompasses only the body. Within the body of **flet**, //function-names// matching those defined by **flet** refer to the locally defined //[[CL:Glossary:function|functions]]// rather than to the global function definitions of the same name. Also, within the scope of **flet**, global //[[CL:Glossary:setf expander]]// definitions of the //function-name// defined by **flet** do not apply. Note that this applies to ''([[CL:Macros:defsetf]] f ...)'', not ''([[Cl:Macros:defmethod]] ([[CL:Macros:setf]] ''f'') ...)''. The names of //[[CL:Glossary:function|functions]]// defined by **flet** are in the //[[CL:Glossary:lexical environment]]//; they retain their local definitions only within the body of **flet**. The function definition bindings are visible only in the body of **flet**, not the definitions themselves. Within the function definitions, local function names that match those being defined refer to //[[CL:Glossary:function|functions]]// or //[[CL:Glossary:macro|macros]]// defined outside the **flet**. **flet** can locally //[[CL:Glossary:shadow]]// a global function name, and the new definition can refer to the global definition. Any //local-documentation// is attached to the corresponding local //function// (if one is actually created) as a //[[CL:Glossary:documentation string]]//. ===labels=== **labels** is equivalent to **flet** except that the scope of the defined function names for **labels** encompasses the function definitions themselves as well as the body. ===macrolet=== **macrolet** establishes local //[[CL:Glossary:macro]]// definitions, using the same format used by **[[CL:Macros:defmacro]]**. Within the body of **macrolet**, global //[[CL:Glossary:setf expander]]// definitions of the //names// defined by the **macrolet** do not apply; rather, **[[CL:Macros:setf]]** expands the //[[CL:Glossary:macro form]]// and recursively process the resulting //[[CL:Glossary:form]]//. The macro-expansion functions defined by **macrolet** are defined in the //[[CL:Glossary:lexical environment]]// in which the **macrolet** form appears. Declarations and **macrolet** and **[[CL:Special Operators:symbol-macrolet]]** definitions affect the local macro definitions in a **macrolet**, but the consequences are undefined if the local macro definitions reference any local //[[CL:Glossary:variable]]// or //[[CL:Glossary:function]]// //[[CL:Glossary:binding|bindings]]// that are visible in that //[[CL:Glossary:lexical environment]]//. Any //local-documentation// is attached to the corresponding local //macro function// as a //[[CL:Glossary:documentation string]]//. ====Examples==== <blockquote> ([[CL:Macros:defun]] foo (x flag) (macrolet ((fudge (z) ; The parameters x and flag are not accessible ; at this point; a reference to flag would be to ; the global variable of that name. ([[CL:Special Operators:if]] flag ([[CL:Functions:math-multiply|*]] ,z ,z) ,z))) ; The parameters x and flag are accessible here. ([[CL:Functions:math-add|+]] x (fudge x) (fudge ([[CL:Functions:math-add|+]] x 1))))) </blockquote> After macroexpansion, this is equivalent to: <blockquote> ([[CL:Macros:defun]] foo (x flag) ([[CL:Functions:math-add|+]] x ([[CL:Special Operators:if]] flag ([[CL:Functions:math-multiply|*]] x x) x) ([[CL:Special Operators:if]] flag ([[CL:Functions:math-multiply|*]] ([[CL:Functions:math-add|+]] x 1) ([[CL:Functions:math-add|+]] x 1)) ([[CL:Functions:math-add|+]] x 1)))) </blockquote> The occurrences of ''x'' and ''flag'' legitimately refer to the parameters of the function ''foo'' because those parameters are visible at the site of the macro call which produced the expansion. <blockquote> (flet ((flet1 (n) ([[CL:Functions:math-add|+]] n n))) (flet ((flet1 (n) ([[CL:Functions:math-add|+]] 2 (flet1 n)))) (flet1 2))) <r>6</r> ([[CL:Macros:defun]] dummy-function () 'top-level) <r>DUMMY-FUNCTION</r> ([[CL:Functions:funcall]] #'dummy-function) <r>TOP-LEVEL</r> (flet ((dummy-function () 'shadow)) ([[CL:Functions:funcall]] #'dummy-function)) → SHADOW ([[CL:Functions:eq]] ([[CL:Functions:funcall]] #'dummy-function) ([[CL:Functions:funcall]] 'dummy-function)) <r>//[[CL:Glossary:true]]// </r> (flet ((dummy-function () 'shadow)) ([[CL:Functions:eq]] ([[CL:Functions:funcall]] #'dummy-function) ([[CL:Functions:funcall]] 'dummy-function))) <r>//[[CL:Glossary:false]]//</r> ([[CL:Macros:defun]] recursive-times (k n) (labels ((temp (n) ([[CL:Special Operators:if]] ([[CL:Functions:zerop]] n) 0 ([[CL:Functions:math-add|+]] k (temp ([[CL:Functions:math-one-minus|1-]] n)))))) (temp n))) <r>RECURSIVE-TIMES </r> (recursive-times 2 3) <r>6</r> ([[CL:Macros:defmacro]] mlets (x &environment env) ([[CL:Special Operators:let]] ((form `(babbit ,x))) ([[CL:Functions:macroexpand]] form env))) <r>MLETS</r> (macrolet ((babbit (z) `(+ ,z ,z))) (mlets 5)) <r>10</r> (flet ((safesqrt (x) ([[CL:Functions:sqrt]] ([[CL:Functions:abs]] x)))) (safesqrt ([[CL:Functions:apply]] #'[[CL:Functions:math-add|+]] ([[CL:Functions:map]] '[[CL:Types:list]] #'safesqrt '(1 2 3 4 5 6))))) <r>3.291173</r> </blockquote> In the example above, the ''safesqrt'' function is used in two places. <blockquote> ([[CL:Macros:defun]] integer-power (n k) ([[CL:Symbols:declare]] ([[CL:Types:integer]] n)) ([[CL:Symbols:declare]] ([[CL:Declarations:type]] ([[CL:Types:integer]] 0 [[CL:Types:wildcard|*]]) k)) (labels ((expt0 (x k a) ([[CL:Symbols:declare]] ([[CL:Types:integer]] x a) ([[CL:Declarations:type]] ([[CL:Types:integer]] 0 [[CL:Types:wildcard|*]]) k)) ([[CL:Macros:cond]] (([[CL:Functions:zerop]] k) a) (([[CL:Functions:evenp]] k) (expt1 ([[CL:Functions:math-multiply|*]] x x) ([[CL:Functions:floor]] k 2) a)) ([[CL:Constant Variables:t]] (expt0 (* x x) ([[CL:Functions:floor]] k 2) (* x a))))) (expt1 (x k a) ([[CL:Symbols:declare]] ([[CL:Types:integer]] x a) ([[CL:Declarations:type]] ([[CL:Types:integer]] 0 [[CL:Types:wildcard|*]]) k)) ([[CL:Macros:cond]] (([[CL:Functions:evenp]] k) (expt1 ([[CL:Functions:math-multiply|*]] x x) ([[CL:Functions:floor]] k 2) a)) ([[CL:Constant Variables:t]] (expt0 ([[CL:Functions:math-multiply|*]] x x) ([[CL:Functions:floor]] k 2) ([[CL:Functions:math-multiply|*]] x a)))))) (expt0 n k 1))) <r>INTEGER-POWER</r> ([[CL:Macros:defun]] example (y l) (flet ((attach (x) ([[CL:Macros:setf]] l ([[CL:Functions:append]] l ([[CL:Functions:list]] x))))) ([[CL:Symbols:declare]] ([[CL:Declarations:inline]] attach)) ([[CL:Macros:dolist]] (x y) ([[CL:Macros:unless]] ([[CL:Functions:null]] ([[CL:Functions:cdr]] x)) (attach x))) l)) <r>EXAMPLE</r> (example '((a apple apricot) (b banana) (c cherry) (d) (e)) '((1) (2) (3) (4 2) (5) (6 3 2))) <r>((1) (2) (3) (4 2) (5) (6 3 2) (A APPLE APRICOT) (B BANANA) (C CHERRY))</r> </blockquote> ====Affected By==== None. ====Exceptional Situations==== None. ====See Also==== * **[[CL:Special Operators:declare|Special Operator DECLARE]]** * **[[CL:Macros:defmacro|Macro DEFMACRO]]** * **[[CL:Macros:defun|Macro DEFUN]]** * **[[CL:Functions:documentation|Generic Function DOCUMENTATION]]** * **[[CL:Special Operators:let|Special Operator LET]]** * {\secref\Evaluation} * {\secref\DocVsDecls} ====Notes==== It is not possible to define recursive //[[CL:Glossary:function|functions]]// with **flet**. **labels** can be used to define mutually recursive //[[CL:Glossary:function|functions]]//. If a **macrolet** //[[CL:Glossary:form]]// is a //[[CL:Glossary:top level form]]//, the body //forms// are also processed as //[[CL:Glossary:top level forms]]//. see section {\secref\FileCompilation}. \issue{DECLARATION-SCOPE:NO-HOISTING} \issue{SETF-METHOD-VS-SETF-METHOD:RENAME-OLD-TERMS} \issue{GET-SETF-METHOD-ENVIRONMENT:ADD-ARG} \issue{SETF-METHOD-VS-SETF-METHOD:RENAME-OLD-TERMS} \issue{GET-SETF-METHOD-ENVIRONMENT:ADD-ARG} \issue{SETF-METHOD-VS-SETF-METHOD:RENAME-OLD-TERMS} \issue{GET-SETF-METHOD-ENVIRONMENT:ADD-ARG} \issue{DEFINING-MACROS-NON-TOP-LEVEL:ALLOW} \issue{LISP-SYMBOL-REDEFINITION:MAR89-X3J13} \issue{FLET-DECLARATIONS} \issue{DECLS-AND-DOC} \issue{FLET-DECLARATIONS:ALLOW} \issue{FUNCTION-NAME:LARGE} \issue{FLET-IMPLICIT-BLOCK:YES} \issue{FUNCTION-NAME:LARGE} \issue{DEFMACRO-BLOCK-SCOPE:EXCLUDES-BINDINGS} \issue{FLET-DECLARATIONS}