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

发布于 2024-10-20 00:34:10 字数 1703 浏览 3 评论 0原文

在文档 页面 上 < code>General::stop 我们读到:

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

消息被抑制 以防止冗余或重复 长计算中的消息。

我的问题是,在处理 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]

我会收到与 f[z] 的评估一样多的 Message 数据包。当然,我希望在生成相同消息 3 次后,通过 General::stop 在从属内核中停止消息生成。有办法实现这一点吗?

$MessageList 的文档页面上,我们读到

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

tutorial/Messages页面上我们读到:

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

这可能是 General::stop 不出现的原因吗?如果这是真的,有没有办法控制主循环的这方面?有没有办法创建这样一个非标准的 Mathematica 会话?

编辑: 看来我的猜测是对的。如果我们在每条消息后清除 $MessageList ,则 General::stop 永远不会出现:

Unprotect[$MessageList]
Do[$MessageList = {}; 1/0, {10}]

所以问题仍然是:如何禁用自动清除 $MessageList > 生成输出后?

On the Documentation page for General::stop we read:

This message is generated after the
indicated message has been generated
for the third time in a single
evaluation
.

Messages are suppressed
to prevent redundant or repetitive
messages in long calculations.

My problem is that when working through MathLink I pass every point as a single evaluation and so General::stop never appears.

For example, if I define:

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]

I get as many Message packets as many evaluations of f[z]. Of course I would like message generarion to be stopped in the slave kernel by General::stop after generating the same message 3 times. Is there a way to achieve this?

On the documentation page for $MessageList we read that

With the standard Mathematica main
loop, $MessageList is reset to {} when
the processing of a particular input
line is complete.

And on the page tutorial/Messages we read:

In every computation you do,
Mathematica maintains a list
$MessageList of all the messages that
are produced.
In a standard Mathematica session,
this list is cleared after each line
of output is generated.

May be this is a reason why General::stop does not appear? If it is true is there a way to control this aspect of the Main Loop? Is there a way to create such a non-standard Mathematica session?

EDIT:
It seems that my supposition was right. If we will clear $MessageList after every Message, then General::stop never appears:

Unprotect[$MessageList]
Do[$MessageList = {}; 1/0, {10}]

So the question remains: how to disable automatic clearing $MessageList after generating output?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

亽野灬性zι浪 2024-10-27 00:34:11

可能有更好的解决方案,但这里有一个似乎有效的解决方案。据我了解,重要的是在从属内核中有一些持久变量来累积消息。

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]

华泰

There are probably better solutions, but here is one that seems to work. As far as I understand, all that matters is that you have some persistent variable in the slave kernel that accumulates messages.

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

淡紫姑娘! 2024-10-27 00:34:11

我已经找到了解决方案。它再次利用了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;

:)

I have found the solution. It exploites again elegant hack by Todd Gayley. Here it is (of course, it must be evaluated in the slave kernel):

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

One can fully emulate standard behavior of Messages in the slave kernel by checking the current value of $Line and comparing it with previous value:

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

:)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文