Changing the behavior of General :: stop and the main loop

In the page documentation for General::stop we read:

This message is generated after the specified message was created a third time in one rating .

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

My problem is that when working through MathLink I pass each point as a single assessment and therefore 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 f[z] ratings. Of course, I would like the message generator to be stopped in the slave kernel of General::stop after generating the same message 3 times. Is there any way to achieve this?

On the documentation page for $MessageList we read that

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

And on the tutorial/Messages page we read:

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

Maybe this is the reason why General::stop does not appear? If true, is there a way to control this aspect of the main loop? Is there any way to create such a custom Mathematica session?

EDIT: Looks like my guess was correct. If we clear $MessageList after each message, then General::stop will never appear:

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

So the question remains: how to turn off the automatic clearing of $MessageList after generating the output?

+4
source share
2 answers

I have found a solution. He uses elegant hack by Todd Gayley . Here it is (of course, it should be evaluated in the core of the subordinate):

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

You can completely emulate the standard behavior of messages in the slave kernel by checking the current value of $Line and comparing it with the previous value:

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

:)

0
source

There are probably better solutions, but it seems to work. As far as I understand, all that matters is that you have a constant 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] 

NTN

+1
source

Source: https://habr.com/ru/post/1341929/


All Articles