防止 Mathematica 中出现大量运行时错误 [英] Preventing avalanche of runtime errors in Mathematica

查看:43
本文介绍了防止 Mathematica 中出现大量运行时错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当笔记本超出几个功能时我遇到的典型情况——我评估一个表达式,但我得到的不是正确答案Beep,然后是几十个无用的警告,然后是进一步的输出的……会被压制"

A typical situation I run into when notebook grows beyond a couple of functions -- I evaluate an expression, but instead of correct answer I get Beep followed by dozens of useless warnings followed by "further Output of ... will be suppressed"

我发现有用的一件事——在函数内部使用类似 Python 的断言"来强制内部一致性.还有什么提示吗?

One thing I found useful -- use Python-like "assert" inside functions to enforce internal consistency. Any other tips?

Assert[expr_, msg_] := If[Not[expr], Print[msg]; Abort[], None]

编辑 11/14警告雪崩的一般原因是当子表达式评估为坏"值时.这会导致父表达式评估为坏"值,并且这种坏"一直传播到根.沿途评估的内置程序会注意到不良情况并产生警告.坏"可能意味着一个带有错误 Head 的表达式、带有错误元素数量的列表、负定矩阵而不是正定矩阵等.通常它不符合父表达式的语义.

edit 11/14 A general cause of a warning avalanche is when a subexpression evaluates to "bad" value. This causes the parent expression to evaluate to a "bad" value and this "badness" propagates all the way to the root. Built-ins evaluated along the way notice the badness and produce warnings. "Bad" could mean an expression with wrong Head, list with wrong number of elements, negative definite matrix instead of positive definite, etc. Generally it's something that doesn't fit in with the semantics of the parent expression.

处理这个问题的一种方法是重新定义所有函数,以在错误输入"时返回未评估的值.这将处理由内置程序生成的大多数消息.执行零件"等结构操作的内置函数仍会尝试评估您的值,并可能产生警告.

One way do deal with this is to redefine all your functions to return unevaluated on "bad input." This will take care of most messages produced by built-ins. Built-ins that do structural operations like "Part" will still attempt to evaluate your value and may produce warnings.

将调试器设置为中断消息"可以防止大量错误,尽管一直打开它似乎有点矫枉过正

Having the debugger set to "break on Messages" prevents an avalanche of errors, although it seems like an overkill to have it turned on all the time

推荐答案

正如其他人所指出的,可以通过三种方式以一致的方式处理错误:

As others have pointed out, there are three ways to deal with errors in a consistent manner:

  1. 正确输入参数并设置函数运行的条件,
  2. 正确且一致地处理所产生的错误,以及
  3. 简化应用这些步骤的方法.

