16
$\begingroup$

Is there a way to find an existing error message in the System` context, that is used for a certain case? I want to include a message in a custom function that compares all the arguments of the function, and checks if they have the same length. I'm pretty sure that there is one such, but I can't seem to find it. And I don't want to insert new symbols or messages to the namespace if I can use existing ones. Now I am looking for a method that is general; i.e., it can be applied to other cases, not just this one with argument lengths.

For example I am looking for a message that works like this:

General::badlen = "The length of arguments `1`, `2`, `3` must be the same.";

myFun[x_List, y_List, z_List] /; 
  If[Length@x == Length@y == Length@z, True,
     Message[myFun::badlen, x, y, z]; False] := x*y*z;
$\endgroup$
4
  • 1
    $\begingroup$ The nearest message that I am aware of is General::bldim... anyway, you might want to look for appropriate messages that you can use within Messages.m, which is in the directory $InstallationDirectory <> "/SystemFiles/Kernel/TextResources/English". $\endgroup$ Nov 17, 2012 at 11:46
  • $\begingroup$ Thanks @J.M. It could be a perfect answer... $\endgroup$ Nov 17, 2012 at 12:38
  • $\begingroup$ I don't think it's a completely optimal message, tho. You'll of course need to inscribe additional code to determine which two of the three arguments given have the incompatibility... also, there might be a better error message within Messages.m; I just got lazy after five minutes. $\endgroup$ Nov 17, 2012 at 12:43
  • $\begingroup$ @J.M. Well, my Q is not about this specific error message (it could have been any other task), but the way how to access/query/find built-in error messages. $\endgroup$ Nov 17, 2012 at 12:58

2 Answers 2

18
$\begingroup$

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[FileNameJoin[{$InstallationDirectory, "SystemFiles",
                                              "Kernel", "TextResources", "English",
                                              "Messages.m"}], str, opts,
                                IgnoreCase -> True],
                       RegularExpression["([\\w$]|`)+::(\\w)+"]], {2}]],
                  With[{s = Last[#]},
                       StringQ[s] && ! StringFreeQ[s, str, IgnoreCase -> True]] &]]

For example,

searchMessages["determinant"]
   {TransferFunctionModel::method :> 
    "Value of option Method -> `1` is not Automatic, \"DeterminantExpansion\",
     \"ResolventIdentities\", \"Inverse\", or Generic."}

The function tries to search for apropos messages within the Messages.m file within the system files. It won't always find an appropriate message, since there are messages like General::offline that aren't within Messages.m (though grep tells me that that particular message is in $InstallationDirectory <> "SystemFiles/Autoload/PacletManager/Kernel/Services.m", so you know what to modify). Still, it's a start...

$\endgroup$
4
  • $\begingroup$ Thanks for the extra effort, I really appreciate it! $\endgroup$ Nov 17, 2012 at 14:21
  • $\begingroup$ No problem: as I said, I'm lazy, so I wrote a routine to do the searching for me... $\endgroup$ Nov 17, 2012 at 15:24
  • 1
    $\begingroup$ That's not the meaning of lazy. Lazy is doing this by hand repeatedly until someone else wrote searchMessages for me... :^) $\endgroup$
    – Mr.Wizard
    Nov 17, 2012 at 16:34
  • $\begingroup$ @Mr.Wizard ... or for me. Now I feel the shame... :) $\endgroup$ Nov 18, 2012 at 14:36
6
$\begingroup$

We can scan the messages that have been loaded into the current session like this:

messages[pattern_, context_:"*"] :=
  Cases[
    Quiet[ToExpression[#, InputForm, Messages]& /@ Names[context~~"*"], General::readp]
  , (_[n_] :> m_String) /; !StringFreeQ[m, pattern, IgnoreCase -> True] :> HoldForm@n :> m
  , {2}
  ]

messages["arguments", "System`"]
(*
{General::bldim:>The arguments `1` and `2` in `3` do not have compatible dimensions.}
*)

messages["longer"]
(*
{General::partd:>Part specification `1` is longer than depth of object.,
 Part::partd:>Part specification `1` is longer than depth of object.}
*)

The emphasis here is on loaded messages. This method will not find any messages in packages that have not yet been loaded. Also beware that some packages load symbols (and their messages) lazily, on demand.

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