如何中止对一系列输入的评估?

时间:2011-04-11 18:20:10

标签: wolfram-mathematica mathematica-frontend

默认情况下,按 Alt + 或在评估中调用Abort[]会导致当前评估输入中止。但是当在FrontEnd中工作时,我们通常会向内核发送一系列输入。例如,如果我们在一个Cell中的不同行上键入以下三个表达式,然后按 Shift + Enter ,我们将获得无限评估:

f := CheckAbort[Pause[.1], Abort[]]
While[True, f]
While[True, f]
While[True, f]

要停止此无限评估,我们必须按 Alt + 三次。

如何在上面的示例中定义函数f,以便按 Alt + 一次将在不退出内核的情况下中止对输入的完整序列的评估

修改

我认为如果FrontEnd为MathKernel创建输入队列,它可能也会取消此队列。

3 个答案:

答案 0 :(得分:6)

Sasha建议只使用四个单元格是有效的,因为这基本上就是FrontEnd所做的事情,向内核提交了几个不同的评估。如果您坚持使用一个单元格,请将其包裹在parens(CompoundExpression)中,这会导致这四行被视为一个评估(请注意;也需要):

(
   f := CheckAbort[Pause[.1], Abort[]];
   While[True, f];
   While[True, f];
   While[True, f]
)

然后,发布的一次中止将作为一个整体中止评估。

答案 1 :(得分:1)

我找到了一种方法来做我想做的事。唯一的问题是,此刻我不知道如何检查FrontEnd是否有一些未决输入。我被迫等待1秒钟。在大多数情况下,它足以将所有未决输入发送到内核,但可能并非总是如此。

In[1]:= $new$PreRead = False;
AbortAllPendingInputs := 
  AbortProtect[If[! $new$PreRead, $new$PreRead = True;
    $TimeOfAbort = SessionTime[];
    last$PreRead = ToString[Definition[$PreRead], InputForm];
    ClearAll[$PreRead];
    $PreRead := If[TrueQ[SessionTime[] - $TimeOfAbort < 1], "",
       $new$PreRead = False;
       ClearAll[$PreRead];
       If[last$PreRead === "Null", #, 
        ToExpression[last$PreRead]; $PreRead@#]
       ] &;]];

In[3]:= f := CheckAbort[Pause[10], AbortAllPendingInputs; Abort[]]

In[4]:= While[True, f]
While[True, f]
While[True, f]

Out[4]= $Aborted

但我仍在寻找更优雅的解决方案。我认为如果FrontEnd为MathKernel创建一个输入队列,它可能也会取消这个队列。

答案 2 :(得分:1)

Alexey,请尝试使用此版本的代码并告诉我是否/何时失败:

AbortAllPendingInputs :=
  AbortProtect[
    $new$PreRead = True;
    $TimeOfAbort = SessionTime[];
    last$PreRead = $PreRead;
    $PreRead = 
      If[
         TrueQ[SessionTime[] - $TimeOfAbort < 1], 
         "",
         $new$PreRead = False; $PreRead = last$PreRead; $PreRead[#]
        ] &;
  ] /; ! TrueQ[$new$PreRead]