Tag Info

Hot answers tagged message-coding

64

I feel this is a good opportunity to list some error-checking techniques. I will discuss those I'm aware of, and please feel free to edit this post and add more. I think the main questions to answer here are what we would like a function to return in the case of error, and how to do this technically. What to return on error I can see 3 different ...

51

I found a robust solution described in this MathGroup message by Maxim Rytin: messageHandler = If[Last[#], Abort[]] & InternalAddHandler["Message", messageHandler] This will abort the computation whenever a message would be printed. It can be turned off using InternalRemoveHandler["Message", messageHandler] Alternatively this can be ...

40

While I wait for better answers from some very knowledgeable people in the matter on the site, I'll write what I'm thinking... I think that most of your problems are due to lack of practice with functional thinking rather than lack of debugability itself. I think one that on the contrary, one of the advantages of programming functionally is that the state ...

32

While I agree that the debugging tools could have been better developed by now, let me just throw in a few notes and links. Function chaining (f[g[h[...]]]): I'd argue that this is a good thing. Why: Functions return expressions, which are immutable. You don't introduce as much state (or at all), as in imperative languages. This makes it easier to debug ...

29

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[, InternalInheritedBlock[{MessagePacket}, Unprotect @ MessagePacket;...

28

Like in other programming languages, such as C or Java, assertions are used to catch errors in the logic of your code. With discipline, you can also use exceptions for a similar purpose (see e.g. this discussion for an example). Using patterns and returning a function unevaluated is useful in different types of situations. The linked above answer also ...

24

If you look carefully, you'll notice that the usage messages of package functions are nicely formatted. Notice the nice italicised and subscripted $x_1$. If you actually look in the package, you'll find a usage message that doesn't have any formatting at all, and even differs from the version ?DelaunayTriangulation gives us. If[Not@ValueQ[...

22

The large addendum on handling multiple messages as built-ins do has been moved to a separate post; please see the link below for advanced message handling options. How to check the style and number of arguments like the built-in functions? Macro package function SetArgumentCount In recent versions there is an undocumented function Macros...

18

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 ...

17

What about something like this? Function[i, {i, ParallelEvaluate[i]};, HoldFirst][ Unprotect[Message, Check, Quiet]; Module[{$guardMes = True,$guardChck = True, $guardQuiet = True}, Message[args___ /;$guardMes] := Block[{$guardMes = False}, Message[args]; If[Head[First@{args}] =!=$Off, Abort[]]; ]; Quiet[args___ /; $guardQuiet] := Block[... 17 Here's another, reliable way: messages = {} clearMessages[] := messages = {} collectMessages[m_] := AppendTo[messages, m] InternalAddHandler["Message", collectMessages] Then do clearMessages[] 1/0; 0/0; messages InternalRemoveHandler["Message", collectMessages] Reference and details: How to abort on any message generated? 17 I would use the fact that Mathematica's pattern matching goes from specific to general. Mathematica determines that the new transformation rule is more specific than a rule already present, and would never be used if it were placed after this rule. In this case, the new rule is placed before the old one. Note that in many cases it is not possible to ... 14 It is actually straightforward. You use Messages[symbol] to get the list, e.g. Power::infy (* trigger loading the message *) Messages[Power] (* {HoldPattern[Power::infy] :> "Infinite expression 1 encountered."} *) then, as it is a list of replacement rules, you can simply do Power::infy /. Messages[Power] (* "Infinite expression 1 encountered." *) ... 14 rcollyer has a nice solution. Here's another possibility using Check and printing the list of messages generated at the current evaluation. Quiet@Block[{$OldMessages = 0}, Do[Check[#^#/# &@Mod[i, 2], Print@StringForm["At i=, ", i, $MessageList[[$OldMessages + 1 ;;]]]; $OldMessages = Length@$MessageList;], ...

14

As acl points out, this post shows you how to setup error highlighting for invalid number of arguments. Coming to the actual error messages used, there are three built-in messages attached to General, that can be used for your own functions as well. These are argx, argrx and argt: General::argx (* "1 called with 2 arguments; 1 argument is expected." *) ...

13

The easiest and, so far, the best solution I have found is the following: (* Put the following two lines at the top of every notebook. *) messageHandler = If[Last[#], Interrupt[]] & ; InternalAddHandler["Message", messageHandler]; The above code is slightly modified from Szabolcs's solution at the beginning of this thread. I changed Abort to ...

11

I agree completely with J.M., Quiet is the answer. Implementing WithOff using Quiet is (as I'm sure you know) trivial. Here it is, just for fun: ClearAll[WithOff] SetAttributes[WithOff, HoldAll]; WithOff[msg_, expr_] := Quiet[expr, {msg}]; WithOff[Pattern::patv, rule = (f[x_Integer | {x__Integer}] :> g[x])]; rule2 = x_[x__] :> x;

11

New Method FJRA pointed out that my original method will fail in certain cases. Here is what I hope is a more robust approach: Unprotect[Message, $MessageList] Message[args___] /; ! TrueQ[$msgClear] := Block[{$msgClear = True},$MessageList = DeleteCases[$MessageList, HoldForm[Power::infy]]; Message[args] ] Now the specified message will print ... 11 You can specify a general error message that only consists of a placeholder General::error = "1"; and then use foo[x_] := Module[{}, If[x < 0, Message[foo::error, "x<0 detected"], x]]; r = foo[-1] foo::error: x<0 detected 10 Here's a tiny utility function you might use if you're trying to look for a message that contains a known string: searchMessages[str_String, opts___] := Sort[Select[ Flatten[Map[ToExpression[#, InputForm, Defer] :> Evaluate[ToExpression[#]] &, StringCases[FindList[$InstallationDirectory <> ...

10

You can do something like this: resetMessages[symbol_] := With[{mysymbol = symbol}, Unprotect[$MessageList];$MessageList = DeleteCases[$MessageList, HoldForm[MessageName[mysymbol, _]]]; Protect[$MessageList];] And you will have to call it after each function... Sqrt[a, b, c, d]; Exp[a, b]; resetMessages[Exp]; Sqrt[a, b, c, d]; \ Exp[a, b]; ...

10

You can control how Messages are sent under Edit->Preferences. Choose the Messages tab and select your prefered behavior.

10

First, note that turning off messages is technically not the same thing as not printing them. You can avoid printing messages by removing the output channel they're being sent to: $Messages = {} Restore the previous behaviour using$Messages = $Output, provided that you haven't changed$Output. But this won't turn messages off, it will only avoid ...

10

Michael's suggestion to use Off and On with General::shdw will be one solution to your problem - if you really decide to go down this road (which is what we recommended against in comments). But, just for the record, it is not difficult to implement one's own version of Quiet, that would be more selective. Here is one possible implementation: ClearAll[...

9

A simple method for accomplishing this is to have Message Throw an error when it is called, interrupting the current execution. Here is a replacement for Check which does that, with the same calling signature: ClearAll[InterruptingCheck] SetAttributes[InterruptingCheck, HoldAll] InterruptingCheck[expr_, failexpr_, msgs : {___MessageName } : {}] := ...

8

You can define the function: messageIsOn[msg_]:=Head[msg]===String Which yields True if the message is on. Than do e.g: msgStatus=messageIsOn[Pattern::patv] If[msgStatus, Off[Pattern::patv]] < some calculation suppressing message Pattern::patv > (* Restore the message status *) If[msgStatus, On[Pattern::patv]]

8

Following R.M's suggestion, and shamelessly lifting code from the Wizard’s fine answer there, you can use Stack[] and get the following: SetAttributes[withTaggedMsg, HoldAll] withTaggedMsg[] := Function[, InternalInheritedBlock[{MessagePacket}, Unprotect[MessagePacket]; MessagePacket[name__, BoxData[obj_, form_]] /; ! TrueQ[$tagMsg] := ... 8 How about using "RuntimeErrorHandler": f = Compile[{{x, _Real}, {y, _Real}}, Log[(x - y^2 - 2. x)^2]/(y x^2 - 2 (x + y) - y^2 + 3.), "RuntimeOptions" -> {"RuntimeErrorHandler" -> Function[Throw[$Failed]]} ]; Catch[Quiet@f[-196, 15]] // AbsoluteTiming (* {0.000019, 0.0000116843} *) Catch[Quiet@f[-196, 14]] // AbsoluteTiming (* {0.000051, \$...

8

My initial answer was simply wrong. I now think this is a bug. Although a message may be expressly attached to the Symbol x using TagSet it is still not localized. (TagSet is superfluous but it helps make the point.) Block[{x}, x /: x::foo = "bar"; Message[x::foo]]; Messages[x] During evaluation of In[]:= x::foo: bar {HoldPattern[x::foo] :> "...

8

This has been fixed in 10.1 (windows) code ClearAll[x] Block[{x}, x::test1 = "message1"]; x::test1 ClearAll[x] Block[{x}, Messages[x] = {HoldPattern[x::test2] :> "message2"}]; x::test2 Block[{x}, x /: x::foo = "bar"; Message[x::foo]]; Messages[x]

Only top voted, non community-wiki answers of a minimum length are eligible