gpt4 book ai didi

debugging - 如何查找 Mathematica 笔记本中发生错误的行?

转载 作者:行者123 更新时间:2023-12-03 06:28:21 26 4
gpt4 key购买 nike

我有一个名为 myUsefulFunctions.m 的 Mathematica 文件,其中包含一个名为 mySuperUsefulFunction 的函数。假设我在笔记本中调用 mySuperUsefulFunction 并收到以下错误:

Part::pspec: Part specification #1 is neither an integer nor a list of integers. >>

有没有办法找到 myUsefulFunctions.m 中发生此错误的行?

最佳答案

轻量级调试功能

除了其他建议之外,这里有一个功能对我有过几次帮助:

ClearAll[debug];
SetAttributes[debug, HoldAll];
debug[code_] :=
Internal`InheritedBlock[{Message},
Module[{inMessage},
Unprotect[Message];
Message[args___] /; ! MatchQ[First[Hold[args]], _$Off] :=
Block[{inMessage = True},
Print[{
Shallow /@ Replace[#, HoldForm[f_[___]] :> HoldForm[f], 1],
Style[Map[Short, Last[#], {2}], Red]
} &@Drop[Drop[Stack[_], -7], 4]
];
Message[args];
Throw[$Failed, Message];
] /; ! TrueQ[inMessage];
Protect[Message];
];
Catch[StackComplete[code], Message]]

这基本上临时重新定义了 Message 来遍历执行堆栈并以易于理解的形式打印被调用函数的名称,以及导致错误消息的最终调用和错误消息本身。之后,我们通过异常退出执行,以免生成令人困惑的错误消息链。

使用示例

以下是 @Mr.Wizard 答案中的示例的工作原理:

In[211]:= debug[myFunc2[Range@10,#1]]

During evaluation of In[211]:=
{{myFunc2,Pick,myFunc1,Part},{1,2,3,4,5,6,7,8,9,10}[[#1]]}

During evaluation of In[211]:= Part::pspec: Part specification #1 is neither
an integer nor a list of integers. >>

Out[211]= $Failed

(在笔记本中,有问题的函数调用被涂成红色)。这允许人们快速查看导致问题的函数调用链。

这是另一个例子:我们构造一个自定义的 gatherBy 函数,它根据另一个“标记”列表收集列表中的元素,该列表的长度应该与原始列表的长度相同:

listSplit[x_, lengths_] := 
MapThread[Take[x, {##}] &, {Most[#], Rest[#] - 1}] &@
Accumulate[Prepend[lengths, 1]];

gatherBy[lst_, flst_] :=
listSplit[lst[[Ordering[flst]]], (Sort@Tally[flst])[[All, 2]]];

例如:

In[212]:= gatherBy[Range[10],{1,1,2,3,2,4,5,5,4,1}]
Out[212]= {{1,2,10},{3,5},{4},{6,9},{7,8}}

因为我故意忽略了所有类型检查,所以使用错误类型参数的调用将导致一系列令人讨厌的错误消息:

In[213]:= gatherBy[Range[10],Range[15]]//Short
During evaluation of In[206]:= Part::partw: Part 11 of {1,2,3,4,5,6,7,8,9,10} does not exist. >>

(* 4 more messages here *)
Out[213]//Short= {{1,2,3,4,5,6,7,8,9,10},<<14>>}

使用debug,我们可以很快看到问题所在:

In[214]:= debug[gatherBy[Range[10],Range[15]]]

During evaluation of In[214]:=
{{gatherBy,listSplit,Part},
{1,2,3,4,5,6,7,8,9,10}[[Ordering[{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}]]]}

During evaluation of In[214]:= Part::partw: Part 11 of {1,2,3,4,5,6,7,8,9,10} does not exist. >>

Out[214]= $Failed

使用一些符号 a 调用 gatherBy[Range[10], a] 是包装 debug 有所帮助的另一个示例。

适用性

其他建议的方法更加系统化,可能更普遍推荐,但是这个方法很容易应用,并且产生的结果通常更容易理解(例如,与 Trace 的输出相比,并不总是容易阅读)。然而,我并没有经常使用它来保证它总是有效。

关于debugging - 如何查找 Mathematica 笔记本中发生错误的行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8362170/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com