Wolfram mathematica 防止Mathematica中运行时错误的雪崩
我遇到的一个典型情况是,当笔记本电脑超出了几个函数时——我计算一个表达式,但没有得到正确的答案,而是发出嘟嘟声,然后是几十个无用的警告,接着是“进一步输出的…将被抑制” 我发现有一件事很有用——在函数中使用类似Python的“assert”来增强内部一致性。还有其他建议吗Wolfram mathematica 防止Mathematica中运行时错误的雪崩,wolfram-mathematica,Wolfram Mathematica,我遇到的一个典型情况是,当笔记本电脑超出了几个函数时——我计算一个表达式,但没有得到正确的答案,而是发出嘟嘟声,然后是几十个无用的警告,接着是“进一步输出的…将被抑制” 我发现有一件事很有用——在函数中使用类似Python的“assert”来增强内部一致性。还有其他建议吗 Assert[expr_, msg_] := If[Not[expr], Print[msg]; Abort[], None] 编辑11/14 警告雪崩的一般原因是子表达式的计算结果为“坏”值。这会导致父表达式的计算结果为“
Assert[expr_, msg_] := If[Not[expr], Print[msg]; Abort[], None]
编辑11/14
警告雪崩的一般原因是子表达式的计算结果为“坏”值。这会导致父表达式的计算结果为“坏”值,并且这种“坏”会一直传播到根。一路上经过评估的内置程序会注意到问题并发出警告。“Bad”可能意味着一个头部错误的表达式、元素数量错误的列表、负定矩阵而不是正定矩阵等。通常,它与父表达式的语义不符
解决这个问题的一种方法是重新定义所有函数,以返回未计算的“错误输入”。这将处理由内置生成的大多数消息。执行“部件”等结构操作的内置程序仍将尝试评估您的值,并可能产生警告
将调试器设置为“消息中断”可以防止错误雪崩,尽管始终打开调试器似乎是一种过火的行为这里的问题本质上是一种类型。一个函数产生一个错误的输出(不正确的类型),然后输入到许多后续函数中,产生大量错误。虽然Mathematica不像其他语言那样有用户定义的类型,但您可以对函数参数进行模式匹配,而无需做太多工作。如果匹配失败,函数将不计算,因此不会发出错误的蜂鸣音。语法的关键部分是“/”,它位于一些代码的末尾,然后是测试。一些示例代码(输出如下) 如果测试更简单,则有另一个符号执行类似的模式测试“?”并紧跟在模式/函数声明中的参数之后。另一个例子如下
Input:
Average[x_] := Mean[x] /; VectorQ[x, NumericQ]
Average[{1, 2, 3}]
Average[$Failed]
Output:
2
Average[$Failed]
Input:
square[x_?NumericQ] := x*x
square[{1, 2, 3}]
square[3]
Output:
square[{1, 2, 3}]
9
它可以帮助定义一个catchall定义,以获取错误条件并以有意义的方式报告它:
f[x_?NumericQ] := x^2;
f[args___] := Throw[{"Bad Arguments: ", Hold[f[args]]}]
因此,您的顶级呼叫可以使用Catch[],也可以让它冒泡:
In[5]:= f[$Failed]
During evaluation of In[5]:= Throw::nocatch: Uncaught Throw[{Bad Args: ,Hold[f[$Failed]]}] returned to top level. >>
Out[5]= Hold[Throw[{"Bad Args: ", Hold[f[$Failed]]}]]
我希望得到的是一种方法,可以定义一个通用过程来捕获错误传播,而无需立即彻底改变我编写函数的方式,尤其是不添加大量类型 下面是一个尝试:
funcDef = t_[args___] :c-: a_ :> ReleaseHold[Hold[t[args] :=
Check[a, Print@Hold[a]; Abort[]]]];
Clear@v;
v[x_, y_] :c-: Sin[x/y] /. funcDef;
?v
v[2, 3]
v[2, 0]
:c-:当然是Esc c-Esc,一个未使用的符号(\[CircleMinus]),但任何人都会这样做
输出:
Global`v
v[x_,y_]:=Check[Sin[x/y],Print[Hold[Sin[x/y]]];Abort[]]
Out[683]= Sin[2/3]
During evaluation of In[679]:= Power::infy: Infinite expression 1/0 encountered. >>
During evaluation of In[679]:= Hold[Sin[2/0]]
Out[684]= $Aborted
我们改变的是
v[x_, y_] := Sin[x/y]
借
这几乎满足了我的前提
编辑
也许为函数添加一个“裸”定义也很方便,它不需要进行错误检查。我们可以将funcDef规则更改为:
funcDef =
t_[args___] \[CircleMinus] a_ :>
{t["nude", args] := a,
ReleaseHold[Hold[t[args] := Check[a, Print@Hold[a]; Abort[]]]]
};
争取
v[x_, y_] :c-: Sin[x/y] /. funcDef;
这个输出
v[nude,x_,y_]:=Sin[x/y]
v[x_,y_]:=Check[Sin[x/y],Print[Hold[Sin[x/y]]];Abort[]]
正如其他人所指出的,有三种方法可以一致地处理错误:
:
形式,因为用这种形式表达某些模式有时更容易,例如x:{{{{{,}..}
。显然,当这还不够时,PatternTest
s()和Condition
s()是一种方法。Samdram很好地涵盖了这一点,但我想补充一点,您可以通过纯函数创建自己的模式测试,例如f[x#?(Head[#]==List&]
相当于f[x#List]
。注意,当使用纯函数的符号和形式时,括号是必要的
处理生成的错误的最简单方法显然是关闭,或者更局部地关闭。在大多数情况下,我们都同意完全关闭我们不想要的消息是一个坏主意,但是当你知道你正在做的事情会引起抱怨,但在其他方面是正确的时,Quiet
非常有用
Throw
和Catch
有它们的位置,但我觉得它们应该只在内部使用,您的代码应该通过设施来传达错误。创建消息的方式与设置使用情况消息的方式相同。我相信连贯错误策略的关键可以使用函数来构建
例子
我的代码中的一个示例是OpenAndRead
,它可以在中止读取操作时防止离开打开的流,如下所示:
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 *)
]
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"}]
直到最近,它还具有
fcn[ file_String, <otherparams> ] := OpenAndRead[file, fcn[#, <otherparams>]&]
fcn[ file_InputStream, <otherparams> ] := <fcn body>
哪个有用法
MakeCheckedReader[ myReader, a_, b_ ] := {file$, a, b} (*as an example*)
现在,检查myReader
的定义会给出两个定义,就像我们想要的那样。但是,在函数体中,文件
必须称为文件$
。(我还没有想出如何按照我的意愿命名文件var。)
Edit:MakeCheckedReader
本身不做任何事情。相反,TagSet
()规范告诉Mathematica,当在SetDelayed
的LHS上找到MakeCheckedReader
时,用所需的函数定义替换它。另外,请注意使用的Quiet
;否则,它会抱怨出现在等式右侧的模式a
和b
编辑2:指出了在定义选中的读取器时如何能够使用文件
而不是文件$
。更新后的解决方案如下:
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 *)
]
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
,并检查其定义,我们得到
myReader[file$_String,a_,b_]:=OpenAndRead[file$,myReader[#1,a_,b_]&]
myReader[file_Symbol,a_,b_]:={file,a,b}
我在晚会上迟到了,我有一个公认的答案和一个很好的回答
f[...] := Module[... /; ...]
data = {{0, 1}, {1, 2}, {2, 4}, {3, 8}, {4, 15}, {5, 29}, {6, 50}, {7,
88}, {8, 130}, {9, 157}, {10, 180}, {11, 191}, {12, 196}, {13,
199}, {14, 200}};
f0[x_] := First @ Cases[data, {t_, p_} /; p >= x :> t, {1}, 1]
f0[100] (* returns 8 *)
f0[1000]
error: First::first: {} has a length of zero and no first element.
f1[x_] := Cases[data, {t_, p_} /; p >= x :> t, {1}, 1]
f1[100] (* returns {8} *)
f1[1000] (* returns {} *)
f2[x_] :=
Module[{m},
m = Cases[data, {t_, p_} /; p >= x :> t, {1}, 1];
First[m] /; m =!= {}
]
f2[100] (* returns 8 *)
f2[1000] (* returns f2[1000] *)
f2[x_] := Null /; Message[f2::err, x]
f2::err = "Could not find a value for ``.";
f2[x_] := (Message[f2::err, x]; Abort[])
Clear[f]
f[x_] := ...
f[x_] := Module[... /; ...]
f[x_] := ... /; ...