3
$\begingroup$

This is a followup of "How to check for Mathematica’s definition of XY?, a question by uli on how to access the definition of a built-in symbol. That question focused on Binomial but mentioned that it could be good to read the source for TraditionalForm or TeXForm in order to tweak it or build on top of it.

So my question is, how can I find the transformation rules involved in making a TraditionalForm? Removing its attribute ReadProtected is not enough to see the actual transformations as the code seems to be hidden in some further indirection.

$\endgroup$
3
$\begingroup$

Information[TraditionalForm] indicates that TraditionalForm is ReadProtected (and Protected). We can remove that with ClearAttributes[TraditionalForm, {Protected, ReadProtected}].

Then Information[TraditionalForm] shows only a few definitions: besides some for dots and for InactiveDTraditional, there are definitions for use within MakeExpression or MakeBoxes,

MakeBoxes[BoxForm`apat$_,TraditionalForm]^:=BoxForm`BoxFormAutoLoad[
  MakeBoxes,
  BoxForm`apat$,
  TraditionalForm,
  "Typeset`TraditionalForm`",
  {{TraditionalForm,MakeBoxes},{TraditionalForm,MakeExpression}}]

MakeExpression[BoxForm`apat$_,TraditionalForm]^:=BoxForm`BoxFormAutoLoad[
  MakeExpression,
  BoxForm`apat$,
  TraditionalForm,
  "Typeset`TraditionalForm`",
  {{TraditionalForm,MakeBoxes},{TraditionalForm,MakeExpression}}]

Digging a bit, BoxForm`BoxFormAutoLoad loads the file System`Private`$SystemFileDir<>System`Dump`fixfile[#4]<>"x" then the definition that called BoxForm`BoxFormAutoLoad is UnSet to avoid loading the file twice. In our case, #4 is "Typeset`TraditionalForm`", leading on my system to loading the .mx file

C:\Program Files\Wolfram Research\Mathematica\10.0\SystemFiles\Kernel\SystemResources\Windows-x86-64\Typeset\TraditionalForm.mx

Files with the extension .mx are binary files that contain definitions of some symbols and can be read with Get. Unfortunately, Trace[Get[filename]] does not show what is going on when Mathematica reads the file. More elaborate tricks redefining Set or SetDelayed using code from "Overriding a built-in function with custom coded procedures" do not help. As far as I can tell, when reading an .mx file, Mathematica directly injects the stored definitions without invoking Set or SetDelayed. So we cannot see rules as they are added.

After failing in that direction (and staring for an hour at the irrelevant Trace[Import[filename]]), I realized we can simply look at Information[TraditionalForm] again. It now gives a rather lengthy output: 64 FormatValues. For instance, a simple rule

HoldPattern[MakeBoxes[Function[x_, y_], TraditionalForm]] :>
  RowBox[{Parenthesize[x, TraditionalForm, Set, Left],
    "\[Function]",
    Parenthesize[y, TraditionalForm, Set, Right]}]

defining how a function f:x->y should be converted to boxes. (There are rules with MakeExpression which do the opposite transformation from boxes to an expression.) However, this is not the end, as there are still some rules which call BoxForm`BoxFormAutoLoad. For such rules, Mathematica loads yet another .mx file and the only way to know its contents is to load it and take another look at FormatValues[TraditionalForm].

Depending on our aim, it can be worth loading all files

Get /@ FileNames["*.mx", 
   DirectoryName[
    System`Private`$SystemFileDir <> 
     System`Dump`fixfile["Typeset`TraditionalForm`"] <> "x"]];

However, this does not run the code in BoxForm`BoxFormAutoLoad that removes definitions involving it. One way that seems to work is to TagUnset the FormatValues that involve BoxForm`BoxFormAutoLoad, but I wouldn't trust that in production code.

Unprotect[TraditionalForm];
Scan[(If[Not[FreeQ[Hold[#[[2]]], BoxForm`BoxFormAutoLoad]],
     TagUnset[TraditionalForm, 
      Evaluate[(#[[1]] /. Verbatim[HoldPattern][x_] :> Hold[x] /. 
          Verbatim[HoldPattern][y_] :> y /. Hold :> HoldPattern)]]]) &,
  FormatValues[TraditionalForm]];

Sorry for the ugly code as the second argument of TagUnset: there, #[[1]] is the left-hand side of a rule, but it takes the form HoldPattern[somename:HoldPattern[somepattern___]] and I had to remove the inner HoldPattern.

$\endgroup$
  • $\begingroup$ Perhaps you will benefit from the function PrintDefinitions from the package GeneralUtilities` . That is, PrintDefinitions@TraditionalForm $\endgroup$ – Jacob Akkerboom May 5 '16 at 10:51

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.