Aborting execution on first message

342 views
Skip to first unread message

Yaroslav Bulatov

unread,
Jan 4, 2011, 6:52:00 PM1/4/11
to
Is there a way to Abort execution on the first message generated?
Essentially, I'm looking to mimic behavior of "Break at Message" of
the Debugger in normal mode

Leonid Shifrin

unread,
Jan 6, 2011, 2:03:49 AM1/6/11
to
Hi Yaroslav,

This is possible. I suggest to use the Block trick, which is generally a
very powerful and underrated mechanism (but also dangerous, since you can
corrupt the kernel in subtle ways if you use it without care). Here is a
minimal example:

ClearAll[f];
f::noodd = "The input is not an odd number";
f::nonum = "The input is not of the right type";
f[x_?OddQ] := x^2;
f[x_?NumericQ] := "" /; Message[f::noodd];
f[_] := "" /; Message[f::nonum];
f[___] := $Failed;

In[37]:= f[2]

During evaluation of In[37]:= f::noodd: The input is not an odd number

During evaluation of In[37]:= f::nonum: The input is not of the right type

Out[37]= $Failed

Here is the simplest (but really not very elegant) version:

In[38]:= Block[{Message},
Message[args__] := Abort[];
f[2]]

Out[38]= $Aborted

Here is a more elaborate version which allows you to get some information
about the execution near the point at which we stop:

ClearAll[execAndAbortOnMessage];
SetAttributes[execAndAbortOnMessage, HoldAll];
execAndAbortOnMessage[code_, actionCode_: Automatic] :=
Block[{Message},
If[Unevaluated[actionCode] === Automatic,
Message[args__] := (Print["Aborted at ", Stack[_][[-5]]];
Abort[]);,
(* else *)
Message[args__] := (Print["Stopped at ", Stack[_][[-5]]];
actionCode);];
code];

For example:

In[39]:= execAndAbortOnMessage[f[2]]

During evaluation of In[39]:= Aborted at f[2]

Out[39]= $Aborted

Or,

In[40]:= execAndAbortOnMessage[f[2], Throw[$Failed]]

During evaluation of In[40]:= Stopped at f[2]

During evaluation of In[40]:= Throw::nocatch: Uncaught Throw[$Failed]
returned to top level. >>

Out[40]= Hold[Throw[$Failed]]

As you see, the above function allows you to execute arbitrary code when you
stop the evaluation. Note that using Abort[] is really the last resort. I
understand that you probably want it for debugging, but even so, often
softer ways like exception throwing as above will offer you more
possibilities. You can use exceptions with tags, for example, to execute
different code depending on the error.

I did not test the function extensively, so it may not always behave as
intended, but at least this is some starting point. You can play with Stack[
] further if you need to extract more information about the evaluation near
the point where we abort it.

Hope this helps.

Regards,
Leonid

Maxim

unread,
Jan 8, 2011, 3:36:59 AM1/8/11
to

There is an undocumented way:

Internal`HandlerBlock[
{"Message", Replace[#, _[_, True] :> Abort[]] &},
Do[Print[i/0], {i, 5}]]

Another handler type is "MessageTextFilter". "Message" is invoked for
every generated message and passes one argument of the form
Hold[..., ...] to the handler function, with the second element set to
False for quieted messages. "MessageTextFilter" is invoked for
messages that actually get printed and calls the function with three
arguments.

Maxim Rytin
m...@inbox.ru

Albert Retey

unread,
Jan 8, 2011, 3:41:13 AM1/8/11
to
Hi,


> Is there a way to Abort execution on the first message generated?
> Essentially, I'm looking to mimic behavior of "Break at Message" of
> the Debugger in normal mode
>

See documentation of Check, I think it is what you are looking for...

hth,

albert

Reply all
Reply to author
Forward
0 new messages