3

MathLinkスレーブカーネルで作業しているとき、正しい解析に問題がありますTextPacket。特に、そのようなパケットMessageがスレーブカーネルによって生成されたものに対応している場合、私はそれを正しく処理する方法をまったく理解していません。マスターカーネルによって生成されたかのように評価ノートに印刷する必要がありMessagesます(ただし、スレーブからのものであることを明確にするためにいくつかのマークが付いています)。TextPacketそして、 sに対応するMessagesをコマンドだけから分離する必要がありPrint[]ます。後者も正しく解析する必要があり、スレーブカーネルからのものであることを示す小さなマークを付けて評価ノートに印刷します。

何が起こるかの例を次に示します。

link = LinkLaunch[First[$CommandLine] <> " -mathlink"]
Print@LinkRead[link]
LinkWrite[link, 
 Unevaluated[EnterExpressionPacket[Print[a]; 1/0; Print[b]]]]
While[Not@MatchQ[packet = LinkRead[link], InputNamePacket[_]], 
 Print[packet]]

MessageデフォルトではMathLink、次の形式で提供されます。

TextPacket[                                 1
Power::infy: Infinite expression - encountered.
                                 0]

醜く見えます。私が見つけたそれをより良くする唯一の方法は、スレーブカーネルで評価することです

$MessagePrePrint = InputForm;

しかし、もっと簡単な解決策があるはずだと思います。特にこのように扱うとき、私はTextPacketsをHoldForm中に入れます:

TextPacket[Power::infy: Infinite expression HoldForm[0^(-1)] encountered.]

そのような文字列を。として印刷するのに適した形式に変換する方法がわかりませんMessage

PSこの質問はその質問から来ています。

4

2 に答える 2

4

与えられた質問に関連して、Todd Gayley(Wolfram Research)によって提案された素晴らしいハックを共有したいと思います。おそらく誰かにとって、それは私にとっても役立つでしょう。このハックは、問題の問題をかなりエレガントな方法で解決します。

1つの手法は、計算のためにFormatTypeをOutputFormに残し、メッセージの処理をオーバーライドして一時的にStandardFormに切り替え、メッセージ出力のみがStandardFormに返されるようにすることです。

LinkWrite[link,
        Unevaluated[EnterExpressionPacket[
            Unprotect[Message];
            Message[args___]:=
               Block[{$inMsg = True, result},
                  SetOptions[$Output, FormatType->StandardForm];
                  result = Message[args];
                  SetOptions[$Output, FormatType->OutputForm];
                  result
               ] /; !TrueQ[$inMsg]
           ]
        ]]

メッセージの内容のExpressionPacketが返されます。これをノートブックのメッセージセルとして印刷するには:

cell = Cell[<the ExpressionPacket>, "Message", "MSG"]
CellPrint[cell]

高度なアプローチ:すべてがStandardFormに印刷されます

出力以外のすべてを返すために、変数とスレーブカーネルを特別な方法でStandardForm再定義できます(次のコードはスレーブカーネルで評価する必要があります)。$Pre$Post

SetOptions[$Output, {PageWidth -> 72, FormatType -> StandardForm}];
(*$inPost is needed for tracing mode compatibility 
(could be switched on by evaluating On[] in the slave kernel) 
in which Messages are printed during evaluation of $Post.*)
$inPost = False; Protect[$inPost];
$Pre := Function[inputexpr, 
  SetOptions[$Output, FormatType -> StandardForm]; 
  Unevaluated[inputexpr], HoldAllComplete];
$Post := Function[outputexpr, 
  Block[{$inPost = True}, 
   SetOptions[$Output, FormatType -> OutputForm]; 
   Unevaluated[outputexpr]], HoldAllComplete];
Protect[$Pre]; Protect[$Post];
$inMsg = False; Protect[$inMsg];
Unprotect[Message];
Message[args___] /; $inPost := Block[{$inMsg = True},
    SetOptions[$Output, FormatType -> StandardForm];
    Message[args];
    SetOptions[$Output, FormatType -> OutputForm]] /; ! $inMsg;
Protect[Message];
于 2011-03-01T01:25:59.037 に答える
2

式は常にHoldFormで提供されますが、デフォルトの$MessagePrePrintではレンダリングされません。評価してみてください

HoldForm[1/0]

InputForm[%]

目的の動作を実現する1つの方法は、独自のボックスレンダラーを実装することです。レンダラーが処理する必要があることを確認するには、

$MessagePrePrint = ToBoxes[{##}] &

奴隷で。そのようです:

link = LinkLaunch[First[$CommandLine] <> " -mathlink"]
Print@LinkRead[link]
LinkWrite[link, 
 Unevaluated[
  EnterExpressionPacket[$MessagePrePrint = ToBoxes[{##}] &; Print[a]; 
   1/0; Print[b]]]]
While[Not@MatchQ[packet = LinkRead[link], InputNamePacket[_]], 
 Print[packet]]
于 2011-02-19T17:01:32.023 に答える