# What is the real default CellEvaluationFunction?

The default CellEvaluationFunction is Identity but one can quickly see that this is handled specially as an equivalent function, (# &), does not work at all the same. The sole example in the documentation uses ToExpression but this also does not work the same, returning only the output of the last line in the Input Cell:

SetOptions[EvaluationNotebook[], CellEvaluationFunction -> ToExpression]


Now in one cell:

2 + 2
5 + 7

12


My question is then: What is the real default function that correctly handles multi-line input/output including the Out[xx]= cell labels?

• Could it be MakeExpression ? The docs say "MakeExpression is used whenever boxes are supplied as input to Mathematica." – Simon Woods Jul 27 '13 at 8:49
• @Simon That's a fine guess but it's not the whole story. If you try SetOptions[EvaluationNotebook[], CellEvaluationFunction -> Function[Null, MakeExpression[##], HoldAll]] you'll get ErrorBox for output. (Not that HoldAll should not be necessary for Box form but I'm covering that as well.) Once again there appears to be something funny going on here, where Identity and MakeExpression are handled specially. I'm trying to figure out how to change the Box form then send it to the true default function for correct processing. – Mr.Wizard Jul 27 '13 at 11:44
• Ah, I see. There does appear to be special handling. Even CellEvaluationFunction :> (Null; Identity) doesn't work. – Simon Woods Jul 27 '13 at 18:16
• Based on LinkSnooper it is based on MakeExpression. The FE sends EnterExpressionPacket@MakeExpression@BoxData[..]. I get errors like you do, if I do it myself, so it must be handled specially. – Michael E2 Jul 30 '13 at 20:28
• It seems to me that what you're after will have to be done via MathLink packets. The In/Out names, for instance, are handled with InputNamePacket, OutputNamePacket. If you're lucky, a solution won't be version dependent. – Michael E2 Jul 30 '13 at 20:28

## 2 Answers

The documentations says that "CellEvaluationFunction is applied to the BoxData expression representing the input to be evaluated". So I think Identity is working normally here. See the followings:

SetOptions[EvaluationNotebook[], CellEvaluationFunction -> function]

In[1]:= 2 + 2
5 + 7

Out[1]= function[BoxData[{RowBox[{"2", "+", "2"}], RowBox[{"5", "+", "7"}]}], StandardForm]


So, if we take the BoxData structure of the above input, we can do some tests:

Identity[BoxData[{RowBox[{"2", "+", "2"}], RowBox[{"5", "+", "7"}]}]]
(* BoxData[{RowBox[{"2", "+", "2"}], RowBox[{"5", "+", "7"}]}] *)

# &[BoxData[{RowBox[{"2", "+", "2"}], RowBox[{"5", "+", "7"}]}]]
(* BoxData[{RowBox[{"2", "+", "2"}], RowBox[{"5", "+", "7"}]}] *)


So, Identity sends the expression BoxData[{RowBox[{"2", "+", "2"}], RowBox[{"5", "+", "7"}]}] to the kernel and it produces the two lines of output with different Out[number] like

In[1]:= 2 + 2
5 + 7


On the other hand, ToExpression is declared as working on strings and boxes interpreting them as inputs, that means if set as CellEvaluationFunction it manipulates the box structure before to send it to the kernel:

ToExpression[BoxData[{RowBox[{"2", "+", "2"}], RowBox[{"5", "+", "7"}]}]]

12


So, I guess Identity is actually the CellEvaluationFunction's default. The only think I cannot understand is why when we set an arbitrary function (like in my first example) as CellEvaluationFunction, the result includes the StandardForm as second argument (function[BoxData[{RowBox[{"2", "+", "2"}], RowBox[{"5", "+", "7"}]}], StandardForm]) while Identity doesn't accept a second argument and, indeed, it's not used.

EDIT

Using (#&) it fails but using (#)& it works:

SetOptions[EvaluationNotebook[], CellEvaluationFunction -> (# &)]

In[78]:= 2 + 2

Out[78]= BoxData[RowBox[{"2", "+", "2"}]]

In[79]:= 2 + 2
5 + 7

Out[79]= BoxData[{RowBox[{"2", "+", "2"}], RowBox[{"5", "+", "7"}]}]

SetOptions[EvaluationNotebook[], CellEvaluationFunction -> (#) &]

In[74]:= 2 + 2

Out[74]= 4

In[75]:= 2 + 2
5 + 7

Out[75]= 4

Out[76]= 12

• Bob, thanks for responding. I fear I haven't phrased this question adequately. I pointed out that using (# &) in place of Identity causes this to fail. The thing is I want to use CellEvaluationFunction to modify the Box data (like $PreRead), then send it along to the kernel as usual. So far everything I've tried has failed. Sure, I can get a kind of output and display it with CellPrint but it doesn't have the Out[xx]= labels and is a hack. – Mr.Wizard Jul 27 '13 at 12:19 • Regarding your update, I'm sorry to inform you that you're being fooled by evaluation order. If you use these methods you will see that the entirety of CellEvaluationFunction -> (#) & is the Function, which by itself is inert, therefore you are not making an Option setting at all. – Mr.Wizard Jul 27 '13 at 13:46 • You are right, I was indeed surprised of the difference. I'm still looking at some alternatives, to no avail. – bobknight Jul 27 '13 at 13:58 • @Mr.Wizard, the labels is just a matter of using CellLabel -> ($Line /. l_ :> ToString@Unevaluated@Out@l). If you care about getting the main loop split for every line, you can also code it but, that's just hacking down the hack. I wouldn't know how to programatically "really" split the main loop. Other than using other hacks like an invisible notebook and NotebookEvaluate, hummm – Rojo Jul 28 '13 at 3:00
• The main loop splitting seeeeems to me happens before the CellEvaluationFunction gets evaluated by the kernel, so I don't have high hopes for an unhacky clean solution. But who knows – Rojo Jul 28 '13 at 3:06

I don't think you can modify the CellEvaluationFunction to achieve your goal. On the other hand, you can modify MakeExpression instead, as MakeExpression is called on each line of input. So:

MakeExpression[x_,form_] /; !TrueQ@flag && TrueQ@override := Block[{flag=True},
List/@MakeExpression[x,form]
]


The above code will add a List wrapper to every evaluated expression, but only when the override variable is True:

override = True;
2+2
5+7


{4}

{12}

Setting override back to False will restore the normal behavior:

override = False;
2+2
5+7


{Null}

4

12