throw
throw tag result-form →
tag—a catch tag; evaluated.
result-form—a form; evaluated as described below.
throw causes a non-local control transfer to a catch whose tag is eq to tag. 7.10.0 11
This is said more precisely below. -moon & kmp 13-feb-92
Dynamic variable \term{bindings} are undone back to the point of the \specref{catch},
and any intervening \specref{unwind-protect} clean-up code is executed.
Tag is evaluated first to produce an object called the throw tag; then result-form is evaluated, and its results are saved. If the result-form produces multiple values, then all the values are saved. The most recent outstanding catch whose tag is eq to the throw tag is exited; the saved results are returned as the value or values of catch.
This is all said in a concept section now. --sjl 7 Mar 92 \issue{EXIT-EXTENT:MINIMAL} When a transfer of control is initiated by \specref{throw}, the following events occur before the transfer of control is complete. Note that for \specref{throw}, the \term{exit point} is the corresponding \specref{catch} \term{form}. \beginlist \itemitem{1.} Intervening \term{exit points} are ``abandoned'' (\ie their \term{extent} ends and it is no longer valid to attempt to transfer control through them). \itemitem{2.} The cleanup clauses of any intervening \specref{unwind-protect} clauses are evaluated. \itemitem{3.} Intervening dynamic \term{bindings} of \declref{special} variables and \term{catch tags} are undone. what about condition handlers and restarts? --sjl 5 Mar 92 \itemitem{4.} The \term{extent} of the \term{exit point} being invoked ends, and control is passed to the target. \endlist The extent of an exit being ``abandoned'' because it is being passed over ends as soon as the transfer of control is initiated. That is, event 1 occurs at the beginning of the initiation of the transfer of control. The consequences are undefined if an attempt is made to transfer control to an \term{exit point} whose \term{dynamic extent} has ended. Moon had me add the part about "interleaved" -kmp 13-Feb-92 Events 2 and 3 are actually performed interleaved, in the order corresponding to the reverse order in which they were established. The effect of this is that the cleanup clauses of an \specref{unwind-protect} sees the same dynamic \term{bindings} of variables and \term{catch tags} as were visible when the \specref{unwind-protect} was entered. Event 4 occurs at the end of the transfer of control. \endissue{EXIT-EXTENT:MINIMAL}
The transfer of control initiated by throw is performed as described in Section 5.2 (Transfer of Control to an Exit Point).
(catch 'result
(setq i 0 j 0)
(loop (incf j 3) (incf i)
(if (= i 3) (throw 'result (values i j))))) → 3, 9
(catch nil
(unwind-protect (throw nil 1)
(throw nil 2))) → 2
The consequences of the following are undefined because the catch of b is passed over by the first throw, hence portable programs must assume that its dynamic extent is terminated. The binding of the catch tag is not yet disestablished and therefore it is the target of the second throw. Moon: Belongs with redundant and confusing text now commented out in Notes.
If the implementation is extended as outlined above,
the following returns \f{2}.
(catch 'a
(catch 'b
(unwind-protect (throw 'a 1)
(throw 'b 2))))
The following prints “The inner catch returns :SECOND-THROW” and then returns :outer-catch.
(catch 'foo
(format t "The inner catch returns ~s.~%"
(catch 'foo
(unwind-protect (throw 'foo :first-throw)
(throw 'foo :second-throw))))
:outer-catch)
⊳ The inner catch returns :SECOND-THROW
→ :OUTER-CATCH
Moon: This whole example is redundant. The consequences of the following are undefined because the \term{extent} of the {\tt (catch 'bar ...)} \term{exit point} ends when the {\tt (THROW 'FOO ...)} commences. Moon: Belongs with redundant and confusing text now commented out in Notes. If the implementation is extended as described above, the pending \term{exit point} to tag {\tt foo} is discarded by the second \specref{throw} to {\tt bar} and the value 4 is transferred to {\tt (catch 'bar ...)}, that returns 4. The {\tt (catch 'foo ...)} then returns the 4 because its first argument has returned normally. {\tt xxx} is not printed. \code (catch 'foo (catch 'bar (unwind-protect (throw 'foo 3) (throw 'bar 4) (print 'xxx)))) \endcode
None.
7.10.0 12If there is no outstanding catch tag that matches the throw tag, no unwinding of the stack is performed, and an error of type control-error is signaled. When the error is signaled, the outstanding \specref{catch tags}
the dynamic variable \term{bindings}, ... are those
Replaced by more general terms.the dynamic environment is that which was in force at the point of the throw.
block, catch, return-from, unwind-protect, Section 3.1 (Evaluation)
Moon thinks this is just confusing and unnecessary. Implementations can support longer \term{extents} for \term{exit points} than is required here; in particular, an implementation may be extended to allow a larger extent as follows: Events of 1, 2, 3, and 4 are interwoven in the reverse order in which they were established. In particular, the \term{extent} of a passed-over \term{exit point} ends when control reaches a frame that was established before the \term{exit point} was established. In particular, it would be valid, during the evaluation of an \specref{unwind-protect} cleanup form executed because of a non-local transfer of control, to initiate a new transfer of control to an \term{exit point} intervening between the \specref{unwind-protect} and the original target; the original processing of transfer of control is abandoned.
catch and throw are normally used when the exit point must have dynamic scope (e.g., the throw is not lexically enclosed by the catch), while block and return are used when lexical scope is sufficient.