Wolfram mathematica Mathematica作业中不需要的评估:为什么会发生,以及如何在包加载期间调试?

Wolfram mathematica Mathematica作业中不需要的评估:为什么会发生,以及如何在包加载期间调试?,wolfram-mathematica,workbench,Wolfram Mathematica,Workbench,我正在开发一个(大)包,它不能再正常加载了。 这是在我更改了一行代码之后发生的。 当我尝试加载包(带有需求)时,包开始加载,然后其中一个setdelayed定义“变得活跃”(即,以某种方式被评估),被困在前几行加载的错误捕获例程中,包加载中止。 带有abort的错误捕获例程正在执行它的工作,只是在包加载阶段不应该首先调用它。 错误消息显示错误的参数实际上是一个模式表达式,几行之后我在setdelayed定义的lhs上使用了它 大概是这样的: ……Some code lines Changed

我正在开发一个(大)包,它不能再正常加载了。 这是在我更改了一行代码之后发生的。 当我尝试加载包(带有需求)时,包开始加载,然后其中一个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
Clear[g,notGoodQ];
notGoodQ[x_]:=EvenQ[x];
g[x_?notGoodQ]:=(Message[g::nogood,x];Abort[])
g/:cccQ[HoldPattern[g[x0_]]]:=True;
当我尝试加载包时,我得到:

g::nogood: Argument x0_ is not good
正如您所看到的,传递的参数是一种模式,它只能来自上面的代码行

我试图找出这种行为的原因,但到目前为止我一直没有成功。 所以我决定使用功能强大的工作台调试工具

我想一步一步地(或通过断点)看看加载包时会发生什么。 我还不太熟悉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时,首先为g定义UpValue,然后为g定义DownValue,否则使用
    Holdpattern

    你能遵守这条规则吗

    Leonid说使用
    Holdpattern
    可能意味着可以改进设计。除了上面提到的解决方案外,如何改进上面的小代码的设计,或者更好地说,在处理upvalues时,如何改进一般代码的设计

    感谢您的帮助

    抛开WB(回答您的问题并不真正需要WB)-这个问题似乎只有一个简单的答案,即仅基于作业期间表达式的计算方式。以下是一个例子:

    In[1505]:= 
    notGoodQ[x_]:=True;
    Clear[g];
    g[x_?notGoodQ]:=(Message[g::nogood,x];Abort[])
    
    In[1509]:= g/:cccQ[g[x0_]]:=True
    
    During evaluation of In[1509]:= g::nogood: -- Message text not found -- (x0_)
    Out[1509]= $Aborted
    
    In[1513]:= 
    ClearAll[h,f];
    h[___]:=Print["Evaluated"];
    
    In[1515]:= h/:f[h[1,2]]:=3
    
    During evaluation of In[1515]:= Evaluated
    During evaluation of In[1515]:= TagSetDelayed::tagnf: Tag h not found in f[Null]. >>
    Out[1515]= $Failed  
    
    为了让它工作,我特意为
    notGoodQ
    定义了一个总是返回
    True
    。现在,为什么在分配期间通过
    TagSetDelayed
    g[x0\ux0]
    进行评估?答案是,虽然作业
    h/:f[h[elem1,…,elemn]]:=…
    中的
    TagSetDelayed
    (以及
    SetDelayed
    )没有应用
    f
    可能具有的任何规则,但它将计算
    h[elem1,…,elem2]
    ,以及
    f
    。以下是一个例子:

    In[1505]:= 
    notGoodQ[x_]:=True;
    Clear[g];
    g[x_?notGoodQ]:=(Message[g::nogood,x];Abort[])
    
    In[1509]:= g/:cccQ[g[x0_]]:=True
    
    During evaluation of In[1509]:= g::nogood: -- Message text not found -- (x0_)
    Out[1509]= $Aborted
    
    In[1513]:= 
    ClearAll[h,f];
    h[___]:=Print["Evaluated"];
    
    In[1515]:= h/:f[h[1,2]]:=3
    
    During evaluation of In[1515]:= Evaluated
    During evaluation of In[1515]:= TagSetDelayed::tagnf: Tag h not found in f[Null]. >>
    Out[1515]= $Failed  
    
    TagSetDelayed
    HoldAll
    这一事实并不意味着它不计算它的参数-它只意味着参数到达它时没有计算,它们是否会被计算取决于
    TagSetDelayed
    的语义(我在上面简要描述过)。这同样适用于
    SetDelayed
    ,因此常用的语句“不计算其参数”在字面上是不正确的。更正确的说法是,它接收未计算的参数,并以一种特殊的方式计算它们——不计算r.h.s,而对于l.h.s,计算head和元素,但不为head应用规则。为了避免这种情况,您可以将内容包装在
    HoldPattern
    中,如下所示:

    ……Some code lines
    
    Changed line of code 
    
    g[x_?NotGoodQ]:=(Message[g::nogood, x];Abort[])
    
    ……..some other code lines
    
    g/: cccQ[g[x0_]]:=True
    
    Clear[g,notGoodQ];
    notGoodQ[x_]:=EvenQ[x];
    g[x_?notGoodQ]:=(Message[g::nogood,x];Abort[])
    g/:cccQ[HoldPattern[g[x0_]]]:=True;
    
    这件事过去了。以下是一些用法:

    In[1527]:= cccQ[g[1]]
    Out[1527]= True
    
    In[1528]:= cccQ[g[2]]
    During evaluation of In[1528]:= g::nogood: -- Message text not found -- (2)
    Out[1528]= $Aborted
    
    但是请注意,在进行定义时,左手边需要
    HoldPattern
    ,这通常是一个信号,表明在函数调用过程中,头部的表达式也可能会求值,这可能会破坏代码。以下是我的意思的一个例子:

    In[1532]:= 
    ClearAll[f,h];
    f[x_]:=x^2;
    f/:h[HoldPattern[f[y_]]]:=y^4;
    
    此代码试图捕获像
    h[f[something]]
    这样的情况,但显然会失败,因为
    f[something]
    将在计算到
    h
    之前进行计算:

    In[1535]:= h[f[5]]
    Out[1535]= h[25]
    
    对我来说,l.h.s.需要
    HoldPattern
    ,这表明我需要重新考虑我的设计

    编辑

    关于在WB中加载期间的调试,您可以做的一件事(IIRC,现在不能检查)是使用良好的旧打印语句,其输出将显示在WB的控制台中。就我个人而言,我很少觉得有必要为此使用调试器(加载时调试包)

    编辑2

    针对问题中的编辑:

    关于定义的顺序:是的,你可以这样做,它解决了这个特殊的问题。但是,一般来说,这是不健全的,我不认为这是一个好的一般方法。对于手头的案件很难给出明确的建议,因为它有点脱离上下文,但在我看来,这里使用
    UpValues
    是不合理的。如果这是为了错误处理而做的,那么就不需要使用
    UpValues

    通常,
    UpValues
    最常用于以安全的方式重载某些函数,而不向重载的函数添加任何规则。一个建议是避免将
    UpValues
    与同样具有
    DownValues
    且可能进行评估的头部相关联-这样做,您就开始与evaluator玩游戏,最终将失败。最安全的方法是将
    upvalue
    附加到惰性符号上(he