Как прервать оценку последовательности входов?

По умолчанию нажимаем 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 ответа

Предложение Саши просто использовать четыре ячейки является действительным, потому что это в основном то, что в любом случае делает FrontEnd, отправляя несколько отдельных оценок в ядро. Если вы настаиваете на использовании одной клетки, оберните ее в паренсе (CompoundExpression), что приводит к тому, что эти четыре строки рассматриваются как одна оценка (обратите внимание на необходимость ; тоже):

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

Затем один выданный прерывание прервет оценку в целом.

Алексей, пожалуйста, попробуйте эту версию своего кода и скажите мне, если / когда он не работает:

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]

Я нашел способ сделать то, что я хочу. Единственная проблема заключается в том, что в данный момент я не знаю, как проверить, есть ли у 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, он, вероятно, также может отменить эту очередь.

Другие вопросы по тегам