Stop a script. Just stop it

How can I stop a mathematica script? Abort[] does not stop the script, just jump over a number of lines and proceed with next lines of calculations.

Also, killing the kernel seems not good idea. All I want is C++ exit(0); or Java's System.exit(0);.

(* 10000 lines of calculations *)
If[a==5,Print["Calculation gives an unacceptable result. I stop execution here"];Abort[]]
(* 10000 lines of calculations *)

The script invoked from Mathematica GUI with Shift+Enter.

Solution as stated by thorimur

Catch[

   (* COMPLETE SCRIPT *)

   (* Lots of calculations *)
   Throw["Calculation must be stopped"];
   Print["Never printed"];
   (* Lots of calculations *)

 ]

Answers 1

  • While you can always abort a running evaluation manually with Command + . (or Ctrl + .), here are several ways to do this in Mathematica within a given script! It depends on your particular application and setting. The first two are more general than the rest. I'll run through (most of) the possibilities.

    1. Confirm and Enclose are useful for specific control. Confirm[expr] checks that expr is not a failure (i.e. is not the value $Failed or a Failure, as I understand it, and exits to the nearest Enclose. Otherwise it returns expr. (You can also include a tag as an argument and exit to the nearest Enclose with that tag; see the docs.) Enclose returns a Failure if an enclosed Confirm gives it one; otherwise it leaves the expression alone. More specific variants are ConfirmBy[expr, f] and ConfirmMatch[expr, patt], which work the same way, but in the first case, exits to Enclose only if f[expr] doesn't give True, and in the second, exits to Enclose only if expr doesn't match the pattern patt.

    2. Throw and Catch are similar, but Throw[x] always exits to the nearest enclosing Catch, which then returns x. So, you'd probably want Throw to be in a branch of an If or something like that. If no Throw is encountered, Catch[expr] returns expr just like Enclose. You can also add a tag to Throw and Catch like with Confirm, to control which Catch catches which Throw.

    3. Just for completeness, Abort[] and Interrupt[] should immediately grind the computation to a halt, just as if you'd pressed Command + .. You can also use Abort[] like a Throw, though, by enclosing it with CheckAbort[expr, failexpr]; if expr produces an Abort[], CheckAbort[expr, failexpr] will evaluate to failexpr instead.

    4. If you want to end a loop (Do, For, or While) you can use Break[] inside it. This just ends the nearest enclosing loop. If you want to simply move on to the next iteration within the loop immediately, but keep the loop going, you can use Continue[].

    5. If you want to exit a function definition, you can (well, sometimes) use Return[expr]. This immediately returns expr, but it can be finicky. For example, you might expect f[x_] := 1 + Return[5] to return 5 as soon as it encounters it, but instead it returns 1 + Return[5]—not even 6. I'd recommend Throw and Catch for flow control in general instead.

    6. If you really want, you can embrace spaghetti and use Goto[tag] and Label[tag] in, which work almost exactly how you'd expect, with the caveat that Goto[tag] and Label[tag] have to be at least nested within some common top level compound expression (expression constructed by ;). So, for example, {(Goto[tag]; 1), (Label[tag]; Print[3]; 4)} won't work, but If[True, If[True, Goto[tag]]]; Print[1]; Label[tag]; Print[2] will.


Related Questions