2
$\begingroup$

I can turn on assertions, but they don't terminate the current evaluation. For example:

On[Assert];
Assert[False]

Assert::asrtf: Assertion False failed. >>

(* IOW assertions are indeed on *)
(* but... *)

Module[{},
  Assert[False];
  Print["this line should never be reached"];
]

Assert::asrtf: Assertion False failed. >>

this line should never be reached

How can I get Mathematica to abort the current evaluation immediately if it runs into a failed assertion?

$\endgroup$
  • 3
    $\begingroup$ Check[Assert[...], Abort[]] or use $AssertFunction with appropriate dressing... $\endgroup$ – ciao May 17 '15 at 21:56
  • $\begingroup$ @kjo Thanks for accepting my answer, but in general you should give this some time. Remember, some users will probably visit the site later because they are sleeping now and surely there are several people having great ideas here. Accepting an answer too soon might discourage them to contribute. $\endgroup$ – halirutan May 18 '15 at 0:25
  • $\begingroup$ @halirutan: no prob, I just "unaccepted" it : ) $\endgroup$ – kjo May 18 '15 at 1:47
  • $\begingroup$ OK, that's a long enough wait: Re-accepted! $\endgroup$ – kjo May 26 '15 at 11:34
4
$\begingroup$

As @ciao showed you, it is possible to use $AssertionFunction to force Assert into aborting. I don't think this should be done. Just imagine what happens when you publish a package where you change the behavior of Assert. Then, for all people using your package, Assert will no longer work in the expected way.

What about implementing your own AbortAssert? You could just copy how it is done in Assert:

  • it is turned on and off by using On and Off, which basically only turns on/off the trace message (this part doesn't work as I expected it)
  • you just use a single function to test a condition. If it fails, the program aborts and prints the assertion that failed

Now we can write this down:

AbortAssert::trace = "Assertion `` failed.";
AbortAssert /: On[AbortAssert] := On[AbortAssert::trace];
AbortAssert /: Off[AbortAssert] := Off[AbortAssert::trace];
SetAttributes[AbortAssert, {HoldFirst}];
AbortAssert[test_] := 
 Check[TrueQ[test] || Message[AbortAssert::trace, HoldForm[test]], 
  Abort[]]

and test it

Module[{},
 AbortAssert[False == True];
 Print["this line should never be reached"];
]

Mathematica graphics

Appendix regarding On and Off

As you see above I need to explicitly define that On[AbortAssert] turns on the trace message. I don't know why this does not work out of the box. The documentation for On clearly states

On[s] is equivalent to On[s::trace].

This doesn't seem to work on my Linux machine with version 10.1.

$\endgroup$
  • $\begingroup$ On a similar note, is it ever advisible to change built-in behaviour in a package? I guess overloading operators for types you define is ok, but not changing what normal use of functions does. $\endgroup$ – masterxilo Jul 5 '16 at 15:15
  • $\begingroup$ @masterxilo Well, it can be dangerous to change built-in stuff even for yourself, because sometimes it is hard see what is used under the hood. Therefore, if you change basic functions, you might run into problems. For instance, if you change Compile and you don't know that things like Plot or Table use it under the hood, you might run into unexpected things. I would not advice to make such things in packages unless you absolutely know what consequences it has. $\endgroup$ – halirutan Jul 6 '16 at 19:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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