Как прервать оценку последовательности входов?
По умолчанию нажимаем 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, он, вероятно, также может отменить эту очередь.