我正在开发一个(大)包,它不再正确加载。这发生在我更改了一行代码之后。当我尝试加载包(需要)时,包开始加载,然后其中一个 setdelayed 定义“激活”(即以某种方式评估),被困在一个错误捕获例程中,之前加载了几行,包加载中止。
带有 abort 的错误捕获例程正在完成它的工作,只是它不应该在包加载阶段首先被调用。错误消息表明,错误的参数实际上是我在几行之后在 setdelayed 定义的 lhs 上使用的模式表达式。
像这样的东西:
……Some code lines
Changed line of code
g[x_?NotGoodQ]:=(Message[g::nogood, x];Abort[])
……..some other code lines
g/: cccQ[g[x0_]]:=True
当我尝试加载包时,我得到:
g::nogood: Argument x0_ is not good
如您所见,传递的参数是一种模式,它只能来自上面的代码行。
我试图找到这种行为的原因,但到目前为止我一直没有成功。所以我决定使用强大的 Workbench 调试工具。
我想逐步(或使用断点)查看加载包时会发生什么。我对 WB 还不太熟悉,但似乎使用 Debug as……,首先加载包,然后最终用断点等进行调试。我的问题是包甚至没有完全加载!并且在加载包之前设置的任何断点似乎都不起作用。
所以……2个问题:
- 谁能解释为什么这些代码行在包加载过程中“活跃起来”?(据我所知,包中没有明显的语法错误或代码片段)
- 谁能解释一下(如果)在加载到 WB 时如何检查/调试包代码?
感谢您的任何帮助。
编辑
根据 Leonid 的回答并使用他的 EvenQ 示例:我们可以Holdpattern
通过在 g 的向下值之前为 g 定义向上值来避免使用
notGoodQ[x_] := EvenQ[x];
Clear[g];
g /: cccQ[g[x0_]] := True
g[x_?notGoodQ] := (Message[g::nogood, x]; Abort[])
现在
?g
Global`g
cccQ[g[x0_]]^:=True
g[x_?notGoodQ]:=(Message[g::nogood,x];Abort[])
In[6]:= cccQ[g[1]]
Out[6]= True
尽管
In[7]:= cccQ[g[2]]
During evaluation of In[7]:= g::nogood: -- Message text not found -- (2)
Out[7]= $Aborted
所以...一般规则:
编写函数 g 时,首先为 g 定义上值,然后为 g 定义下值,否则使用Holdpattern
你能订阅这个规则吗?
列昂尼德说,使用Holdpattern
可能表明可改进的设计。除了上面指出的解决方案之外,如何改进上面的小代码的设计,或者更好的是,一般来说,在处理 upvalues 时?
感谢您的帮助