Изменение поведения General :: stop и основного цикла - PullRequest
4 голосов
/ 02 марта 2011

В документации page для General::stop мы читаем:

Это сообщение генерируется после того, как указанное сообщение было сгенерировано в третий раз inразовая оценка .

Сообщения подавляются для предотвращения избыточных или повторяющихся сообщений в длинных вычислениях.

Моя проблема заключается в том, что при работе с 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 после генерации вывода?

Ответы [ 2 ]

1 голос
/ 02 марта 2011

Возможно, есть лучшие решения, но вот одно, похоже, работает. Насколько я понимаю, все, что имеет значение, это то, что у вас есть некоторая постоянная переменная в подчиненном ядре, которая накапливает сообщения.

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]

НТН

0 голосов
/ 03 марта 2011

Я нашел решение.Он снова эксплуатирует 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;

:)

...