改变General :: stop和主循环的行为

时间:2011-03-02 05:04:59

标签: wolfram-mathematica mathlink

General::stop的{​​{3}}文档中,我们读到了:

  

此消息是在生成之后生成的   指示的消息已生成   第三次在一个单一的   评价即可。

     

消息被抑制   防止多余或重复   长时间计算中的消息。

我的问题是,在MathLink工作时,我将每一点作为单一评估传递,因此General::stop永远不会出现。

例如,如果我定义:

link = LinkLaunch[First[$CommandLine] <> " -mathlink"]
f[z_?NumericQ] := (Print@LinkRead[link]; 
   LinkWrite[link, 
    Unevaluated[
     EnterExpressionPacket[NIntegrate[Sin[1/x], {x, .001, z}]]]]; 
   While[Head[packet = LinkRead[link]] =!= OutputNamePacket, 
    Print[packet]]; First@LinkRead[link]);
Plot[f[z], {z, 1, 10}, PlotPoints -> 6, MaxRecursion -> 0]

我获得Messagef[z]General::stop个数据包。当然,我希望在生成相同的消息3次之后,$MessageList在从属内核中停止消息生成。有没有办法实现这个目标?

tutorial/Messages的文档页面上,我们读到了

  

使用标准 Mathematica main   循环,$ MessageList重置为{}时   处理特定输入   线已经完成。

在页面General::stop上我们读到了:

  

在你做的每一次计算中,    Mathematica 维护一个列表   所有消息的$ MessageList   生产。   在标准 Mathematica 会话中,   每行后清除此列表   输出的产生。

这可能是$MessageList没有出现的原因吗?如果确实有办法控制主循环的这个方面?有没有办法创建这样的非标准 Mathematica 会话?

修改 似乎我的假设是正确的。如果我们在每封邮件之后清除General::stop,则Unprotect[$MessageList] Do[$MessageList = {}; 1/0, {10}] 永远不会出现:

$MessageList

所以问题仍然存在:如何在生成输出后禁用自动清除{{1}}?

2 个答案:

答案 0 :(得分:1)

可能有更好的解决方案,但这里似乎有效。据我所知,重要的是你在奴隶内核中有一些累积消息的持久变量。

link = LinkLaunch[First[$CommandLine] <> " -mathlink"]
f[z_?NumericQ] := 
(Print@LinkRead[link];
LinkWrite[link, Unevaluated[EnterExpressionPacket[
  If[! ValueQ[oldMessageList], oldMessageList = {}];
  Block[{$MessageList = oldMessageList},
   Module[{result},
    oldMessageList  = 
     Join[oldMessageList, (result = 
        NIntegrate[Sin[1/x], {x, .001, z}]; $MessageList)];
    result
    ]]]]];
While[Head[packet = LinkRead[link]] =!= OutputNamePacket, 
Print[packet]]; First@LinkRead[link]);

Plot[f[z], {z, 1, 10}, PlotPoints -> 6, MaxRecursion -> 0]

HTH

答案 1 :(得分:0)

我找到了解决方案。它再次利用elegant hack by Todd Gayley。这是(当然,它必须在从属内核中进行评估):

$globalMessageList = {};
Unprotect[Message];
Message[args___] := 
  Block[{$inMsg = True, $MessageList = $globalMessageList},
    Message[args];
    $globalMessageList = $MessageList;
    ] /; ! TrueQ[$inMsg];
Protect[Message];

通过检查$Line的当前值并将其与之前的值进行比较,可以完全模拟从属内核中消息的标准行为:

If[TrueQ[$Line > lastLine], 
 LinkWrite[$kern, 
  Unevaluated[ExpressionPacket[$globalMessageList = {};]]]; 
 LinkRead[$kern]]; lastLine = $Line;

:)