18

I would like a notebook evaluation to entirely stop when an Assert fails, without quitting the kernel. Is this possible (e.g., by setting $AssertFunction to ... something)?

Edit:

For example, if I create a notebook containing a cell with the following lines, I would like the value of test to still be 0, and for no subsequent cells to be exectuted.

test = 0;
Assert[False];
test = 1;

EDIT:

Note that setting $AssertFunction=Abort[]& does not work, because it only aborts the current computation, but afterwards evaluation continues to proceed through the notebook.

A related question: why must we execute On[Assert] before we can set $AssertFunction? Naturally I understand why we must turn assertions on and off; that is not my question. My question is why On[Assert] apparently resets $AssertFunction:

On[Assert] 
$AssertFunction = Abort[] &;
Assert[False]  (* aborts *)
Off[Assert]
On[Assert]
Assert[False]  (* does not abort *)
J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
Alan
  • 13,686
  • 19
  • 38
  • I see, that's because Abort[] aborts the current evaluation. You are evaluating a whole notebook at once. That's different: the front end will queue up all inputs and send them one by one to the kernel. Abort[] only aborts one of these, as it cannot affect the front end state. Abort[] is only for the kernel. I thought $AssertFunction = FrontEndTokenExecute["EvaluatorAbort"] & would work but it doesn't. I suggest editing the question and spelling out what I said above to attract more attention (i.e. spelling out that Abort doesn't work). – Szabolcs Nov 10 '15 at 20:08
  • The reason why we need On[Assert] is so that we can easily turn on and off the assertions. It's like -DNDEBUG when compiling C code. – Szabolcs Nov 10 '15 at 20:08
  • 1
    @Szabolcs I'd say the fact that "EvaluatorAbort" token is not working is a bug. It doesn't even when I select the cell with SelectionMove. – Kuba Nov 16 '15 at 08:36
  • @Kuba aborting evaluation in the debugger also doesn't work properly, that might be related (one example, feel free to add the bugs tag there). – Jacob Akkerboom Nov 17 '15 at 11:17
  • @JacobAkkerboom I don't really know, could you ask support what one should expect after evaluating Abort[] - newline - Print[1] or after Pause[5] - newline - Print[5] where during pause menu item AbortEvaluation is used? My mails to WRI are still being lost. – Kuba Nov 17 '15 at 11:24
  • @Kuba okido, I put that in a brand new todo list :P (temporary message) – Jacob Akkerboom Nov 17 '15 at 14:56

4 Answers4

13
On[Assert]
$AssertFunction := (
    (*1*)
   SelectionMove[EvaluationNotebook[], All, Notebook, AutoScroll -> False];
   FrontEndExecute @ FrontEndToken @ "RemoveFromEvaluationQueue";
   SelectionMove[EvaluationCell[], After, Cell, AutoScroll -> False];
    (*2*)
   RunScheduledTask[$Pre =., {1}];
       $Pre = Abort[] &; Abort[];
);
  1. First procedure removes all queued cells from the evaluation queue. And puts a selection after a current evaluating cell.

  2. Since no Token or Abort works, let's improvise to abort pending evaluation in current evaluation cell. Each line(not really a line) is a separate CompoundExpression which needs to be aborted separately so we can $Pre the Abort[] operation. But it would be nice to get rid of that later, that's where ScheduledTask comes in. 1 second is arbitrary but I think enough to abort everything and not to interrupt user actions in future.

enter image description here

Everything from main cell after Assert is aborted and the cell with 4 is skipped from evaluation even though it was selected too.

Kuba
  • 136,707
  • 13
  • 279
  • 740
  • Interesting. Needless to say, I supposed something simpler was possible. Can you also address my secondary question? That is, why must the definition of $AssertFunction come after On[Assert]? That is, I find it odd that On[Assert] overrides the current definition of $AssertFunction; is there a good reason for this? – Alan Nov 16 '15 at 13:02
  • @Alan I don't know at the moment :/ – Kuba Nov 16 '15 at 13:04
7

As of Version 11.2 RunScheduledTask has been superseded by SessionSubmit. @Kuba 's cool function stopped working on 11.2 but does work when RunScheduledTask is replaced.

George Wolfe
  • 5,462
  • 21
  • 43
0

This is such a fantastic post! One of my notebooks opens a database that is in the current directory but if I have opened a notebook in a different directory, then it fails to find the database and all subsequent evaluations are wrong. Therefore I wanted to test the directory and Abort the evaluation of all pending cells if it is wrong. But because sometimes I am on my laptop and sometimes on my desktop, only the \Documents part of the path is constant. Using this answer updated to 12.2 produces the following, which works like a charm:

fpath=(NotebookBrowseDirectory/.Options[$FrontEnd])<>"\\";(*save in notebook path*)
(*stop evaluation if the path does not end in \Documents\*)
If[StringTake[fpath,-11]!="\\Documents\\",
(*Remove cells from evaluation queue*)(
SelectionMove[EvaluationNotebook[],All,Notebook,AutoScroll -> False];
FrontEndExecute@FrontEndToken@"RemoveFromEvaluationQueue";
SelectionMove[EvaluationCell[], After, Cell, AutoScroll -> False];
(*set $Pre to abort current cell but before that schedule a task to un-define $Pre*)
SessionSubmit[ScheduledTask[$Pre =., {Quantity[3, "Seconds"]}]];
MessageDialog["Wrong working directory! Open and close a file in /Documents and rerun."];
$Pre=Abort[]&;Abort[];)];

Many thanks @Kuba. It could only be made better by avoiding or redirecting the production of an output cell with $Aborted for each subsequent line in the evaluation cell.

Nicholas G
  • 1,981
  • 10
  • 15
0

It sounds like you want to inspect the stack when an assertion fails. Will Dialog do what you want? As in

$AssertFunction:=Dialog[]

As already mentioned however, cells queued for evaluation, and even subsequent lines in the current cell, will still execute when you Return or ExitDialog. You can ExitDialog[Unevaluated[Abort[]]] to abort a statement, but

test=0;
Assert[False];
test=1;

is three statements.

Ian
  • 1,285
  • 10
  • 17