正如 Samsdram 指出的那样,正确键入您的函数会有很大帮助.不要忘记 : 形式的 Pattern 因为有时用这种形式表达一些模式更容易,例如x:{{_, _} ..}.显然,当这还不够 PatternTests (?) 和 Conditions (/;) 是要走的路.Samdram 很好地涵盖了这一点,但我想补充一点,您可以通过纯函数创建自己的模式测试,例如f[x_?(Head[#]===List&)] 等价于 f[x_List].请注意,使用纯函数的&符号形式时,括号是必需的.

As Samsdram pointed out, correctly typing your functions will help a great deal. Don't forget about the : form of Pattern as it is sometimes easier to express some patterns in this form, e.g. x:{{_, _} ..}. Obviously, when that isn't sufficient PatternTests (?) and Conditions (/;) are the way to go. Samdram covers that pretty well, but I'd like to add that you can create your own pattern test via pure functions, e.g. f[x_?(Head[#]===List&)] is equivalent to f[x_List]. Note, the parentheses are necessary when using the ampersand form of pure functions.

处理产生的错误的最简单方法显然是Off,或者更本地化安静.在大多数情况下,我们都同意完全关闭我们不想要的消息是一个坏主意,但是 Quiet 在您知道自己正在做的事情会产生投诉,但在其他方面是正确的.

The simplest way to deal with errors generated is obviously Off, or more locally Quiet. For the most part, we can all agree that it is a bad idea to completely shut off the messages we don't want, but Quiet can be extremely useful when you know you are doing something that will generate complaints, but is otherwise correct.

ThrowCatch 有它们的位置,但我觉得它们应该只在内部使用,并且您的代码应该通过 Message 设施.可以以与设置使用消息相同的方式创建消息.我相信可以使用函数 检查CheckAbort, AbortProtect.

Throw and Catch have their place, but I feel they should only be used internally, and your code should communicate errors via the Message facilities. Messages can be created in the same manner as setting up a usage message. I believe the key to a coherent error strategy can be built using the functions Check, CheckAbort, AbortProtect.

我的代码中的一个示例是 OpenAndRead,它可以防止在中止读取操作时离开打开的流,如下所示:

An example from my code is OpenAndRead which protects against leaving open streams when aborting a read operation, as follows:

OpenAndRead[file_String, fcn_]:=
Module[{strm, res},
  strm = OpenRead[file];
  res = CheckAbort[ fcn[strm], $Aborted ];
  Close[strm];
  If[res === $Aborted, Abort[], res] (* Edited to allow Abort to propagate *)
]

直到最近才有使用

fcn[ file_String, <otherparams> ] := OpenAndRead[file, fcn[#, <otherparams>]&]
fcn[ file_InputStream, <otherparams> ] := <fcn body>

然而,每次都这样做很烦人.

However, this is annoying to do every time.

这是 belisarius 解决方案发挥作用的地方,通过创建可以一致使用的方法.不幸的是,他的解决方案有一个致命的缺陷:你失去了对语法高亮功能的支持.所以,这是我想出的一种替代方法,用于从上面挂接 OpenAndRead

This is where belisarius solution comes into play, by creating a method that you can use consistently. Unfortunately, his solution has a fatal flaw: you lose support of the syntax highlighting facilities. So, here's an alternative that I came up with for hooking into OpenAndRead from above

MakeCheckedReader /: 
    SetDelayed[MakeCheckedReader[fcn_Symbol, symbols___], a_] :=
    Quiet[(fcn[file_String, symbols] := OpenAndRead[file, fcn[#, symbols] &];
           fcn[file_Symbol, symbols] := a), {RuleDelayed::"rhs"}]

有用途

MakeCheckedReader[ myReader, a_, b_ ] := {file$, a, b} (*as an example*)

现在,检查 myReader 的定义会给出两个定义,就像我们想要的那样.但是,在函数体中,file 必须被称为 file$.(我还没有想出如何按照我的意愿命名文件 var.)

Now, checking the definition of myReader gives two definitions, like we want. In the function body, though, file must be referred to as file$. (I have not yet figured out how to name the file var as I'd wish.)

编辑:MakeCheckedReader 本身实际上并不做任何事情.相反,TagSet (/:) 规范告诉 Mathematica,当在 SetDelayed 的 LHS 上找到 MakeCheckedReader 时,将其替换为所需的函数定义.另外,请注意 Quiet 的使用;否则,它会抱怨出现在等式右侧的模式 a_b_.

Edit: MakeCheckedReader works by not actually doing anything itself. Instead, the TagSet (/:) specification tells Mathematica that when MakeCheckedReader is found on the LHS of a SetDelayed then replace it with the desired function definitions. Also, note the use of Quiet; otherwise, it would complain about the patterns a_ and b_ appearing on the right side of the equation.

编辑 2:Leonid 指出了如何能够使用 file 不是 file$ 定义已检查的阅读器时.更新后的解决方案如下:

Edit 2: Leonid pointed out how to be able to use file not file$ when defining a checked reader. The updated solution is as follows:

MakeCheckedReader /: 
    SetDelayed[MakeCheckedReader[fcn_Symbol, symbols___], a_] :=
    Quiet[(fcn[file_String, symbols] := OpenAndRead[file, fcn[#, symbols] &];
           SetDelayed @@ Hold[fcn[file_Symbol, symbols], a]), 
           {RuleDelayed::"rhs"}]

更改的原因在此中进行了解释回答他的.定义myReader,如上,并检查其定义,我们得到

The reasoning for the change is explained in this answer of his. Defining myReader, as above, and checking its definition, we get

myReader[file$_String,a_,b_]:=OpenAndRead[file$,myReader[#1,a_,b_]&]
myReader[file_Symbol,a_,b_]:={file,a,b}

这篇关于防止 Mathematica 中出现大量运行时错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