The loop-finish macro can be used lexically within an extended loop form to terminate that form "normally." That is, it transfers control to the loop epilogue of the lexically innermost extended loop form. This permits execution of any finally clause (for effect) and the return of any accumulated result.
The below example terminates the loop, but returns the accumulated count.
(loop for i in '(1 2 3 stop-here 4 5 6) when (symbolp i) do (loop-finish) count i) → 3
This loop is equivalent to:
(loop for i in '(1 2 3 stop-here 4 5 6) until (symbolp i) count i) → 3
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:
(defun tokenize-sentence (string) (macrolet ((add-word (wvar svar) `(when ,wvar (push (coerce (nreverse ,wvar) 'string) ,svar) (setf ,wvar nil)))) (loop with word = '() and sentence = '() and endpos = nil for i below (length string) do (let ((char (aref string i))) (case char (#\Space (add-word word sentence)) (#\. (setf endpos (1+ i)) (loop-finish)) (otherwise (push char word)))) finally (add-word word sentence) (return (values (nreverse sentence) endpos)))))
(tokenize-sentence "this is a sentence. this is another sentence.")
("this" "is" "a" "sentence") 19
(tokenize-sentence "this is a sentence")
("this" "is" "a" "sentence") NIL
Whether or not loop-finish is fbound in the global environment is implementation-dependent; however, the restrictions on redefinition and shadowing of loop-finish are the same as for symbols in the COMMON-LISP package which are fbound in the global environment. The consequences of attempting to use loop-finish outside of loop are undefined.