6
$\begingroup$

I'm trying to build a Verbose option into some code but I'm having trouble passing to a Quiet statement a variable list of which messages I want to suppress.

My naïve try is code along the lines of

f[x_] := Module[{messageList},
  messageList = {Power::infy};
  Quiet[1/x, messageList]
  ]
f[0]

The idea would then be to build an option Verbose which controls whether the assignment messageList = {Power::infy} is made, or whether that variable is set to {}, which will let the message through.

However, even this bare-bones code is not working, and it returns messages of the sort

Quiet::anmlist: Argument 2 of Quiet[1/0,messageList$1303]
      should be All, None, a message name, or a list of message names. >>

(though obviously the number after messageList$ changes every time).


Edit

It seems, from a discussion in the comments, that two things are important (though I don't understand why). First of all, not all error messages are treated equally (as shown e.g. by running Evaluate[{Power::infy, FindRoot::lstol}]) so to give a better example, here is one with the error I'm interested in, FindRoot::lstol:

g[a_] := Module[{verbose = True, messageList},
  If[verbose,
   messageList = {},
   messageList = {FindRoot::lstol}
   ];
  Quiet[
   FindRoot[x^2 + x + a, {x, 3}]
   , messageList]
  ]
g[1]

It is also important to me to be able to control, from within the function (and eventually with an OptionsPattern[] that contains Verbose->True or False) whether the message list that gets passed is {} or a nontrivial one. I'm not picky about how it gets there (i.e. messageList = If[verbose, {}, {FindRoot::lstol}]; would serve just fine) but it does need to have at least that level of logic built in.


What is the correct way to do this?

$\endgroup$
8
  • 3
    $\begingroup$ You need to use Evaluate@messageList inside Quiet because Quiet has the attribute HoldAll. $\endgroup$
    – C. E.
    Aug 20, 2014 at 16:55
  • $\begingroup$ I tried that, but it has very patchy behaviour and different messages work differently. Try, for example, running Evaluate[{Power::infy, FindRoot::lstol}]: the first one evaluates to itself, but the second one returns the error message. And, of course, giving Quiet the message text is not what you want to do. $\endgroup$ Aug 20, 2014 at 17:14
  • 1
    $\begingroup$ OK, try this: function[x_] := With[{messageList := {Power::infy, FindRoot::lstol}}, Quiet[1/x, messageList]] (Worked for me on your example but I don't know what other corner cases there are.) $\endgroup$
    – C. E.
    Aug 20, 2014 at 17:31
  • $\begingroup$ @Pickett Unless I am overlooking something, there's no need to use SetDelayed inside With's first argument. $\endgroup$ Aug 20, 2014 at 17:41
  • 1
    $\begingroup$ @TeakeNutma You are overlooking the fact that otherwise FindRoot::lstol will be evaluated at assignment. For example With[{x = 2 + 2}, Hold[x]] versus With[{x := 2 + 2}, Hold[x]]. $\endgroup$
    – C. E.
    Aug 20, 2014 at 17:43

4 Answers 4

6
$\begingroup$

We can use Hold to prevent message names from being evaluated until the time is right:

g[a_, verbose_:False] :=
  Module[{messageList}
  , messageList = If[verbose, {}, Hold[FindRoot::lstol]]
  ; messageList /. _[m___] :> Quiet[FindRoot[x^2 + x + a, {x, 3}], {m}]
  ]

result screenshot

$\endgroup$
3
  • $\begingroup$ So, in essence, this works not by Evaluating the Hold, but by replacing it with a 'wrapper' that's everything else in the Quiet? $\endgroup$ Aug 21, 2014 at 14:01
  • $\begingroup$ (In that case, I think syntax like If[verbose, Hold[], Hold[FindRoot::lstol]] /. Hold[m___] :> Quiet[FindRoot[x^2 + x + a, {x, 3}], {m}] is a bit clearer.) $\endgroup$ Aug 21, 2014 at 14:58
  • $\begingroup$ @episanty Yes, it works by preventing evaluation of the message list using Hold and then transforming the expression into a call to Quiet. Whether or not to use the auxiliary variable messageList, or to represent the empty message list using Hold[], are choices that can be made to suit one's taste (and the form of the "real" version of g). $\endgroup$
    – WReach
    Aug 21, 2014 at 18:15
4
$\begingroup$

I have found a workaround which works for my purposes, though it is not particularly pretty, and the weird behaviour of Evaluate on error messages remains a mystery to me. It is possible to switch between different Quiet behaviours by setting a custom message group and then switching that within the logic.

The following code works, as far as I can tell.

$MessageGroups = Join[$MessageGroups, {"Custom" :> {FindRoot::lstol}}]

g[a_, verbose_] := Module[{},
  If[verbose,
   $MessageGroups = ($MessageGroups /. {("Custom" :> {___}) -> ("Custom" :> {})}),
   $MessageGroups = ($MessageGroups /. 
                        {("Custom" :> {___}) -> ("Custom" :> {FindRoot::lstol})})
   ];
  Quiet[
   FindRoot[x^2 + x + a, {x, 3}]
   , {"Custom"}]
  ]

It has two obvious disadvantages:

  • The function g has side effects, and the value of "Custom"/.$MessageGroups is depends on the value of verbose on the last call to g.

  • This pollutes a global variable, and may therefore interfere with other uses of g run on other notebooks on the same kernel or on parallel kernels.

Both of these can probably be fixed with appropriate use of contexts, though it is probably enough to be careful with both of those disadvantages. In any case, I remain interested in a more 'normal' solution which doesn't need to meddle with normal variables and which explains the different behaviour of Power::infy and FindRoot::lstol.

$\endgroup$
4
$\begingroup$

Why not something a little simpler?

g[a_, verbose_: False] /; ! verbose := Quiet[g[a, True], FindRoot::lstol]
g[a_, True] := FindRoot[x^2 + x + a, {x, 3}]

Now:

g[1]        (* no message *)

g[1, True]  (* FindRoot::lstol: printed *)

This has the advantage of separating the primary definition from the one that controls Message printing, making both easier to read in my opinion.

$\endgroup$
1
$\begingroup$

another workaround

example: problem

msg = {General::argx, Power::infy}
Quiet[1/0 + Sqrt[], Evaluate@msg]

example: workaround

msg = {General::argx::English, Power::infy}
Quiet[1/0 + Sqrt[], Evaluate@msg]

it seems: messages, which take arguments are problematic

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.