3

MathLink使用从内核时,我遇到了正确解析TextPackets 的问题。特别是当这样的数据包对应于Message从内核生成的时,我根本不明白如何正确处理它。我需要Messages将它们打印在评估笔记本中,就好像它们是由主内核生成的一样(但有一些标记以明确它来自从属内核)。而且我需要将TextPackets 对应的Messages 与 just toPrint[]命令分开。后者我也需要正确解析,将它们打印在评估笔记本中,并带有一点标记,表明它来自从内核。

下面是一个例子:

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)提出的与给定问题相关的好技巧。也许对某些人来说,它对我也很有用。这个hack以相当优雅的方式解决了这个问题。

一种技术是将 FormatType 保留在 OutputForm 进行计算,但覆盖 Message 的处理以临时切换到 StandardForm,以便只有 Message 输出以 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[%]

实现所需行为的一种方法是实现自己的框渲染器。要查看渲染器必须处理,请设置

$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 回答