11
$\begingroup$

I noticed that for notebook-related heads, there are usually a pair of same functions, one in System context, another in FrontEnd context. I filtered out a list of functions of this kind:

candidates = StringReplace[Names["FrontEnd`*"], "FrontEnd`" -> ""];
duplicates = Cases[Names["System`*"], Alternatives @@ candidates]

This gives a list of 84 heads appearing in both contexts.

  • So what are the purposes of these duplicate functions?
  • Is there any difference between these duplicates? (Are they used automatically by Front End to perform its functionality? For example, when clicking "Save" menu item, it is actually FrontEnd`NotebookSave[] who takes action?)
$\endgroup$
  • 4
    $\begingroup$ Oh, my. I just found this tutorial. $\endgroup$ – Naitree Dec 3 '14 at 2:49
  • 3
    $\begingroup$ You found the answer, so feel free to post it yourself! Self-answers are encouraged here. $\endgroup$ – Szabolcs Dec 3 '14 at 2:58
10
$\begingroup$

One thing that might help you when investigating in such issues is the LinkSnooper. This is a java program that can be used to set up an additional kernel configuration. When you use this kernel, you can watch all traffic between front-end and kernel.

With this, you could look what happens if you evaluate a simple 1+1

FE ---> K: EnterExpressionPacket[MakeExpression[BoxData[RowBox[{"1", "+", "1"}]], StandardForm]]
FE <--- K: OutputNamePacket["Out[14]= "]
FE <--- K: ReturnExpressionPacket[BoxData["2", StandardForm]]
FE <--- K: InputNamePacket["In[15]:= "]

The arrows show the direction of the communication. As you see, you input line is sent from the FE to the kernel for evaluation and the kernel sends back the result as a ReturnExpressionPacket.

If you use for instance CurrentValue, which is one of the functions in your list, something different happens. When we evaluate CurrentValue["MousePosition"] it should be clear from the beginning, that the kernel can never ever answer this request, because the kernel has no knowledge of the GUI, windows, or mouse pointers. The program that does know this is the FE, because it has all the notebook-windows under its control and it does all the GUI stuff. Let's check the communication:

FE ---> K: EnterExpressionPacket[MakeExpression[BoxData[RowBox[{"CurrentValue", "[", "\"MousePosition\"", "]"}]], StandardForm]]
FE <--- K: CallPacket[FrontEnd`Value[FrontEnd`CurrentValue["MousePosition"], True]]
FE ---> K: ReturnPacket[{2769, 804}]
FE <--- K: OutputNamePacket["Out[15]= "]
FE <--- K: ReturnExpressionPacket[BoxData[RowBox[{"{", RowBox[{"2769", ",", "804"}], "}"}], StandardForm]]

You see that the input is sent to the kernel, but instead of returning the result, the kernel sends the request back to the FE for evaluation. The FE returns the result in a ReturnPacket to the kernel that then sends it as ReturnExpressionPacket to the FE as result.

Therefore, instead of of call the System function CurrentValue, you could call

FrontEndExecute[FrontEnd`Value[FrontEnd`CurrentValue["MousePosition"], True]]

I remember that John Fultz explained some of those details once in chat, but I cannot find it now.

$\endgroup$
  • $\begingroup$ This is indeed a very useful tool for analyzing communications between GUI and kernel. Thanks very much for sharing it. And thanks for your detailed usage instruction. $\endgroup$ – Naitree Dec 3 '14 at 4:18
  • $\begingroup$ Is there any example how to use this to avoid calling Kernel at all? Dynamic seems to know already what it should know: Framed[1, ImageSize -> Dynamic[{.1, .1} CurrentValue["MousePosition"]] ]. So, could this be used in terms of performance tunning? $\endgroup$ – Kuba Feb 20 '15 at 10:42
8
$\begingroup$

The front-end-related operations are actually performed by Front End itself.

According to the tutorial Executing Notebook Commands Directly in the Front End:

When you execute a command like NotebookWrite[obj,data] the actual operation of inserting data into your notebook is performed in the front end. Normally, however, the kernel is needed in order to evaluate the original command, and to construct the appropriate request to send to the front end. But it turns out that the front end is set up to execute a limited collection of commands directly, without ever involving the kernel.

So those front-end-related functions in System` context can be thought like some sort of "wrapper" for the corresponding functions in FrontEnd` context, who actually performs the requested operation.

And of course, different contexts are used for distinguishing between commands to be executed in the kernel and to be executed directly in the front end.

Note that the execution of functions in FrontEnd` context is done completely by front end. Kernel is not involved at all. Thus, nothing will happen by executing the following

FrontEnd`NotebookSave[]

Because by Shift+Enter it was sent to kernel for execution. Kernel has to be told to return the operation to front end, by wrapping the command with FrontEndExecute. Thus, the following should work

FrontEndExecute[FrontEnd`NotebookSave[]]

(However, on my Ubuntu system, the code above cause Mathematica shut down immediately. Let's discuss this in another question.)

$\endgroup$
  • $\begingroup$ This is of course far after the fact but that crash is because you didn't pass a notebook to save. Front end packets are finnicky and crash the system easily. FrontEndExecute[FrontEnd`NotebookSave[EvaluationNotebook[]]] is perfectly valid. $\endgroup$ – b3m2a1 Dec 31 '16 at 1:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.