4

ドキュメンテーションpageには、次のように記載されGeneral::stopています。

このメッセージは、示されたメッセージが1 回の評価で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]

Messageの評価と同じ数のパケットを取得しますf[z]。もちろんGeneral::stop、同じメッセージを 3 回生成した後、スレーブ カーネルでメッセージの生成を停止させたいと考えています。これを達成する方法はありますか?

のドキュメントページで、$MessageListそれを読みました

標準のMathematicaメインループでは、特定の入力行の処理が完了すると $MessageList が {} にリセットされます。

そして、tutorial/Messages私たちが読んだページで:

実行するすべての計算で、 Mathematicaは生成されるすべてのメッセージのリスト $MessageList を維持します。標準Mathematicaセッションでは、このリストは出力の各行が生成されるたびにクリアされます。

General::stopこれが表示されない理由でしょうか?それが本当なら、メイン ループのこの側面を制御する方法はありますか? このような非標準のMathematicaセッションを作成する方法はありますか?

編集: 私の推測は正しかったようです。$MessageListすべてのメッセージの後にクリアすると、General::stop表示されなくなります。

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

出力を生成した後に自動クリアを無効にする方法は$MessageList?

4

2 に答える 2

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

于 2011-03-02T11:40:56.867 に答える
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;

:)

于 2011-03-03T16:15:12.200 に答える