This shows you the differences between two versions of the page.
cl:macros:loop-finish [2019/09/14 05:00] |
cl:macros:loop-finish [2021/01/25 18:00] (current) |
||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Local Macro LOOP-FINISH ====== | ||
+ | |||
+ | ====Syntax==== | ||
+ | * **loop-finish** | ||
+ | |||
+ | ====Description==== | ||
+ | The **loop-finish** macro can be used lexically within an extended **[[CL:Macros:loop]]** //[[CL:Glossary:form]]// to terminate that //[[CL:Glossary:form]]// "normally." That is, it transfers control to the loop epilogue of the lexically innermost extended **[[CL:Macros:loop]]** //[[CL:Glossary:form]]//. This permits execution of any **[[CL:Macros:finally]]** clause (for effect) and the return of any accumulated result. | ||
+ | |||
+ | ====Examples==== | ||
+ | The below example terminates the loop, but returns the accumulated count. | ||
+ | |||
+ | <blockquote> | ||
+ | (loop for i in '(1 2 3 stop-here 4 5 6) | ||
+ | when ([[CL:Functions:symbolp]] i) | ||
+ | do (loop-finish) | ||
+ | count i) → 3 | ||
+ | </blockquote> | ||
+ | |||
+ | This loop is equivalent to: | ||
+ | <blockquote> | ||
+ | (loop for i in '(1 2 3 stop-here 4 5 6) | ||
+ | until ([[CL:Functions:symbolp]] i) | ||
+ | count i) → 3 | ||
+ | </blockquote> | ||
+ | |||
+ | |||
+ | While **loop-finish** can be used can be used in a variety of situations, it is really most needed in a situation where a need to exit is detected at other than the loop's "top level" (where **until** or **when** often work just as well), or where some computation must occur between the point where a need to exit is detected and the point where the exit actually occurs. For example: | ||
+ | |||
+ | <blockquote> | ||
+ | ([[CL:Macros:defun]] tokenize-sentence (string) | ||
+ | ([[CL:Special Operators:macrolet]] ((add-word (wvar svar) | ||
+ | `([[CL:Macros:when]] ,wvar | ||
+ | ([[CL:Macros:push]] ([[CL:Functions:coerce]] ([[CL:Functions:nreverse]] ,wvar) '[[CL:Types:string]]) ,svar) | ||
+ | ([[CL:Macros:setf]] ,wvar [[CL:Constant Variables:nil]])))) | ||
+ | (loop with word = '() and sentence = '() and endpos = [[CL:Constant Variables:nil]] | ||
+ | for i below ([[CL:Functions:length]] string) | ||
+ | do ([[CL:Special Operators:let]] ((char ([[CL:Functions:aref]] string i))) | ||
+ | ([[CL:Macros:case]] char | ||
+ | (#\Space (add-word word sentence)) | ||
+ | (#\. ([[CL:Macros:setf]] endpos ([[CL:Functions:math-one-plus|1+]] i)) (loop-finish)) | ||
+ | (otherwise ([[CL:Functions:push]] char word)))) | ||
+ | finally (add-word word sentence) | ||
+ | ([[CL:Macros:return]] ([[CL:Functions:values]] ([[CL:Functions:nreverse]] sentence) endpos))))) <r>TOKENIZE-SENTENCE</r> | ||
+ | (tokenize-sentence "this is a sentence. this is another sentence.") <r>("this" "is" "a" "sentence") | ||
+ | 19</r> | ||
+ | (tokenize-sentence "this is a sentence") <r>("this" "is" "a" "sentence") | ||
+ | NIL</r> | ||
+ | </blockquote> | ||
+ | |||
+ | ====Side Effects==== | ||
+ | Transfers control. | ||
+ | |||
+ | ====Affected By==== | ||
+ | None. | ||
+ | |||
+ | ====Exceptional Situations==== | ||
+ | Whether or not **loop-finish** is //[[CL:Glossary:fbound]]// in the //[[CL:Glossary:global environment]]// is //[[CL:Glossary:implementation-dependent]]//; however, the restrictions on redefinition and //[[CL:Glossary:shadow|shadowing]]// of **loop-finish** are the same as for //[[CL:Glossary:symbol|symbols]]// in the **COMMON-LISP** //[[CL:Glossary:package]]// which are //[[CL:Glossary:fbound]]// in the //[[CL:Glossary:global environment]]//. The consequences of attempting to use **loop-finish** outside of **[[CL:Macros:loop]]** are undefined. | ||
+ | |||
+ | ====See Also==== | ||
+ | * **[[CL:Macros:loop|Macro LOOP]]** | ||
+ | * {\secref\LoopFacility} | ||
+ | |||
+ | ====Notes==== | ||
+ | |||
+ | \issue{LEXICAL-CONSTRUCT-GLOBAL-DEFINITION:UNDEFINED} | ||