Version 12.2 brought us Confirm and Enclose. What's the point? Is it just that it's a slightly more convenient syntax than Throw and Catch with a conditional?

I can see where Confirm beats Assert: you don't need to On[Assert] first, and also Confirm is catchable.

  • 6
    $\begingroup$ It really deserves a "Background & Context" section in the docs. One difference is that Confirm throws a failure to an enclosing Enclose (bad name?) only if the expression evaluates to one of certain common forms of failure; otherwise, execution continues. The first example in "Applications" @Rolf points out shows how that might be syntactically convenient. It is perhaps no more than syntactic sugar for common Catch/Throw failure conditions. $\endgroup$
    – Michael E2
    Commented Feb 2, 2021 at 17:23
  • 6
    $\begingroup$ One of the major differences is that Enclose @ expr scopes lexically for inner Confirms (making these functions very predictable), while Catch @ expr scopes dynamically for inner Throws. The dynamical scoping of single argument Throw/Catch is often very undesirable and Leonid takes every opportunity to point out that it's a defect of the language that they can completely break evaluation control because of that. In addition, ConfirmBy and ConfrimMatch etc. are just really nice syntactically. $\endgroup$ Commented Feb 2, 2021 at 17:48
  • 6
    $\begingroup$ @SjoerdSmit I think that exceptions inherently scope dynamically to be useful, they are all about bubbling up through call stack until the proper handler is reached. If they would scope lexically, then this would just be a somewhat less local form of Return, similar in spirit to two-argument Return. What I have been criticizing are Catch and Throw without a tag, since then there is no way to be selective, and one can catch something that was intended to be caught higher up in the call stack. This would be like e.g. throwing Exception in Java, rather than its more specific subclass. $\endgroup$ Commented Feb 2, 2021 at 19:45
  • 4
    $\begingroup$ @SjoerdSmit Yeah, I get your point. I just wanted to point out that dynamic scoping is inherent in exceptions, so if we are willing to use them, we should accept that. Of course I agree that in all cases where the lexical scope can be used, it is safer. What makes single-arg Catch and Throw dangerous compared to their 2 or 3 arg counterparts is IMO not so much the dynamic nature (which they all share), but the fact that they can't be nested / re-entrant, so to speak. Which of course matters for dynamic scope, because in general you can't control the full evaluation stack. $\endgroup$ Commented Feb 2, 2021 at 20:38
  • 4
    $\begingroup$ I propose @SjoerdSmit write up a summary of the commentary as a response. Or anyone else who might feel so inclined. $\endgroup$ Commented Feb 2, 2021 at 22:13

1 Answer 1


Confirm and Enclose are higher-level constructs meant to provide a convenient (and readable) notation for recovering from expected but somewhat unusual conditions involving program data or state. They happen to be built upon the lower-level Throw/Catch mechanism, but part of the point of their introduction is to hide such implementation details from the user.

Throw is a very low-level abstraction, akin to a goto statement. In itself, it does not offer someone reading the code many clues as to its purpose. By contrast, the various Confirm functions are meant to indicate to the reader that there are recovery strategies in place for:

  • unusual data (Confirm, ConfirmBy and ConfirmMatch)
  • unusual program state (ConfirmAssert)
  • unusual warning messages (ConfirmQuiet)

The Confirm family join a growing list of non-local return features within Mathematica. In principle, all such constructs could be implemented using only Throw, Catch and CheckAll. Nevertheless, there are many features for specific purposes and with specific names. Consider:

Signaller Handler Handler
Error If
Throw Catch dynamic if tag unmatched yes general-purpose non-local exit facility
Abort CheckAbort dynamic no yes error-handling
Message Check dynamic if messages unmatched no warning-handling
Assert $AssertFunction dynamic n/a no checking programming preconditions
Enclose lexical or
if tag unmatched yes recovering from unusual data
ConfirmAssert Enclose lexical or dynamic if tag unmatched yes recovering from unusual program state
ConfirmQuiet Enclose lexical or dynamic if tag unmatched yes recovering from warnings
any WithCleanup dynamic yes depends upon signal resource disposal
any Internal` WithLocalSettings dynamic yes depends upon signal resource disposal
any CheckAll dynamic no depends upon signal backstopping exits

Many of these names and functions have arisen due to history. Enclose and WithCleanup may represent a move by WRI to unify the handling patterns for expected but unusual program conditions. It might explain why there is no ConfirmNoAbort -- Abort can be reserved for truly unexpected program errors.

Some observations:

  • Throw/Catch are similar to the like-named symbols in Lisp, as well as longjmp/setjmp from C.
  • Abort/CheckAbort are similar to throw/try-catch in C++, Java and C#... except that with CheckAbort it can be difficult (or impossible) to identify the triggering signal using just $MessageList. So Throw/Catch are often used instead for error-handling.
  • ConfirmAssert and Assert are similar but perhaps the former should now be used for handling expected program conditions and the latter reserved for forensics during debugging sessions.
  • ConfirmQuiet is much like Check except that it integrates with Enclose.
  • CheckAll and Internal`WithLocalSettings are undocumented. But the recently introduced experimental symbol WithCleanup covers most of the functionality provided by the latter. WithCleanup is similar to unwind-protect in Lisp and try-finally in Java and C#. CheckAll is similar to a handler for type t in Lisp or try-catch(Throwable) in Java.
  • As of V12.2, the lexical forms of Confirm are simulated by dynamic Throw/Catch using private tags and some heuristic checks in Enclose. The abstraction is a bit leaky but likely not to the point of real harm... for fun try Enclose[Confirm[SymbolName@#]]&[Confirm] (working with held code is really hard in WL).
  • 3
    $\begingroup$ Thank you very much for the complete overview. It is very helpful. $\endgroup$
    – Michael E2
    Commented Feb 6, 2021 at 19:49
  • $\begingroup$ +1, very nice answer. I am happy I have not tried to answer myself, it would've likely been a half-hearted and / or needlessly bloated attempt compared to this one. $\endgroup$ Commented Feb 6, 2021 at 22:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.