Prepend Information to Warning Messages

I have a function running within a Do loop that sometimes issues a warning. I'd like to prepend the warning with the loop ctr so that I can go back and debug that instance later.
Basically, I would like to modify the following line,

Do[i^0, {i, -1, 1}] 

so that instead of displaying the warning:

Power::indet: Indeterminate expression 0^0 encountered. >> 

it displays:

i=0, Power::indet: Indeterminate expression 0^0 encountered. >> 

Where i==0 is the iteration that i^0 issues the warning.

Thanks

Replay

Here is my proposal for tagging messages with (the value of) an arbitrary expression at the time of message generation. The tag is placed inside the the message itself.

ClearAll[withTaggedMsg]
SetAttributes[withTaggedMsg, HoldAll]

withTaggedMsg[exp_, label_: "When"] := Function[,
   Internal`InheritedBlock[{MessagePacket},
     Unprotect @ MessagePacket;
     mp : MessagePacket[__, _BoxData] /; !TrueQ[$tagMsg] :=
       Block[{$tagMsg = True},
         Style[Row[{label, HoldForm[exp], "=", exp, " "}, "  "], "SBO"] /. tag_ :>
           MapAt[RowBox[{ToBoxes @ tag, #}] &, mp, {-1, 1}] // Identity
       ];
     #
   ],
  HoldAll]

Usage:

Do[i^0, {i, -1, 1}] // withTaggedMsg[i]

Prepend Information to Warning Messages

Do[i^0, {i, -1, 1}] // withTaggedMsg[i, "At iteration"]

Prepend Information to Warning Messages



Note: this only works with variables that are either globally accessible or are scoped using Block. For example,

f[x_] := Message[f::brains, x]
f[5] // withTaggedMsg[x]
(* At iteration x = x f::brains: -- Message text not found -- (5) *)

Module[{x = 5},
 Message[f::brains, x]
] // withTaggedMsg[x]
(* At iteration x = x f::brains: -- Message text not found -- (5) *)

With[{x = 5},
 Message[f::brains, x]
] // withTaggedMsg[x]
(* At iteration x = x f::brains: -- Message text not found -- (5) *)

Block[{x = 5},
 Message[f::brains, x]
] // withTaggedMsg[x]
(* At iteration x = 5 f::brains: -- Message text not found -- (5) *)

This means that any variable that is scoped using Block can be used to tag a message. So, loop variables from Do and Table are accessible via this method, in addition to any Block variable. This makes it indispensable as a debugging tool.

I cannot seem to make it do exactly what you want do to how messages are created, but here is a serviceable alternative using $MessagePrePrint. $MessagePrePrint formats the variables specified in the message string, and in your example, the message has the form

General::indet = "Indeterminate expression `1` encountered."

where the `1` will be replaced by $0^0$, or whatever else you pass to it. It is that argument that $MessagePrePrint operates on, and we can change it to suit us, as follows

Block[{$MessagePrePrint},
     $MessagePrePrint := ToString[StandardForm[#]] <> " at i = " <> ToString[i] &;
 Do[i^0, {i, -1, 1}]
]

where the output will now read "$0^0\text{ at i} =1$".



(Edit from Mr.Wizard)

The code above fails in Mathematica 7. It seems that v7 doesn't like the fact that

InputForm @ ToString @ StandardForm @ HoldForm[0^0]

 "\!\(\*TagBox[\(0\^0\), HoldForm]\)"

Here is a variation that is compatible with version 7:

Block[{$MessagePrePrint},
      $MessagePrePrint := [email protected]{#, " at i = ", i} ~ToString~ StandardForm &;
  Do[i^0, {i, -1, 1}]
]

This is still not ideal however, as every field in the message gets this tag. For example, if you enter the spurious Inner[f, {{1, 2}}, {3}] you get:

Inner::incom: Length 2 at i = 1 of dimension 2 at i = 1 in {{1,2}} at i = 1 is incommensurate with length 1 at i = 1 of dimension 1 in {3} at i = 1. >>

rcollyer has a nice solution. Here's another possibility using Check and printing the list of messages generated at the current evaluation.

[email protected][{$OldMessages = 0},
        Do[Check[#^#/# &@Mod[i, 2],
            [email protected]["At i=``, ``", i, $MessageList[[$OldMessages + 1 ;;]]];
            $OldMessages = [email protected]$MessageList;],
        {i, 0, 5}]
   ];

(* At i=0, {Power::indet,Power::infy}
   At i=2, {Power::indet,Power::infy}
   At i=4, {Power::indet,General::stop,Power::infy,General::stop} *)

Remove the [email protected] if you want to see the actual messages generated.

Category: debugging Time: 2012-07-11 Views: 1

Related post

iOS development

Android development

Python development

JAVA development

Development language

PHP development

Ruby development

search

Front-end development

Database

development tools

Open Platform

Javascript development

.NET development

cloud computing

server

Copyright (C) avrocks.com, All Rights Reserved.

processed in 0.200 (s). 12 q(s)