# Tag Info

52

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

38

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

34

Solutions to algebraic or transcendental equations are expressed in terms of Root objects whenever it is impossible to find explicit solutions. In general there is no way express roots of 5-th (or higher) order polynomials in terms of radicals. However even higher order algebraic equations can be solved explicitly if an associated Galois group is solvable. ...

31

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

27

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

26

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

25

Use Reduce[(1/x) Cosh[x/2] == Sqrt[2], x, Reals] or Solve[(1/x) Cosh[x/2] == Sqrt[2], x, Reals] the latter yields {{x -> Root[{-E^(-(#1/2)) - E^(#1/2) + 2 Sqrt[2] #1 &, 0.75858229952537718426}]}, {x -> Root[{-E^(-(#1/2)) - E^(#1/2) + 2 Sqrt[2] #1 &, 5.4693513860610533998}]}} For transcendental equations you may get with Reduce ...

25

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

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

21

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

17

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

16

All of these work: f[x_] := Cosh[x/2]/x - Sqrt[2]; FindRoot [f[x] == 0, {x, 1}] N@FindInstance[f[x] == 0, x, Reals, 2] N@Reduce [f[x] == 0, x, Reals] NSolve [f[x] == 0, x, Reals] N@Solve [f[x] == 0, x, Reals]

16

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

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

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;], ... 13 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." *) ... 12 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] := ...

12

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?

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

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

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

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 } : {}] := ...

9

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 ... 9 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 ... 9 It seems to me that there's a better approach, but one way is to define your own DownValue for this particular message. For example: Unprotect[Message]; Message[NIntegrate::maxp, its_, int_, err_] := Sow[err] Then NIntegrate[Sin[x]/Sqrt[x], {x, 0, 100}, Method -> "MonteCarlo", PrecisionGoal -> 6] // Reap (* Out: {1.07721, {{0.0761274}}} *) 9 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 ... 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 You can control how Messages are sent under Edit->Preferences. Choose the Messages tab and select your prefered behavior. 7 There were some attempts on that in this discussion. I also have this functionality in my debug function posted here 7 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[, Internal`InheritedBlock[{MessagePacket}, Unprotect[MessagePacket]; MessagePacket[name__, BoxData[obj_, form_]] /; ! TrueQ[$tagMsg] := ...

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