User Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

cl:special_operators:let [2017/05/01 21:00] (current)
Line 1: Line 1:
 +====== Special Operator LET, LET* ======
 +
 +====Syntax====
 +  * **let** //({var | (var [init-form])}''​*''​) declaration''​*''​ form''​*''//​ → //​result''​*''//​
 +  * **let<​nowiki>​*</​nowiki>​** //({var | (var [init-form])}''​*''​) declaration''​*''​ form''​*''//​ → //​result''​*''//​
 +
 +====Arguments and Values====
 +  * //var// - a //​[[CL:​Glossary:​symbol]]//​.
 +  * //​init-form//​ - a //​[[CL:​Glossary:​form]]//​.
 +  * //​declaration//​ - a **[[CL:​Special Operators:​declare]]** //​[[CL:​Glossary:​expression]]//;​ not evaluated.
 +  * //form// - a //​[[CL:​Glossary:​form]]//​.
 +  * //results// - the //​[[CL:​Glossary:​value|values]]//​ returned by the //​[[CL:​Glossary:​form|forms]]//​.
 +
 +====Description====
 +**let** and **let<​nowiki>​*</​nowiki>​** create new variable //​[[CL:​Glossary:​binding|bindings]]//​ and execute a series of //forms// that use these //​[[CL:​Glossary:​binding|bindings]]//​. **let** performs the //​[[CL:​Glossary:​binding|bindings]]//​ in parallel and **let<​nowiki>​*</​nowiki>​** does them sequentially.
 +
 +The form:
 +
 +<​blockquote>​
 +(let ((//var1// //​init-form-1//​) ​
 +      (//var2// //​init-form-2//​) ​
 +      ... 
 +      (//varm// //​init-form-m//​)) ​
 +  //​declaration1//​
 +  //​declaration2// ​
 +  ... 
 +  //​declarationp// ​
 +  //​form1// ​
 +  //​form2// ​
 +  ... 
 +  //formn//)
 +</​blockquote> ​
 +
 +first evaluates the expressions //​init-form-1//,​ //​init-form-2//,​ and so on, in that order, saving the resulting values. Then all of the variables //​var<​sub>​j</​sub>//​ are bound to the corresponding values; each //​[[CL:​Glossary:​binding]]//​ is lexical unless there is a **[[CL:​Declarations:​special]]** declaration to the contrary. The expressions //​form<​sub>​k</​sub>//​ are then evaluated in order; the values of all but the last are discarded (that is, the body of a **let** is an //​[[CL:​Glossary:​implicit progn]]//).
 +
 +**let<​nowiki>​*</​nowiki>​** is similar to **let**, but the //​[[CL:​Glossary:​binding|bindings]]//​ of variables are performed sequentially rather than in parallel. The expression for the //​init-form//​ of a //var// can refer to //vars// previously bound in the **let<​nowiki>​*</​nowiki>​**.
 +
 +The form:
 +
 +<​blockquote>​
 +(let* ((//var1// //​init-form-1//​) ​
 +       ​(//​var2//​ //​init-form-2//​) ​
 +       ​... ​
 +       ​(//​varm//​ //​init-form-m//​))
 +  //​declaration1// ​
 +  //​declaration2// ​
 +  ... 
 +  //​declarationp//​
 +  //​form1// ​
 +  //​form2// ​
 +  ... 
 +  //​formn//​) ​
 +</​blockquote> ​
 +
 +first evaluates the expression //​init-form-1//,​ then binds the variable //var1// to that value; then it evaluates //​init-form-2//​ and binds //var2//, and so on. The expressions //​var<​sub>​j</​sub>//​ are then evaluated in order; the values of all but the last are discarded (that is, the body of **let<​nowiki>​*</​nowiki>​** is an implicit **[[CL:​Special Operators:​progn]]**).
 +
 +For both **let** and **let<​nowiki>​*</​nowiki>​**,​ if there is not an //​init-form//​ associated with a //var//, //var// is initialized to **[[CL:​Constant Variables:​nil]]**.
 +
 +The special form **let** has the property that the //​[[CL:​Glossary:​scope]]//​ of the name binding does not include any initial value form. For **let<​nowiki>​*</​nowiki>​**,​ a variable'​s //​[[CL:​Glossary:​scope]]//​ also includes the remaining initial value forms for subsequent variable bindings.
 +
 +====Examples====
 +<​blockquote>​
 +([[CL:​Macros:​defparameter]] *a* 'top) <​r>​*A* </r>
 +([[CL:​Macros:​defun]] dummy-function () *a*) <​r>​DUMMY-FUNCTION </r>
 +(let ((*a* '​inside) (b *a*)) 
 +  ([[CL:​Functions:​format]] [[CL:​Constant Variables:​nil]] "~S ~S ~S" *a* b (dummy-function))) <​r>"​INSIDE TOP TOP" </r>
 +(let* ((*a* '​inside) (b *a*)) 
 +  ([[CL:​Functions:​format]] [[CL:​Constant Variables:​nil]] "~S ~S ~S" *a* b (dummy-function))) <​r>"​INSIDE INSIDE TOP" </r>
 +(let ((*a* '​inside) (b *a*)) 
 +  ([[CL:​Symbols:​declare]] ([[CL:​Declarations:​special]] *a*)) ([[CL:​Functions:​format]] [[CL:​Constant Variables:​nil]] "~S ~S ~S" *a* b (dummy-function))) <​r>"​INSIDE TOP INSIDE"​ </r>
 +</​blockquote>​
 +
 +The example below is incorrect; although ''​x''​ is indeed set before it is used, and is set to a value of the declared type //​[[CL:​Glossary:​integer]]//,​ nevertheless ''​x''​ initially takes on the value **[[CL:​Constant Variables:​nil]]** in violation of the type declaration.
 +
 +<​blockquote>​
 +(let (x) 
 +  ([[CL:​Symbols:​declare]] ([[CL:​Types:​integer]] x)) 
 +  ([[CL:​Macros:​setf]] x (gcd y z)) ...)
 +</​blockquote>​
 +
 +====Affected By====
 +None.
 +
 +====Exceptional Situations====
 +None.
 +
 +====See Also====
 +**[[CL:​Special Operators:​progv|Special Operator PROGV]]**
 +
 +====Notes====
 +None.
 +
 +\issue{DECLS-AND-DOC} \issue{VARIABLE-LIST-ASYMMETRY:​SYMMETRIZE} \issue{KMP-COMMENTS-ON-SANDRA-COMMENTS:​X3J13-MAR-92} \issue{KMP-COMMENTS-ON-SANDRA-COMMENTS:​X3J13-MAR-92}